brain-cache 0.4.2 → 3.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/.claude/skills/brain-cache/SKILL.md +52 -0
- package/README.md +49 -100
- package/dist/{askCodebase-BZIXS3EV.js → askCodebase-EE32B7BP.js} +9 -9
- package/dist/buildContext-GWVDAYH6.js +14 -0
- package/dist/{chunk-Y7BU7IYX.js → chunk-3HQRTLBH.js} +70 -6
- package/dist/{chunk-ZKVZTDND.js → chunk-4IOR54GU.js} +2 -1
- package/dist/chunk-6C2OYMKD.js +16 -0
- package/dist/{workflows-KYCBR7TC.js → chunk-CY34XQ2O.js} +115 -24
- package/dist/chunk-DFFMV3RR.js +171 -0
- package/dist/{chunk-PJQNHMQH.js → chunk-DPH5X5HL.js} +1 -1
- package/dist/{chunk-FQL4HV4R.js → chunk-HRJ3OT6Q.js} +1 -1
- package/dist/chunk-KMRPAVMM.js +967 -0
- package/dist/{chunk-KQZSBRRH.js → chunk-RKPICQU7.js} +1 -1
- package/dist/{chunk-EEC7KYPY.js → chunk-TXLCXXKY.js} +7 -8
- package/dist/claude-md-section-K47HUTE4.js +38 -0
- package/dist/cli.js +13 -9
- package/dist/{doctor-KRNLXE4R.js → doctor-FCET2MNJ.js} +3 -3
- package/dist/{embedder-ZLHAZZUI.js → embedder-HVEXDJAU.js} +2 -2
- package/dist/{init-QNN5H3DR.js → init-2E4JMZZC.js} +71 -6
- package/dist/mcp.js +1450 -130
- package/dist/{search-O4CFAH45.js → search-7ISZ7EXI.js} +16 -15
- package/dist/{status-7MT4IROA.js → status-VKTSG2SN.js} +3 -3
- package/dist/statusline-script-NFUDFOWK.js +95 -0
- package/dist/watch-QPMAB62P.js +128 -0
- package/dist/workflows-MWEY7OAI.js +14 -0
- package/package.json +5 -1
- package/dist/buildContext-APWOPZMJ.js +0 -14
- package/dist/chunk-JZQWPHAQ.js +0 -103
- package/dist/chunk-SBSMKI4B.js +0 -109
- package/dist/chunk-ZGYLHFHJ.js +0 -17
- package/dist/claude-md-section-6ZJ3TMO4.js +0 -34
|
@@ -18,13 +18,12 @@ var VECTOR_INDEX_THRESHOLD = 256;
|
|
|
18
18
|
var EMBED_TIMEOUT_MS = 3e4;
|
|
19
19
|
var COLD_START_RETRY_DELAY_MS = 2e3;
|
|
20
20
|
var EMBED_MAX_TOKENS = 8192;
|
|
21
|
-
var DEFAULT_SEARCH_LIMIT = 10;
|
|
22
|
-
var DEFAULT_DISTANCE_THRESHOLD = 0.4;
|
|
23
|
-
var DIAGNOSTIC_DISTANCE_THRESHOLD = 0.45;
|
|
24
|
-
var DIAGNOSTIC_SEARCH_LIMIT = 20;
|
|
25
21
|
var DEFAULT_TOKEN_BUDGET = 4096;
|
|
26
22
|
var FILE_HASHES_FILENAME = "file-hashes.json";
|
|
27
23
|
var TOOL_CALL_OVERHEAD_TOKENS = 300;
|
|
24
|
+
var COMPRESSION_TOKEN_THRESHOLD = 500;
|
|
25
|
+
var HIGH_RELEVANCE_SIMILARITY_THRESHOLD = 0.85;
|
|
26
|
+
var COMPRESSION_HARD_LIMIT = 800;
|
|
28
27
|
|
|
29
28
|
// src/services/logger.ts
|
|
30
29
|
import pino from "pino";
|
|
@@ -72,6 +71,7 @@ function setLogLevel(level) {
|
|
|
72
71
|
export {
|
|
73
72
|
GLOBAL_CONFIG_DIR,
|
|
74
73
|
PROFILE_PATH,
|
|
74
|
+
CONFIG_PATH,
|
|
75
75
|
PROJECT_DATA_DIR,
|
|
76
76
|
EMBEDDING_DIMENSIONS,
|
|
77
77
|
DEFAULT_EMBEDDING_DIMENSION,
|
|
@@ -81,13 +81,12 @@ export {
|
|
|
81
81
|
EMBED_TIMEOUT_MS,
|
|
82
82
|
COLD_START_RETRY_DELAY_MS,
|
|
83
83
|
EMBED_MAX_TOKENS,
|
|
84
|
-
DEFAULT_SEARCH_LIMIT,
|
|
85
|
-
DEFAULT_DISTANCE_THRESHOLD,
|
|
86
|
-
DIAGNOSTIC_DISTANCE_THRESHOLD,
|
|
87
|
-
DIAGNOSTIC_SEARCH_LIMIT,
|
|
88
84
|
DEFAULT_TOKEN_BUDGET,
|
|
89
85
|
FILE_HASHES_FILENAME,
|
|
90
86
|
TOOL_CALL_OVERHEAD_TOKENS,
|
|
87
|
+
COMPRESSION_TOKEN_THRESHOLD,
|
|
88
|
+
HIGH_RELEVANCE_SIMILARITY_THRESHOLD,
|
|
89
|
+
COMPRESSION_HARD_LIMIT,
|
|
91
90
|
childLogger,
|
|
92
91
|
setLogLevel
|
|
93
92
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/claude-md-section.ts
|
|
4
|
+
var CLAUDE_MD_SECTION = `
|
|
5
|
+
## Brain-Cache MCP Tools
|
|
6
|
+
|
|
7
|
+
Use brain-cache tools before reading files or using Grep/Glob for codebase questions.
|
|
8
|
+
|
|
9
|
+
| Query type | Tool | NOT this |
|
|
10
|
+
|-----------|------|---------|
|
|
11
|
+
| Locate a function, type, or symbol | \`search_codebase\` | \`build_context\` |
|
|
12
|
+
| Understand how specific code works across files | \`build_context\` | file reads |
|
|
13
|
+
| Diagnose brain-cache failures | \`doctor\` | -- |
|
|
14
|
+
| Reindex the project | \`index_repo\` | -- |
|
|
15
|
+
|
|
16
|
+
### search_codebase (locate code)
|
|
17
|
+
|
|
18
|
+
Call \`mcp__brain-cache__search_codebase\` to find functions, types, definitions, or implementations by meaning rather than keyword match.
|
|
19
|
+
|
|
20
|
+
Do NOT use for understanding how code works \u2014 use build_context once you have located the symbol.
|
|
21
|
+
|
|
22
|
+
### build_context (understand specific behavior)
|
|
23
|
+
|
|
24
|
+
Call \`mcp__brain-cache__build_context\` with a focused question about how specific code works. It retrieves semantically relevant code, deduplicates results, and fits them to a token budget.
|
|
25
|
+
|
|
26
|
+
Use for: "How does X work?", "What does this function do?", debugging unfamiliar code paths.
|
|
27
|
+
|
|
28
|
+
### doctor (diagnose issues)
|
|
29
|
+
|
|
30
|
+
Call \`mcp__brain-cache__doctor\` when any brain-cache tool fails or returns unexpected results.
|
|
31
|
+
|
|
32
|
+
### index_repo (reindex)
|
|
33
|
+
|
|
34
|
+
Call \`mcp__brain-cache__index_repo\` only when the user explicitly asks to reindex, or after major code changes. Do not call proactively.
|
|
35
|
+
`;
|
|
36
|
+
export {
|
|
37
|
+
CLAUDE_MD_SECTION
|
|
38
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
formatTokenSavings
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6C2OYMKD.js";
|
|
5
5
|
|
|
6
6
|
// src/cli/index.ts
|
|
7
7
|
import { Command } from "commander";
|
|
8
|
-
var version = "0.
|
|
8
|
+
var version = true ? "3.0.0" : "dev";
|
|
9
9
|
var program = new Command();
|
|
10
10
|
program.name("brain-cache").description("Local AI runtime \u2014 GPU cache layer for Claude").version(version);
|
|
11
11
|
program.command("init").description("Detect hardware, pull embedding model, create config directory").action(async () => {
|
|
12
|
-
const { runInit } = await import("./init-
|
|
12
|
+
const { runInit } = await import("./init-2E4JMZZC.js");
|
|
13
13
|
await runInit();
|
|
14
14
|
});
|
|
15
15
|
program.command("doctor").description("Report system health: GPU, VRAM tier, Ollama status").action(async () => {
|
|
16
|
-
const { runDoctor } = await import("./doctor-
|
|
16
|
+
const { runDoctor } = await import("./doctor-FCET2MNJ.js");
|
|
17
17
|
await runDoctor();
|
|
18
18
|
});
|
|
19
19
|
program.command("index").description("Index a codebase: parse, chunk, embed, and store in LanceDB").argument("[path]", "Directory to index (defaults to current directory)").option("-f, --force", "Force full reindex, ignoring cached file hashes").action(async (path, opts) => {
|
|
20
|
-
const { runIndex } = await import("./workflows-
|
|
20
|
+
const { runIndex } = await import("./workflows-MWEY7OAI.js");
|
|
21
21
|
await runIndex(path, { force: opts.force });
|
|
22
22
|
});
|
|
23
|
+
program.command("watch").description("Watch a directory for file changes and auto-reindex").argument("[path]", "Directory to watch (defaults to current directory)").action(async (path) => {
|
|
24
|
+
const { runWatch } = await import("./watch-QPMAB62P.js");
|
|
25
|
+
await runWatch(path);
|
|
26
|
+
});
|
|
23
27
|
program.command("search").description("Search indexed codebase with a natural language query").argument("<query>", "Natural language query string").option("-n, --limit <n>", "Maximum number of results", "10").option("-p, --path <path>", "Project root directory").action(async (query, opts) => {
|
|
24
|
-
const { runSearch } = await import("./search-
|
|
28
|
+
const { runSearch } = await import("./search-7ISZ7EXI.js");
|
|
25
29
|
await runSearch(query, {
|
|
26
30
|
limit: parseInt(opts.limit, 10),
|
|
27
31
|
path: opts.path
|
|
@@ -30,12 +34,12 @@ program.command("search").description("Search indexed codebase with a natural la
|
|
|
30
34
|
program.command("status").description(
|
|
31
35
|
"Show index stats: files indexed, chunks stored, last indexed time"
|
|
32
36
|
).argument("[path]", "Project root directory (defaults to current directory)").action(async (path) => {
|
|
33
|
-
const { runStatus } = await import("./status-
|
|
37
|
+
const { runStatus } = await import("./status-VKTSG2SN.js");
|
|
34
38
|
await runStatus(path);
|
|
35
39
|
});
|
|
36
40
|
program.command("context").description("Build token-budgeted context from codebase for a query").argument("<query>", "Natural language query string").option("-n, --limit <n>", "Maximum number of search results", "10").option("-b, --budget <tokens>", "Token budget for assembled context", "4096").option("-p, --path <path>", "Project root directory").option("--raw", "Output raw JSON (MCP transport compatible)").action(
|
|
37
41
|
async (query, opts) => {
|
|
38
|
-
const { runBuildContext } = await import("./buildContext-
|
|
42
|
+
const { runBuildContext } = await import("./buildContext-GWVDAYH6.js");
|
|
39
43
|
const result = await runBuildContext(query, {
|
|
40
44
|
limit: parseInt(opts.limit, 10),
|
|
41
45
|
maxTokens: parseInt(opts.budget, 10),
|
|
@@ -60,7 +64,7 @@ ${formatTokenSavings({ tokensSent: result.metadata.tokensSent, estimatedWithout:
|
|
|
60
64
|
program.command("ask").description(
|
|
61
65
|
"Ask a natural language question about the codebase \u2014 retrieves context locally, reasons via Claude"
|
|
62
66
|
).argument("<question>", "Natural language question about the codebase").option("-b, --budget <tokens>", "Token budget for context retrieval", "4096").option("-p, --path <path>", "Project root directory").action(async (question, opts) => {
|
|
63
|
-
const { runAskCodebase } = await import("./askCodebase-
|
|
67
|
+
const { runAskCodebase } = await import("./askCodebase-EE32B7BP.js");
|
|
64
68
|
const result = await runAskCodebase(question, {
|
|
65
69
|
path: opts.path,
|
|
66
70
|
maxContextTokens: parseInt(opts.budget, 10)
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
isOllamaInstalled,
|
|
5
5
|
isOllamaRunning,
|
|
6
6
|
modelMatches
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HRJ3OT6Q.js";
|
|
8
8
|
import {
|
|
9
9
|
detectCapabilities,
|
|
10
10
|
readProfile
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DPH5X5HL.js";
|
|
12
12
|
import {
|
|
13
13
|
PROFILE_PATH
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-TXLCXXKY.js";
|
|
15
15
|
|
|
16
16
|
// src/workflows/doctor.ts
|
|
17
17
|
import ollama from "ollama";
|
|
@@ -5,15 +5,18 @@ import {
|
|
|
5
5
|
isOllamaRunning,
|
|
6
6
|
pullModelIfMissing,
|
|
7
7
|
startOllama
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HRJ3OT6Q.js";
|
|
9
9
|
import {
|
|
10
10
|
detectCapabilities,
|
|
11
11
|
writeProfile
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-DPH5X5HL.js";
|
|
13
|
+
import "./chunk-TXLCXXKY.js";
|
|
14
14
|
|
|
15
15
|
// src/workflows/init.ts
|
|
16
|
-
import { existsSync, readFileSync, writeFileSync, appendFileSync } from "fs";
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync, appendFileSync, chmodSync, mkdirSync, copyFileSync } from "fs";
|
|
17
|
+
import { join, dirname } from "path";
|
|
18
|
+
import { homedir } from "os";
|
|
19
|
+
import { fileURLToPath } from "url";
|
|
17
20
|
async function runInit() {
|
|
18
21
|
process.stderr.write("brain-cache: detecting hardware capabilities...\n");
|
|
19
22
|
const profile = await detectCapabilities();
|
|
@@ -52,7 +55,7 @@ async function runInit() {
|
|
|
52
55
|
`brain-cache: warming model ${profileWithVersion.embeddingModel} into VRAM...
|
|
53
56
|
`
|
|
54
57
|
);
|
|
55
|
-
const { embedBatchWithRetry } = await import("./embedder-
|
|
58
|
+
const { embedBatchWithRetry } = await import("./embedder-HVEXDJAU.js");
|
|
56
59
|
await embedBatchWithRetry(profileWithVersion.embeddingModel, ["warmup"]);
|
|
57
60
|
process.stderr.write("brain-cache: model warm.\n");
|
|
58
61
|
await writeProfile(profileWithVersion);
|
|
@@ -86,7 +89,7 @@ async function runInit() {
|
|
|
86
89
|
process.stderr.write("brain-cache: created .mcp.json with brain-cache MCP server.\n");
|
|
87
90
|
}
|
|
88
91
|
const claudeMdPath = "CLAUDE.md";
|
|
89
|
-
const { CLAUDE_MD_SECTION: brainCacheSection } = await import("./claude-md-section-
|
|
92
|
+
const { CLAUDE_MD_SECTION: brainCacheSection } = await import("./claude-md-section-K47HUTE4.js");
|
|
90
93
|
if (existsSync(claudeMdPath)) {
|
|
91
94
|
const content = readFileSync(claudeMdPath, "utf-8");
|
|
92
95
|
if (content.includes("## Brain-Cache MCP Tools")) {
|
|
@@ -99,6 +102,68 @@ async function runInit() {
|
|
|
99
102
|
writeFileSync(claudeMdPath, brainCacheSection.trimStart());
|
|
100
103
|
process.stderr.write("brain-cache: created CLAUDE.md with Brain-Cache MCP Tools section.\n");
|
|
101
104
|
}
|
|
105
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
106
|
+
const packageRoot = join(dirname(currentFile), "..", "..");
|
|
107
|
+
const skillSource = join(packageRoot, ".claude", "skills", "brain-cache", "SKILL.md");
|
|
108
|
+
const skillTargetDir = join(process.cwd(), ".claude", "skills", "brain-cache");
|
|
109
|
+
const skillTarget = join(skillTargetDir, "SKILL.md");
|
|
110
|
+
if (existsSync(skillTarget)) {
|
|
111
|
+
process.stderr.write("brain-cache: skill already installed at .claude/skills/brain-cache/SKILL.md, skipping.\n");
|
|
112
|
+
} else if (!existsSync(skillSource)) {
|
|
113
|
+
process.stderr.write("brain-cache: Warning: skill source not found in package. Copy .claude/skills/brain-cache/ manually from the repo.\n");
|
|
114
|
+
} else {
|
|
115
|
+
mkdirSync(skillTargetDir, { recursive: true });
|
|
116
|
+
copyFileSync(skillSource, skillTarget);
|
|
117
|
+
process.stderr.write("brain-cache: installed skill to .claude/skills/brain-cache/SKILL.md\n");
|
|
118
|
+
}
|
|
119
|
+
const { STATUSLINE_SCRIPT_CONTENT } = await import("./statusline-script-NFUDFOWK.js");
|
|
120
|
+
const statuslinePath = join(homedir(), ".brain-cache", "statusline.mjs");
|
|
121
|
+
if (existsSync(statuslinePath)) {
|
|
122
|
+
const existingScript = readFileSync(statuslinePath, "utf-8");
|
|
123
|
+
if (existingScript === STATUSLINE_SCRIPT_CONTENT) {
|
|
124
|
+
process.stderr.write("brain-cache: statusline.mjs already installed, skipping.\n");
|
|
125
|
+
} else {
|
|
126
|
+
process.stderr.write(
|
|
127
|
+
"brain-cache: Warning: ~/.brain-cache/statusline.mjs already exists with custom content. Skipping to preserve user changes.\n"
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
writeFileSync(statuslinePath, STATUSLINE_SCRIPT_CONTENT, "utf-8");
|
|
132
|
+
chmodSync(statuslinePath, 493);
|
|
133
|
+
process.stderr.write("brain-cache: installed statusline.mjs to ~/.brain-cache/statusline.mjs\n");
|
|
134
|
+
}
|
|
135
|
+
const claudeDir = join(homedir(), ".claude");
|
|
136
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
137
|
+
const statusLineEntry = {
|
|
138
|
+
type: "command",
|
|
139
|
+
command: `node "${join(homedir(), ".brain-cache", "statusline.mjs")}"`
|
|
140
|
+
};
|
|
141
|
+
try {
|
|
142
|
+
if (existsSync(settingsPath)) {
|
|
143
|
+
const rawSettings = readFileSync(settingsPath, "utf-8");
|
|
144
|
+
const parsed = JSON.parse(rawSettings);
|
|
145
|
+
if (parsed["statusLine"]) {
|
|
146
|
+
process.stderr.write(
|
|
147
|
+
"brain-cache: Warning: ~/.claude/settings.json already has a statusLine entry. Skipping to preserve existing configuration.\n"
|
|
148
|
+
);
|
|
149
|
+
} else {
|
|
150
|
+
parsed["statusLine"] = statusLineEntry;
|
|
151
|
+
writeFileSync(settingsPath, JSON.stringify(parsed, null, 2) + "\n");
|
|
152
|
+
process.stderr.write("brain-cache: added statusLine to ~/.claude/settings.json\n");
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
156
|
+
const newSettings = { statusLine: statusLineEntry };
|
|
157
|
+
writeFileSync(settingsPath, JSON.stringify(newSettings, null, 2) + "\n");
|
|
158
|
+
process.stderr.write("brain-cache: created ~/.claude/settings.json with statusLine entry.\n");
|
|
159
|
+
}
|
|
160
|
+
} catch (err) {
|
|
161
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
162
|
+
process.stderr.write(
|
|
163
|
+
`brain-cache: Warning: Could not configure ~/.claude/settings.json: ${msg}. Status line will not appear in Claude Code until settings.json is configured manually.
|
|
164
|
+
`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
102
167
|
}
|
|
103
168
|
export {
|
|
104
169
|
runInit
|