brain-cache 0.3.3 → 0.3.5

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.
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- formatTokenSavings
4
- } from "./chunk-GGOUKACO.js";
5
2
  import {
6
3
  runBuildContext
7
- } from "./chunk-QNPB2UD2.js";
4
+ } from "./chunk-AEJKKJDU.js";
8
5
  import "./chunk-5FXXZBZV.js";
6
+ import {
7
+ formatTokenSavings
8
+ } from "./chunk-GGOUKACO.js";
9
9
  import "./chunk-BF5UDEIF.js";
10
10
  import "./chunk-GR6QXZ4J.js";
11
11
  import "./chunk-V4ARVFRG.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runBuildContext
4
- } from "./chunk-QNPB2UD2.js";
4
+ } from "./chunk-AEJKKJDU.js";
5
5
  import "./chunk-5FXXZBZV.js";
6
6
  import "./chunk-BF5UDEIF.js";
7
7
  import "./chunk-GR6QXZ4J.js";
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- assembleContext
3
+ assembleContext,
4
+ countChunkTokens
4
5
  } from "./chunk-5FXXZBZV.js";
5
6
  import {
6
7
  RETRIEVAL_STRATEGIES,
@@ -26,6 +27,7 @@ import {
26
27
  } from "./chunk-3SFDFUEX.js";
27
28
 
28
29
  // src/workflows/buildContext.ts
30
+ import { readFile } from "fs/promises";
29
31
  import { resolve } from "path";
30
32
  async function runBuildContext(query, opts) {
31
33
  const profile = await readProfile();
@@ -62,8 +64,20 @@ async function runBuildContext(query, opts) {
62
64
  const results = await searchChunks(table, queryVector, strategy);
63
65
  const deduped = deduplicateChunks(results);
64
66
  const assembled = assembleContext(deduped, { maxTokens });
65
- const estimatedWithoutBraincache = indexState.totalTokens;
66
- const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - assembled.tokenCount / estimatedWithoutBraincache) * 100) : 0;
67
+ const uniqueFiles = [...new Set(assembled.chunks.map((c) => c.filePath))];
68
+ let estimatedWithoutBraincache = 0;
69
+ for (const filePath of uniqueFiles) {
70
+ try {
71
+ const fileContent = await readFile(filePath, "utf-8");
72
+ estimatedWithoutBraincache += countChunkTokens(fileContent);
73
+ } catch {
74
+ }
75
+ }
76
+ const rawChunkTokens = assembled.chunks.reduce(
77
+ (sum, c) => sum + countChunkTokens(c.content),
78
+ 0
79
+ );
80
+ const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - rawChunkTokens / estimatedWithoutBraincache) * 100) : 0;
67
81
  const result = {
68
82
  content: assembled.content,
69
83
  chunks: assembled.chunks,
@@ -0,0 +1,34 @@
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
+ **IMPORTANT: Use brain-cache tools as your FIRST action before reading files or using Grep/Glob.**
8
+
9
+ ### build_context (use for understanding)
10
+
11
+ Call \`mcp__brain-cache__build_context\` with the user's question BEFORE reading individual files. This retrieves semantically relevant code from across the entire repo, deduplicates it, and returns a token-budgeted context block.
12
+
13
+ **Always use for questions like:**
14
+ - "How does X work?" / "Explain X end to end"
15
+ - "Walk me through the flow of X"
16
+ - "What does this page/feature/component do?"
17
+ - "Explain the architecture" / "How is the project structured?"
18
+ - "What happens when Y is called?"
19
+ - Any question that requires understanding code across multiple files
20
+ - Debugging unfamiliar code paths or understanding error flows
21
+
22
+ **Do NOT skip this tool and jump to reading files.** build_context returns better results with fewer tokens than manually reading files.
23
+
24
+ ### search_codebase (use for locating)
25
+
26
+ Call \`mcp__brain-cache__search_codebase\` instead of Grep or Glob when locating functions, symbols, types, definitions, or implementations. It uses semantic search \u2014 finds code by meaning, not just keyword match.
27
+
28
+ ### doctor (use for diagnosing)
29
+
30
+ Call \`mcp__brain-cache__doctor\` first when any brain-cache tool fails or returns unexpected results.
31
+ `;
32
+ export {
33
+ CLAUDE_MD_SECTION
34
+ };
package/dist/cli.js CHANGED
@@ -5,11 +5,11 @@ import {
5
5
 
6
6
  // src/cli/index.ts
7
7
  import { Command } from "commander";
8
- var version = "0.3.3";
8
+ var version = "0.3.5";
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-ILR3VJNO.js");
12
+ const { runInit } = await import("./init-L4CMLYVY.js");
13
13
  await runInit();
14
14
  });
15
15
  program.command("doctor").description("Report system health: GPU, VRAM tier, Ollama status").action(async () => {
@@ -17,7 +17,7 @@ program.command("doctor").description("Report system health: GPU, VRAM tier, Oll
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-SYWKVVOK.js");
20
+ const { runIndex } = await import("./workflows-ZC24RRNX.js");
21
21
  await runIndex(path, { force: opts.force });
22
22
  });
23
23
  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) => {
@@ -35,7 +35,7 @@ program.command("status").description(
35
35
  });
