@theihtisham/agent-shadow-brain 5.1.1 → 6.0.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 +355 -1095
- package/dist/adapters/copilot.d.ts +14 -0
- package/dist/adapters/copilot.d.ts.map +1 -0
- package/dist/adapters/copilot.js +93 -0
- package/dist/adapters/copilot.js.map +1 -0
- package/dist/adapters/cursor.d.ts +13 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +96 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/index.d.ts +4 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +7 -3
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/windsurf.d.ts +14 -0
- package/dist/adapters/windsurf.d.ts.map +1 -0
- package/dist/adapters/windsurf.js +107 -0
- package/dist/adapters/windsurf.js.map +1 -0
- package/dist/brain/agent-firewall.d.ts +7 -0
- package/dist/brain/agent-firewall.d.ts.map +1 -0
- package/dist/brain/agent-firewall.js +152 -0
- package/dist/brain/agent-firewall.js.map +1 -0
- package/dist/brain/agent-handoff.d.ts +19 -0
- package/dist/brain/agent-handoff.d.ts.map +1 -0
- package/dist/brain/agent-handoff.js +127 -0
- package/dist/brain/agent-handoff.js.map +1 -0
- package/dist/brain/air-gap.d.ts +23 -0
- package/dist/brain/air-gap.d.ts.map +1 -0
- package/dist/brain/air-gap.js +137 -0
- package/dist/brain/air-gap.js.map +1 -0
- package/dist/brain/attention-heatmap.d.ts +24 -0
- package/dist/brain/attention-heatmap.d.ts.map +1 -0
- package/dist/brain/attention-heatmap.js +108 -0
- package/dist/brain/attention-heatmap.js.map +1 -0
- package/dist/brain/auto-setup.js +19 -14
- package/dist/brain/auto-setup.js.map +1 -1
- package/dist/brain/auto-update.js +1 -1
- package/dist/brain/brain-chat.d.ts +42 -0
- package/dist/brain/brain-chat.d.ts.map +1 -0
- package/dist/brain/brain-chat.js +162 -0
- package/dist/brain/brain-chat.js.map +1 -0
- package/dist/brain/brain-encryption.d.ts +14 -0
- package/dist/brain/brain-encryption.d.ts.map +1 -0
- package/dist/brain/brain-encryption.js +68 -0
- package/dist/brain/brain-encryption.js.map +1 -0
- package/dist/brain/brain-exchange.d.ts +30 -0
- package/dist/brain/brain-exchange.d.ts.map +1 -0
- package/dist/brain/brain-exchange.js +106 -0
- package/dist/brain/brain-exchange.js.map +1 -0
- package/dist/brain/brain-garden.d.ts +18 -0
- package/dist/brain/brain-garden.d.ts.map +1 -0
- package/dist/brain/brain-garden.js +81 -0
- package/dist/brain/brain-garden.js.map +1 -0
- package/dist/brain/brain-portability.js +1 -1
- package/dist/brain/branch-brain.d.ts +23 -0
- package/dist/brain/branch-brain.d.ts.map +1 -0
- package/dist/brain/branch-brain.js +159 -0
- package/dist/brain/branch-brain.js.map +1 -0
- package/dist/brain/calibration-monitor.d.ts +20 -0
- package/dist/brain/calibration-monitor.d.ts.map +1 -0
- package/dist/brain/calibration-monitor.js +144 -0
- package/dist/brain/calibration-monitor.js.map +1 -0
- package/dist/brain/causal-chains.d.ts +37 -0
- package/dist/brain/causal-chains.d.ts.map +1 -0
- package/dist/brain/causal-chains.js +250 -0
- package/dist/brain/causal-chains.js.map +1 -0
- package/dist/brain/collision-detective.d.ts +32 -0
- package/dist/brain/collision-detective.d.ts.map +1 -0
- package/dist/brain/collision-detective.js +233 -0
- package/dist/brain/collision-detective.js.map +1 -0
- package/dist/brain/cost-aware-spawner.d.ts +7 -0
- package/dist/brain/cost-aware-spawner.d.ts.map +1 -0
- package/dist/brain/cost-aware-spawner.js +77 -0
- package/dist/brain/cost-aware-spawner.js.map +1 -0
- package/dist/brain/dream-engine.d.ts +35 -0
- package/dist/brain/dream-engine.d.ts.map +1 -0
- package/dist/brain/dream-engine.js +273 -0
- package/dist/brain/dream-engine.js.map +1 -0
- package/dist/brain/embeddings.d.ts +27 -0
- package/dist/brain/embeddings.d.ts.map +1 -0
- package/dist/brain/embeddings.js +175 -0
- package/dist/brain/embeddings.js.map +1 -0
- package/dist/brain/forgetting-curve.d.ts +21 -0
- package/dist/brain/forgetting-curve.d.ts.map +1 -0
- package/dist/brain/forgetting-curve.js +174 -0
- package/dist/brain/forgetting-curve.js.map +1 -0
- package/dist/brain/formal-verification-bridge.d.ts +26 -0
- package/dist/brain/formal-verification-bridge.d.ts.map +1 -0
- package/dist/brain/formal-verification-bridge.js +219 -0
- package/dist/brain/formal-verification-bridge.js.map +1 -0
- package/dist/brain/global-brain.d.ts +63 -0
- package/dist/brain/global-brain.d.ts.map +1 -0
- package/dist/brain/global-brain.js +348 -0
- package/dist/brain/global-brain.js.map +1 -0
- package/dist/brain/hallucination-quarantine.d.ts +26 -0
- package/dist/brain/hallucination-quarantine.d.ts.map +1 -0
- package/dist/brain/hallucination-quarantine.js +135 -0
- package/dist/brain/hallucination-quarantine.js.map +1 -0
- package/dist/brain/hive-accelerator.d.ts +39 -0
- package/dist/brain/hive-accelerator.d.ts.map +1 -0
- package/dist/brain/hive-accelerator.js +152 -0
- package/dist/brain/hive-accelerator.js.map +1 -0
- package/dist/brain/json-output.d.ts +26 -0
- package/dist/brain/json-output.d.ts.map +1 -0
- package/dist/brain/json-output.js +112 -0
- package/dist/brain/json-output.js.map +1 -0
- package/dist/brain/l0-cache.d.ts +40 -0
- package/dist/brain/l0-cache.d.ts.map +1 -0
- package/dist/brain/l0-cache.js +176 -0
- package/dist/brain/l0-cache.js.map +1 -0
- package/dist/brain/local-llm.d.ts +20 -0
- package/dist/brain/local-llm.d.ts.map +1 -0
- package/dist/brain/local-llm.js +132 -0
- package/dist/brain/local-llm.js.map +1 -0
- package/dist/brain/mcp-server.d.ts +44 -0
- package/dist/brain/mcp-server.d.ts.map +1 -1
- package/dist/brain/mcp-server.js +486 -12
- package/dist/brain/mcp-server.js.map +1 -1
- package/dist/brain/model-registry.d.ts +96 -0
- package/dist/brain/model-registry.d.ts.map +1 -0
- package/dist/brain/model-registry.js +585 -0
- package/dist/brain/model-registry.js.map +1 -0
- package/dist/brain/orchestrator.js +1 -1
- package/dist/brain/pr-auto-review.d.ts +17 -0
- package/dist/brain/pr-auto-review.d.ts.map +1 -0
- package/dist/brain/pr-auto-review.js +73 -0
- package/dist/brain/pr-auto-review.js.map +1 -0
- package/dist/brain/pre-mortem.d.ts +21 -0
- package/dist/brain/pre-mortem.d.ts.map +1 -0
- package/dist/brain/pre-mortem.js +210 -0
- package/dist/brain/pre-mortem.js.map +1 -0
- package/dist/brain/prompt-cache.d.ts +54 -0
- package/dist/brain/prompt-cache.d.ts.map +1 -0
- package/dist/brain/prompt-cache.js +105 -0
- package/dist/brain/prompt-cache.js.map +1 -0
- package/dist/brain/reputation-ledger.d.ts +42 -0
- package/dist/brain/reputation-ledger.d.ts.map +1 -0
- package/dist/brain/reputation-ledger.js +326 -0
- package/dist/brain/reputation-ledger.js.map +1 -0
- package/dist/brain/session-hooks.d.ts +47 -0
- package/dist/brain/session-hooks.d.ts.map +1 -0
- package/dist/brain/session-hooks.js +706 -0
- package/dist/brain/session-hooks.js.map +1 -0
- package/dist/brain/subagent-bridge.d.ts +46 -0
- package/dist/brain/subagent-bridge.d.ts.map +1 -0
- package/dist/brain/subagent-bridge.js +364 -0
- package/dist/brain/subagent-bridge.js.map +1 -0
- package/dist/brain/subconscious.d.ts +34 -0
- package/dist/brain/subconscious.d.ts.map +1 -0
- package/dist/brain/subconscious.js +275 -0
- package/dist/brain/subconscious.js.map +1 -0
- package/dist/brain/swarm-debate.d.ts +22 -0
- package/dist/brain/swarm-debate.d.ts.map +1 -0
- package/dist/brain/swarm-debate.js +134 -0
- package/dist/brain/swarm-debate.js.map +1 -0
- package/dist/brain/team-brain-sync.d.ts +22 -0
- package/dist/brain/team-brain-sync.d.ts.map +1 -0
- package/dist/brain/team-brain-sync.js +132 -0
- package/dist/brain/team-brain-sync.js.map +1 -0
- package/dist/brain/token-economy.d.ts +25 -0
- package/dist/brain/token-economy.d.ts.map +1 -0
- package/dist/brain/token-economy.js +216 -0
- package/dist/brain/token-economy.js.map +1 -0
- package/dist/brain/voice-mode.d.ts +15 -0
- package/dist/brain/voice-mode.d.ts.map +1 -0
- package/dist/brain/voice-mode.js +97 -0
- package/dist/brain/voice-mode.js.map +1 -0
- package/dist/cli.js +990 -6
- package/dist/cli.js.map +1 -1
- package/dist/dashboard/server.d.ts +6 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +1118 -368
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/v6-dashboard-html.d.ts +2 -0
- package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -0
- package/dist/dashboard/v6-dashboard-html.js +2474 -0
- package/dist/dashboard/v6-dashboard-html.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +644 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +77 -12
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/brain/auto-update.ts — Check for Shadow Brain updates
|
|
2
2
|
import * as https from 'https';
|
|
3
|
-
const CURRENT_VERSION = '
|
|
3
|
+
const CURRENT_VERSION = '5.2.0';
|
|
4
4
|
const PACKAGE_NAME = '@theihtisham/agent-shadow-brain';
|
|
5
5
|
export async function checkForUpdate() {
|
|
6
6
|
return new Promise((resolve) => {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface BrainChatCitation {
|
|
2
|
+
memoryId: string;
|
|
3
|
+
content: string;
|
|
4
|
+
category: string;
|
|
5
|
+
agent: string;
|
|
6
|
+
score: number;
|
|
7
|
+
}
|
|
8
|
+
export interface BrainChatTurn {
|
|
9
|
+
id: string;
|
|
10
|
+
conversationId: string;
|
|
11
|
+
role: 'user' | 'assistant';
|
|
12
|
+
content: string;
|
|
13
|
+
citations?: BrainChatCitation[];
|
|
14
|
+
provider?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
createdAt: Date;
|
|
17
|
+
tokensUsed?: number;
|
|
18
|
+
cached?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class BrainChat {
|
|
21
|
+
private history;
|
|
22
|
+
private initialized;
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
ask(question: string, opts?: {
|
|
25
|
+
conversationId?: string;
|
|
26
|
+
maxCitations?: number;
|
|
27
|
+
projectDir?: string;
|
|
28
|
+
}): Promise<BrainChatTurn>;
|
|
29
|
+
listConversations(): Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
turnCount: number;
|
|
32
|
+
lastActive: Date;
|
|
33
|
+
preview: string;
|
|
34
|
+
}>;
|
|
35
|
+
getConversation(id: string): BrainChatTurn[];
|
|
36
|
+
clearConversation(id: string): Promise<boolean>;
|
|
37
|
+
clearAll(): Promise<void>;
|
|
38
|
+
private persist;
|
|
39
|
+
}
|
|
40
|
+
export declare function getBrainChat(): BrainChat;
|
|
41
|
+
export declare function resetBrainChatForTests(): void;
|
|
42
|
+
//# sourceMappingURL=brain-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-chat.d.ts","sourceRoot":"","sources":["../../src/brain/brain-chat.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAOD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,WAAW,CAAS;IAEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAcrB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IA6FvI,iBAAiB,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAShG,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,EAAE;IAItC,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM/C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAKjB,OAAO;CAWtB;AAGD,wBAAgB,YAAY,IAAI,SAAS,CAGxC;AACD,wBAAgB,sBAAsB,IAAI,IAAI,CAAsB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// src/brain/brain-chat.ts — Chat with Your Brain (contextual RAG)
|
|
2
|
+
// v6.0.0 — Hive Mind Edition
|
|
3
|
+
//
|
|
4
|
+
// Conversational interface over the global brain. Retrieves the most relevant
|
|
5
|
+
// memories via semantic search, constructs a citation-aware prompt, sends it
|
|
6
|
+
// through ModelRegistry, and returns the answer + cited memories.
|
|
7
|
+
//
|
|
8
|
+
// The response is also written back to the brain as a new memory (category:
|
|
9
|
+
// "chat-query") so the conversation history becomes queryable.
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import * as os from 'os';
|
|
13
|
+
import * as crypto from 'crypto';
|
|
14
|
+
import { getGlobalBrain } from './global-brain.js';
|
|
15
|
+
import { getEmbeddings } from './embeddings.js';
|
|
16
|
+
import { getModelRegistry } from './model-registry.js';
|
|
17
|
+
import { getPromptCache } from './prompt-cache.js';
|
|
18
|
+
const HIST_PATH = path.join(os.homedir(), '.shadow-brain', 'chat-history.json');
|
|
19
|
+
export class BrainChat {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.history = new Map();
|
|
22
|
+
this.initialized = false;
|
|
23
|
+
}
|
|
24
|
+
async init() {
|
|
25
|
+
if (this.initialized)
|
|
26
|
+
return;
|
|
27
|
+
fs.mkdirSync(path.dirname(HIST_PATH), { recursive: true });
|
|
28
|
+
if (fs.existsSync(HIST_PATH)) {
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(fs.readFileSync(HIST_PATH, 'utf-8'));
|
|
31
|
+
for (const [id, turns] of Object.entries(parsed.conversations ?? {})) {
|
|
32
|
+
this.history.set(id, turns.map(t => ({ ...t, createdAt: new Date(t.createdAt) })));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch { /* skip */ }
|
|
36
|
+
}
|
|
37
|
+
this.initialized = true;
|
|
38
|
+
}
|
|
39
|
+
async ask(question, opts = {}) {
|
|
40
|
+
await this.init();
|
|
41
|
+
const brain = getGlobalBrain();
|
|
42
|
+
await brain.init();
|
|
43
|
+
const emb = getEmbeddings();
|
|
44
|
+
await emb.init();
|
|
45
|
+
const registry = getModelRegistry();
|
|
46
|
+
await registry.init();
|
|
47
|
+
const cache = getPromptCache();
|
|
48
|
+
const conversationId = opts.conversationId || `conv-${crypto.randomBytes(6).toString('hex')}`;
|
|
49
|
+
const turns = this.history.get(conversationId) ?? [];
|
|
50
|
+
const maxCitations = opts.maxCitations ?? 6;
|
|
51
|
+
// Record user turn
|
|
52
|
+
const userTurn = {
|
|
53
|
+
id: 'turn-' + crypto.randomBytes(4).toString('hex'),
|
|
54
|
+
conversationId, role: 'user', content: question, createdAt: new Date(),
|
|
55
|
+
};
|
|
56
|
+
turns.push(userTurn);
|
|
57
|
+
// Retrieve relevant memories via semantic search
|
|
58
|
+
const candidates = brain.recall({ limit: 200, minImportance: 0.2 });
|
|
59
|
+
const searchables = candidates.map(e => ({ id: e.id, text: `${e.category}: ${e.content}` }));
|
|
60
|
+
const ranked = await emb.semanticSearch(question, searchables, maxCitations);
|
|
61
|
+
const citations = [];
|
|
62
|
+
for (const r of ranked) {
|
|
63
|
+
const entry = candidates.find(e => e.id === r.id);
|
|
64
|
+
if (!entry)
|
|
65
|
+
continue;
|
|
66
|
+
citations.push({
|
|
67
|
+
memoryId: entry.id,
|
|
68
|
+
content: entry.content,
|
|
69
|
+
category: entry.category,
|
|
70
|
+
agent: String(entry.agentTool),
|
|
71
|
+
score: +r.score.toFixed(4),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const citationBlock = citations.length
|
|
75
|
+
? citations.map((c, i) => `[${i + 1}] (${c.agent}/${c.category}) ${c.content.slice(0, 260)}`).join('\n')
|
|
76
|
+
: '(no relevant memories found)';
|
|
77
|
+
const system = `You are Shadow Brain — the Hive Mind assistant for a developer's AI agents.
|
|
78
|
+
You answer from the brain's memory when possible. Cite sources with [N] matching the numbered list.
|
|
79
|
+
Be direct and terse. Never invent memories that aren't listed.`;
|
|
80
|
+
const recentContext = turns.slice(-6, -1).map(t => `${t.role.toUpperCase()}: ${t.content}`).join('\n');
|
|
81
|
+
const prompt = [
|
|
82
|
+
recentContext ? 'Conversation so far:\n' + recentContext + '\n' : '',
|
|
83
|
+
'Relevant brain memories:\n' + citationBlock,
|
|
84
|
+
'\nUser question:\n' + question,
|
|
85
|
+
'\nAnswer, citing memories like [1] [2] when you use them:',
|
|
86
|
+
].filter(Boolean).join('\n');
|
|
87
|
+
const generate = () => registry.generate(prompt, { system, featureName: 'brain-chat', maxTokens: 600 });
|
|
88
|
+
const start = Date.now();
|
|
89
|
+
const response = await cache.wrap({ prompt, system, model: 'lead', provider: 'lead', estimatedTokens: Math.ceil(prompt.length / 4) + 400, estimatedCostUsd: 0.004 }, generate);
|
|
90
|
+
const asstTurn = {
|
|
91
|
+
id: 'turn-' + crypto.randomBytes(4).toString('hex'),
|
|
92
|
+
conversationId,
|
|
93
|
+
role: 'assistant',
|
|
94
|
+
content: response.text || '(no response)',
|
|
95
|
+
citations,
|
|
96
|
+
provider: response.provider,
|
|
97
|
+
model: response.model,
|
|
98
|
+
createdAt: new Date(),
|
|
99
|
+
tokensUsed: (response.inputTokens ?? 0) + (response.outputTokens ?? 0),
|
|
100
|
+
};
|
|
101
|
+
turns.push(asstTurn);
|
|
102
|
+
this.history.set(conversationId, turns);
|
|
103
|
+
// Also store as a brain memory so future chats can find past conversations
|
|
104
|
+
try {
|
|
105
|
+
const projectId = 'brain-chat';
|
|
106
|
+
brain.writeSync({
|
|
107
|
+
projectId, projectName: 'brain-chat',
|
|
108
|
+
agentTool: 'claude-code',
|
|
109
|
+
category: 'chat-answer',
|
|
110
|
+
content: `Q: ${question.slice(0, 220)}\nA: ${(response.text || '').slice(0, 380)}`,
|
|
111
|
+
importance: 0.45,
|
|
112
|
+
metadata: { conversationId, provider: response.provider, model: response.model, citationCount: citations.length },
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch { /* non-fatal */ }
|
|
116
|
+
// Record ms timing for observability
|
|
117
|
+
asstTurn.ms = Date.now() - start;
|
|
118
|
+
this.persist().catch(() => { });
|
|
119
|
+
return asstTurn;
|
|
120
|
+
}
|
|
121
|
+
listConversations() {
|
|
122
|
+
return Array.from(this.history.entries()).map(([id, turns]) => ({
|
|
123
|
+
id,
|
|
124
|
+
turnCount: turns.length,
|
|
125
|
+
lastActive: turns[turns.length - 1]?.createdAt ?? new Date(),
|
|
126
|
+
preview: turns[0]?.content.slice(0, 80) ?? '',
|
|
127
|
+
})).sort((a, b) => b.lastActive.getTime() - a.lastActive.getTime());
|
|
128
|
+
}
|
|
129
|
+
getConversation(id) {
|
|
130
|
+
return this.history.get(id) ?? [];
|
|
131
|
+
}
|
|
132
|
+
async clearConversation(id) {
|
|
133
|
+
const ok = this.history.delete(id);
|
|
134
|
+
if (ok)
|
|
135
|
+
await this.persist();
|
|
136
|
+
return ok;
|
|
137
|
+
}
|
|
138
|
+
async clearAll() {
|
|
139
|
+
this.history.clear();
|
|
140
|
+
await this.persist();
|
|
141
|
+
}
|
|
142
|
+
async persist() {
|
|
143
|
+
try {
|
|
144
|
+
const shape = {
|
|
145
|
+
schemaVersion: 1,
|
|
146
|
+
conversations: Object.fromEntries(this.history.entries()),
|
|
147
|
+
};
|
|
148
|
+
const tmp = HIST_PATH + '.tmp';
|
|
149
|
+
fs.writeFileSync(tmp, JSON.stringify(shape, null, 2));
|
|
150
|
+
fs.renameSync(tmp, HIST_PATH);
|
|
151
|
+
}
|
|
152
|
+
catch { /* non-fatal */ }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
let _instance = null;
|
|
156
|
+
export function getBrainChat() {
|
|
157
|
+
if (!_instance)
|
|
158
|
+
_instance = new BrainChat();
|
|
159
|
+
return _instance;
|
|
160
|
+
}
|
|
161
|
+
export function resetBrainChatForTests() { _instance = null; }
|
|
162
|
+
//# sourceMappingURL=brain-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-chat.js","sourceRoot":"","sources":["../../src/brain/brain-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EncryptedBrainFile } from '../types.js';
|
|
2
|
+
export declare class BrainEncryption {
|
|
3
|
+
/** Derive a 32-byte key from a passphrase + salt (scrypt). */
|
|
4
|
+
static deriveKey(passphrase: string, salt: Buffer): Buffer;
|
|
5
|
+
/** Encrypt plaintext bytes with a passphrase. Returns a JSON-friendly structure. */
|
|
6
|
+
static encrypt(plaintext: string | Buffer, passphrase: string): EncryptedBrainFile;
|
|
7
|
+
/** Decrypt an encrypted file. Throws if passphrase is wrong or data tampered. */
|
|
8
|
+
static decrypt(encrypted: EncryptedBrainFile, passphrase: string): Buffer;
|
|
9
|
+
/** Encrypt a file path in-place (atomic). */
|
|
10
|
+
static encryptFile(filePath: string, passphrase: string): Promise<void>;
|
|
11
|
+
/** Decrypt a .enc file back to plaintext. */
|
|
12
|
+
static decryptFile(encPath: string, passphrase: string, outPath?: string): Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=brain-encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-encryption.d.ts","sourceRoot":"","sources":["../../src/brain/brain-encryption.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAOjD,qBAAa,eAAe;IAC1B,8DAA8D;IAC9D,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAI1D,oFAAoF;IACpF,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB;IAmBlF,iFAAiF;IACjF,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;IAWzE,6CAA6C;WAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7E,6CAA6C;WAChC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAQjG"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/brain/brain-encryption.ts — ChaCha20-Poly1305 encrypted brain-at-rest
|
|
2
|
+
// v6.0.0 — Hive Mind Edition
|
|
3
|
+
//
|
|
4
|
+
// Encrypts the global brain file on disk with ChaCha20-Poly1305 AEAD.
|
|
5
|
+
// Key is derived from a user passphrase (or OS-keychain-managed value).
|
|
6
|
+
//
|
|
7
|
+
// Node 22 supports chacha20-poly1305 natively via crypto.createCipheriv.
|
|
8
|
+
import * as crypto from 'crypto';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
const CIPHER = 'chacha20-poly1305';
|
|
11
|
+
const KEY_BYTES = 32;
|
|
12
|
+
const NONCE_BYTES = 12;
|
|
13
|
+
const SALT_BYTES = 16;
|
|
14
|
+
export class BrainEncryption {
|
|
15
|
+
/** Derive a 32-byte key from a passphrase + salt (scrypt). */
|
|
16
|
+
static deriveKey(passphrase, salt) {
|
|
17
|
+
return crypto.scryptSync(passphrase, salt, KEY_BYTES, { N: 16384, r: 8, p: 1, maxmem: 64 * 1024 * 1024 });
|
|
18
|
+
}
|
|
19
|
+
/** Encrypt plaintext bytes with a passphrase. Returns a JSON-friendly structure. */
|
|
20
|
+
static encrypt(plaintext, passphrase) {
|
|
21
|
+
const salt = crypto.randomBytes(SALT_BYTES);
|
|
22
|
+
const nonce = crypto.randomBytes(NONCE_BYTES);
|
|
23
|
+
const key = BrainEncryption.deriveKey(passphrase, salt);
|
|
24
|
+
const cipher = crypto.createCipheriv(CIPHER, key, nonce, { authTagLength: 16 });
|
|
25
|
+
const buf = typeof plaintext === 'string' ? Buffer.from(plaintext, 'utf-8') : plaintext;
|
|
26
|
+
const encrypted = Buffer.concat([cipher.update(buf), cipher.final()]);
|
|
27
|
+
const authTag = cipher.getAuthTag();
|
|
28
|
+
return {
|
|
29
|
+
schemaVersion: 1,
|
|
30
|
+
cipher: CIPHER,
|
|
31
|
+
salt: salt.toString('base64'),
|
|
32
|
+
nonce: nonce.toString('base64'),
|
|
33
|
+
ciphertext: encrypted.toString('base64'),
|
|
34
|
+
authTag: authTag.toString('base64'),
|
|
35
|
+
createdAt: new Date().toISOString(),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Decrypt an encrypted file. Throws if passphrase is wrong or data tampered. */
|
|
39
|
+
static decrypt(encrypted, passphrase) {
|
|
40
|
+
const salt = Buffer.from(encrypted.salt, 'base64');
|
|
41
|
+
const nonce = Buffer.from(encrypted.nonce, 'base64');
|
|
42
|
+
const authTag = Buffer.from(encrypted.authTag, 'base64');
|
|
43
|
+
const ciphertext = Buffer.from(encrypted.ciphertext, 'base64');
|
|
44
|
+
const key = BrainEncryption.deriveKey(passphrase, salt);
|
|
45
|
+
const decipher = crypto.createDecipheriv(CIPHER, key, nonce, { authTagLength: 16 });
|
|
46
|
+
decipher.setAuthTag(authTag);
|
|
47
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
48
|
+
}
|
|
49
|
+
/** Encrypt a file path in-place (atomic). */
|
|
50
|
+
static async encryptFile(filePath, passphrase) {
|
|
51
|
+
const plaintext = fs.readFileSync(filePath);
|
|
52
|
+
const encrypted = BrainEncryption.encrypt(plaintext, passphrase);
|
|
53
|
+
const tmp = filePath + '.enc.tmp';
|
|
54
|
+
fs.writeFileSync(tmp, JSON.stringify(encrypted));
|
|
55
|
+
fs.renameSync(tmp, filePath + '.enc');
|
|
56
|
+
fs.unlinkSync(filePath);
|
|
57
|
+
}
|
|
58
|
+
/** Decrypt a .enc file back to plaintext. */
|
|
59
|
+
static async decryptFile(encPath, passphrase, outPath) {
|
|
60
|
+
const raw = fs.readFileSync(encPath, 'utf-8');
|
|
61
|
+
const parsed = JSON.parse(raw);
|
|
62
|
+
const plain = BrainEncryption.decrypt(parsed, passphrase);
|
|
63
|
+
const target = outPath ?? encPath.replace(/\.enc$/, '');
|
|
64
|
+
fs.writeFileSync(target, plain);
|
|
65
|
+
return target;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=brain-encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-encryption.js","sourceRoot":"","sources":["../../src/brain/brain-encryption.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BrainSlicePackage } from '../types.js';
|
|
2
|
+
export declare class BrainExchange {
|
|
3
|
+
private brain;
|
|
4
|
+
constructor();
|
|
5
|
+
export(opts: {
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
author: string;
|
|
9
|
+
categories?: string[];
|
|
10
|
+
tags?: string[];
|
|
11
|
+
minImportance?: number;
|
|
12
|
+
limit?: number;
|
|
13
|
+
license?: string;
|
|
14
|
+
}): Promise<{
|
|
15
|
+
filePath: string;
|
|
16
|
+
package: BrainSlicePackage;
|
|
17
|
+
}>;
|
|
18
|
+
import(filePath: string, opts?: {
|
|
19
|
+
projectDir: string;
|
|
20
|
+
agentTool?: string;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
imported: number;
|
|
23
|
+
pkg: BrainSlicePackage;
|
|
24
|
+
}>;
|
|
25
|
+
listLocal(): BrainSlicePackage[];
|
|
26
|
+
private redact;
|
|
27
|
+
}
|
|
28
|
+
export declare function getBrainExchange(): BrainExchange;
|
|
29
|
+
export declare function resetBrainExchangeForTests(): void;
|
|
30
|
+
//# sourceMappingURL=brain-exchange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-exchange.d.ts","sourceRoot":"","sources":["../../src/brain/brain-exchange.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAKhD,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAc;;IAMrB,MAAM,CAAC,IAAI,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAA;KAAE,CAAC;IAuCvD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAkC,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAA;KAAE,CAAC;IAsBvK,SAAS,IAAI,iBAAiB,EAAE;IAgBhC,OAAO,CAAC,MAAM;CAOf;AAID,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// src/brain/brain-exchange.ts — Curated shareable brain slices
|
|
2
|
+
// v6.0.0 — Hive Mind Edition
|
|
3
|
+
//
|
|
4
|
+
// Export a curated subset of your brain as a shareable JSON package. Import
|
|
5
|
+
// someone else's package to instantly get expert knowledge for a domain.
|
|
6
|
+
// Zero-server design: packages are plain JSON files on disk (or shared via
|
|
7
|
+
// gist/HTTP/IPFS — transport is up to the user).
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import * as os from 'os';
|
|
11
|
+
import * as crypto from 'crypto';
|
|
12
|
+
import { getGlobalBrain, GlobalBrain } from './global-brain.js';
|
|
13
|
+
const EXCHANGE_DIR = path.join(os.homedir(), '.shadow-brain', 'exchange');
|
|
14
|
+
export class BrainExchange {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.brain = getGlobalBrain();
|
|
17
|
+
}
|
|
18
|
+
async export(opts) {
|
|
19
|
+
await this.brain.init();
|
|
20
|
+
fs.mkdirSync(EXCHANGE_DIR, { recursive: true });
|
|
21
|
+
const categories = opts.categories ?? [];
|
|
22
|
+
const keywords = opts.tags ?? [];
|
|
23
|
+
const limit = opts.limit ?? 500;
|
|
24
|
+
const minImportance = opts.minImportance ?? 0.5;
|
|
25
|
+
let entries = this.brain.recall({ keywords: keywords.length ? keywords : undefined, minImportance, limit });
|
|
26
|
+
if (categories.length) {
|
|
27
|
+
const allowed = new Set(categories.map(c => c.toLowerCase()));
|
|
28
|
+
entries = entries.filter(e => allowed.has(e.category.toLowerCase()));
|
|
29
|
+
}
|
|
30
|
+
const pkg = {
|
|
31
|
+
id: `pkg-${crypto.randomBytes(6).toString('hex')}`,
|
|
32
|
+
name: opts.name,
|
|
33
|
+
description: opts.description,
|
|
34
|
+
author: opts.author,
|
|
35
|
+
version: '1.0.0',
|
|
36
|
+
tags: opts.tags ?? [],
|
|
37
|
+
categories: Array.from(new Set(entries.map(e => e.category))),
|
|
38
|
+
memoryCount: entries.length,
|
|
39
|
+
memories: entries.map(e => ({
|
|
40
|
+
content: this.redact(e.content),
|
|
41
|
+
category: e.category,
|
|
42
|
+
importance: e.importance,
|
|
43
|
+
})),
|
|
44
|
+
createdAt: new Date(),
|
|
45
|
+
license: opts.license ?? 'MIT',
|
|
46
|
+
};
|
|
47
|
+
const safeName = opts.name.toLowerCase().replace(/[^a-z0-9_-]+/g, '-');
|
|
48
|
+
const filePath = path.join(EXCHANGE_DIR, `${safeName}-${pkg.id.slice(-6)}.json`);
|
|
49
|
+
fs.writeFileSync(filePath, JSON.stringify(pkg, null, 2));
|
|
50
|
+
return { filePath, package: pkg };
|
|
51
|
+
}
|
|
52
|
+
async import(filePath, opts = { projectDir: process.cwd() }) {
|
|
53
|
+
await this.brain.init();
|
|
54
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
55
|
+
const pkg = JSON.parse(raw);
|
|
56
|
+
const projectId = GlobalBrain.projectIdFor(opts.projectDir);
|
|
57
|
+
const projectName = path.basename(opts.projectDir);
|
|
58
|
+
let imported = 0;
|
|
59
|
+
for (const m of pkg.memories) {
|
|
60
|
+
this.brain.writeSync({
|
|
61
|
+
projectId,
|
|
62
|
+
projectName,
|
|
63
|
+
agentTool: opts.agentTool ?? 'claude-code',
|
|
64
|
+
category: m.category,
|
|
65
|
+
content: m.content,
|
|
66
|
+
importance: m.importance,
|
|
67
|
+
metadata: { origin: 'brain-exchange', packageId: pkg.id, packageName: pkg.name, author: pkg.author },
|
|
68
|
+
});
|
|
69
|
+
imported++;
|
|
70
|
+
}
|
|
71
|
+
return { imported, pkg };
|
|
72
|
+
}
|
|
73
|
+
listLocal() {
|
|
74
|
+
fs.mkdirSync(EXCHANGE_DIR, { recursive: true });
|
|
75
|
+
const files = fs.readdirSync(EXCHANGE_DIR).filter(f => f.endsWith('.json'));
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const f of files) {
|
|
78
|
+
try {
|
|
79
|
+
const raw = fs.readFileSync(path.join(EXCHANGE_DIR, f), 'utf-8');
|
|
80
|
+
const pkg = JSON.parse(raw);
|
|
81
|
+
out.push({ ...pkg, createdAt: new Date(pkg.createdAt) });
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* skip */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
88
|
+
}
|
|
89
|
+
redact(content) {
|
|
90
|
+
return content
|
|
91
|
+
.replace(/(api[_-]?key|secret|token|password|passwd|pwd)\s*[:=]\s*["'][^"']{8,}["']/gi, '$1: [REDACTED]')
|
|
92
|
+
.replace(/[A-Za-z0-9+/=]{40,}/g, '[REDACTED_BLOB]')
|
|
93
|
+
.replace(/\b[\w.+-]+@[\w.-]+\.\w{2,}\b/g, '[REDACTED_EMAIL]')
|
|
94
|
+
.replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, '[REDACTED_IP]');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
let _instance = null;
|
|
98
|
+
export function getBrainExchange() {
|
|
99
|
+
if (!_instance)
|
|
100
|
+
_instance = new BrainExchange();
|
|
101
|
+
return _instance;
|
|
102
|
+
}
|
|
103
|
+
export function resetBrainExchangeForTests() {
|
|
104
|
+
_instance = null;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=brain-exchange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-exchange.js","sourceRoot":"","sources":["../../src/brain/brain-exchange.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GardenNode } from '../types.js';
|
|
2
|
+
export declare class BrainGarden {
|
|
3
|
+
private brain;
|
|
4
|
+
private forgetting;
|
|
5
|
+
private causal;
|
|
6
|
+
constructor();
|
|
7
|
+
snapshot(limit?: number): Promise<GardenNode[]>;
|
|
8
|
+
/** Compact stats used by the dashboard widget. */
|
|
9
|
+
stats(): Promise<{
|
|
10
|
+
nodes: number;
|
|
11
|
+
avgBloom: number;
|
|
12
|
+
linkedFraction: number;
|
|
13
|
+
}>;
|
|
14
|
+
private kindFromCategory;
|
|
15
|
+
}
|
|
16
|
+
export declare function getBrainGarden(): BrainGarden;
|
|
17
|
+
export declare function resetBrainGardenForTests(): void;
|
|
18
|
+
//# sourceMappingURL=brain-garden.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-garden.d.ts","sourceRoot":"","sources":["../../src/brain/brain-garden.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,UAAU,EACX,MAAM,aAAa,CAAC;AAKrB,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAe;;IAQvB,QAAQ,CAAC,KAAK,SAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAyClD,kDAAkD;IAC5C,KAAK,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IAUnF,OAAO,CAAC,gBAAgB;CAMzB;AAID,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// src/brain/brain-garden.ts — Aesthetic brain-as-garden visualizer data source
|
|
2
|
+
// v6.0.0 — Hive Mind Edition
|
|
3
|
+
//
|
|
4
|
+
// Returns a GardenNode[] snapshot of the brain state formatted for a D3 /
|
|
5
|
+
// three.js / Canvas visualization. Memories "bloom" based on strength; links
|
|
6
|
+
// become "vines" between them. Decaying memories dim. It's a living
|
|
7
|
+
// constellation.
|
|
8
|
+
import { getGlobalBrain } from './global-brain.js';
|
|
9
|
+
import { getForgettingCurve } from './forgetting-curve.js';
|
|
10
|
+
import { getCausalChains } from './causal-chains.js';
|
|
11
|
+
export class BrainGarden {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.brain = getGlobalBrain();
|
|
14
|
+
this.forgetting = getForgettingCurve();
|
|
15
|
+
this.causal = getCausalChains();
|
|
16
|
+
}
|
|
17
|
+
async snapshot(limit = 200) {
|
|
18
|
+
await this.brain.init();
|
|
19
|
+
await this.forgetting.init();
|
|
20
|
+
await this.causal.init();
|
|
21
|
+
const timeline = this.brain.timeline({ limit });
|
|
22
|
+
const nodes = [];
|
|
23
|
+
for (const event of timeline) {
|
|
24
|
+
const state = this.forgetting.getState(event.id);
|
|
25
|
+
const strength = state?.currentStrength ?? event.importance;
|
|
26
|
+
const ageMs = Date.now() - event.createdAt.getTime();
|
|
27
|
+
const ageDays = ageMs / (1000 * 60 * 60 * 24);
|
|
28
|
+
nodes.push({
|
|
29
|
+
id: event.id,
|
|
30
|
+
kind: this.kindFromCategory(event.category),
|
|
31
|
+
label: event.content.slice(0, 80),
|
|
32
|
+
age: +ageDays.toFixed(1),
|
|
33
|
+
strength: +strength.toFixed(3),
|
|
34
|
+
connections: [],
|
|
35
|
+
bloom: Math.max(0.1, Math.min(1, strength * (1 - Math.min(1, ageDays / 90)))),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
// Enrich connections from causal chains (fire-and-forget — keep cheap)
|
|
39
|
+
for (const node of nodes) {
|
|
40
|
+
try {
|
|
41
|
+
const chain = await this.causal.trace(node.id, { maxDepth: 2 });
|
|
42
|
+
node.connections = chain.nodes
|
|
43
|
+
.filter(n => n.id !== node.id)
|
|
44
|
+
.slice(0, 6)
|
|
45
|
+
.map(n => n.id);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
node.connections = [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return nodes;
|
|
52
|
+
}
|
|
53
|
+
/** Compact stats used by the dashboard widget. */
|
|
54
|
+
async stats() {
|
|
55
|
+
const nodes = await this.snapshot(150);
|
|
56
|
+
if (!nodes.length)
|
|
57
|
+
return { nodes: 0, avgBloom: 0, linkedFraction: 0 };
|
|
58
|
+
const avg = nodes.reduce((a, n) => a + n.bloom, 0) / nodes.length;
|
|
59
|
+
const linked = nodes.filter(n => n.connections.length > 0).length / nodes.length;
|
|
60
|
+
return { nodes: nodes.length, avgBloom: +avg.toFixed(3), linkedFraction: +linked.toFixed(3) };
|
|
61
|
+
}
|
|
62
|
+
// ── Internals ─────────────────────────────────────────────────────────────
|
|
63
|
+
kindFromCategory(category) {
|
|
64
|
+
const c = category.toLowerCase();
|
|
65
|
+
if (c.includes('decision') || c.includes('adr'))
|
|
66
|
+
return 'decision';
|
|
67
|
+
if (c.includes('pattern'))
|
|
68
|
+
return 'pattern';
|
|
69
|
+
return 'memory';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let _instance = null;
|
|
73
|
+
export function getBrainGarden() {
|
|
74
|
+
if (!_instance)
|
|
75
|
+
_instance = new BrainGarden();
|
|
76
|
+
return _instance;
|
|
77
|
+
}
|
|
78
|
+
export function resetBrainGardenForTests() {
|
|
79
|
+
_instance = null;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=brain-garden.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-garden.js","sourceRoot":"","sources":["../../src/brain/brain-garden.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ export class BrainPortability {
|
|
|
35
35
|
const fileName = `brain-${projectName}-${timestamp}.json`;
|
|
36
36
|
const filePath = path.join(this.exportDir, fileName);
|
|
37
37
|
const data = {
|
|
38
|
-
version: '5.0
|
|
38
|
+
version: '5.2.0',
|
|
39
39
|
exportedAt: new Date(),
|
|
40
40
|
projectName,
|
|
41
41
|
projectDir: this.projectDir,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BranchBrainState, BranchMemoryTag } from '../types.js';
|
|
2
|
+
export declare class BranchBrain {
|
|
3
|
+
private brain;
|
|
4
|
+
private tags;
|
|
5
|
+
private lastBranchByProject;
|
|
6
|
+
private initialized;
|
|
7
|
+
constructor();
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
/** Current branch from git for the given project dir. */
|
|
10
|
+
currentBranch(projectDir: string): Promise<string>;
|
|
11
|
+
/** Tag a memory as either global or branch-scoped. */
|
|
12
|
+
tag(memoryId: string, branch: string, scope?: 'branch' | 'global'): Promise<BranchMemoryTag>;
|
|
13
|
+
/** Return the set of memory IDs active for a branch (branch-scoped + global). */
|
|
14
|
+
activeMemoryIds(branch: string): string[];
|
|
15
|
+
/** Compute + return the current branch brain state. */
|
|
16
|
+
getState(projectDir: string): Promise<BranchBrainState>;
|
|
17
|
+
/** Promote a branch-scoped memory to global (e.g., after merging). */
|
|
18
|
+
promoteToGlobal(memoryId: string): Promise<boolean>;
|
|
19
|
+
private persist;
|
|
20
|
+
}
|
|
21
|
+
export declare function getBranchBrain(): BranchBrain;
|
|
22
|
+
export declare function resetBranchBrainForTests(): void;
|
|
23
|
+
//# sourceMappingURL=branch-brain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-brain.d.ts","sourceRoot":"","sources":["../../src/brain/branch-brain.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAWrB,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,IAAI,CAA6C;IACzD,OAAO,CAAC,mBAAmB,CAAkC;IAC7D,OAAO,CAAC,WAAW,CAAS;;IAMtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B,yDAAyD;IACnD,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUxD,sDAAsD;IAChD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,QAAQ,GAAG,QAAmB,GAAG,OAAO,CAAC,eAAe,CAAC;IAe5G,iFAAiF;IACjF,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE;IAazC,uDAAuD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyC7D,sEAAsE;IAChE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YAW3C,OAAO;CAgBtB;AAID,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|