36
36
  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
37
  async (query, opts) => {
38
- const { runBuildContext } = await import("./buildContext-QIMH5LQY.js");
38
+ const { runBuildContext } = await import("./buildContext-IND6F67G.js");
39
39
  const result = await runBuildContext(query, {
40
40
  limit: parseInt(opts.limit, 10),
41
41
  maxTokens: parseInt(opts.budget, 10),
@@ -61,7 +61,7 @@ ${formatTokenSavings({ tokensSent: result.metadata.tokensSent, estimatedWithout,
61
61
  program.command("ask").description(
62
62
  "Ask a natural language question about the codebase \u2014 retrieves context locally, reasons via Claude"
63
63
  ).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) => {
64
- const { runAskCodebase } = await import("./askCodebase-OAAG35G5.js");
64
+ const { runAskCodebase } = await import("./askCodebase-NYPWHDEZ.js");
65
65
  const result = await runAskCodebase(question, {
66
66
  path: opts.path,
67
67
  maxContextTokens: parseInt(opts.budget, 10)
@@ -86,13 +86,7 @@ async function runInit() {
86
86
  process.stderr.write("brain-cache: created .mcp.json with brain-cache MCP server.\n");
87
87
  }
88
88
  const claudeMdPath = "CLAUDE.md";
89
- const brainCacheSection = `
90
- ## Brain-Cache MCP Tools
91
-
92
- When answering "how does X work", "explain the architecture", or any question requiring multi-file reasoning, call \`mcp__brain-cache__build_context\` with the question BEFORE reading individual files. It returns pre-built, relevant context with token savings.
93
-
94
- When locating functions, symbols, types, or definitions, call \`mcp__brain-cache__search_codebase\` instead of using Grep or file-find tools. It searches the local vector index and returns ranked results.
95
- `;
89
+ const { CLAUDE_MD_SECTION: brainCacheSection } = await import("./claude-md-section-YPMDPAPW.js");
96
90
  if (existsSync(claudeMdPath)) {
97
91
  const content = readFileSync(claudeMdPath, "utf-8");
98
92
  if (content.includes("## Brain-Cache MCP Tools")) {
package/dist/mcp.js CHANGED
@@ -1087,6 +1087,7 @@ async function runSearch(query, opts) {
1087
1087
  }
1088
1088
 
1089
1089
  // src/workflows/buildContext.ts
1090
+ import { readFile as readFile5 } from "fs/promises";
1090
1091
  import { resolve as resolve3 } from "path";
1091
1092
  async function runBuildContext(query, opts) {
1092
1093
  const profile = await readProfile();
@@ -1123,8 +1124,20 @@ async function runBuildContext(query, opts) {
1123
1124
  const results = await searchChunks(table, queryVector, strategy);
1124
1125
  const deduped = deduplicateChunks(results);
1125
1126
  const assembled = assembleContext(deduped, { maxTokens });
1126
- const estimatedWithoutBraincache = indexState.totalTokens;
1127
- const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - assembled.tokenCount / estimatedWithoutBraincache) * 100) : 0;
1127
+ const uniqueFiles = [...new Set(assembled.chunks.map((c) => c.filePath))];
1128
+ let estimatedWithoutBraincache = 0;
1129
+ for (const filePath of uniqueFiles) {
1130
+ try {
1131
+ const fileContent = await readFile5(filePath, "utf-8");
1132
+ estimatedWithoutBraincache += countChunkTokens(fileContent);
1133
+ } catch {
1134
+ }
1135
+ }
1136
+ const rawChunkTokens = assembled.chunks.reduce(
1137
+ (sum, c) => sum + countChunkTokens(c.content),
1138
+ 0
1139
+ );
1140
+ const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - rawChunkTokens / estimatedWithoutBraincache) * 100) : 0;
1128
1141
  const result = {
1129
1142
  content: assembled.content,
1130
1143
  chunks: assembled.chunks,
@@ -1144,7 +1157,7 @@ async function runBuildContext(query, opts) {
1144
1157
  }
1145
1158
 
1146
1159
  // src/mcp/index.ts
1147
- var version = "0.3.3";
1160
+ var version = "0.3.5";
1148
1161
  var log9 = childLogger("mcp");
1149
1162
  var server = new McpServer({ name: "brain-cache", version });
1150
1163
  server.registerTool(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brain-cache",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Local MCP-first context engine for Claude. Index your codebase, retrieve only what matters, and cut token usage.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- formatTokenSavings
4
- } from "./chunk-GGOUKACO.js";
5
2
  import {
6
3
  countChunkTokens
7
4
  } from "./chunk-5FXXZBZV.js";
5
+ import {
6
+ formatTokenSavings
7
+ } from "./chunk-GGOUKACO.js";
8
8
  import {
9
9
  embedBatchWithRetry
10
10
  } from "./chunk-GR6QXZ4J.js";