brain-cache 0.3.1 → 0.3.3

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.
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-GGOUKACO.js";
5
5
  import {
6
6
  runBuildContext
7
- } from "./chunk-H4XSGUHL.js";
7
+ } from "./chunk-QNPB2UD2.js";
8
8
  import "./chunk-5FXXZBZV.js";
9
9
  import "./chunk-BF5UDEIF.js";
10
10
  import "./chunk-GR6QXZ4J.js";
11
11
  import "./chunk-V4ARVFRG.js";
12
- import "./chunk-6MACVOTO.js";
13
- import "./chunk-MSI4MDIM.js";
12
+ import "./chunk-DTJNPRN6.js";
13
+ import "./chunk-DDDLTKDT.js";
14
14
  import {
15
15
  childLogger
16
16
  } from "./chunk-3SFDFUEX.js";
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runBuildContext
4
- } from "./chunk-H4XSGUHL.js";
4
+ } from "./chunk-QNPB2UD2.js";
5
5
  import "./chunk-5FXXZBZV.js";
6
6
  import "./chunk-BF5UDEIF.js";
7
7
  import "./chunk-GR6QXZ4J.js";
8
8
  import "./chunk-V4ARVFRG.js";
9
- import "./chunk-6MACVOTO.js";
10
- import "./chunk-MSI4MDIM.js";
9
+ import "./chunk-DTJNPRN6.js";
10
+ import "./chunk-DDDLTKDT.js";
11
11
  import "./chunk-3SFDFUEX.js";
12
12
  export {
13
13
  runBuildContext
@@ -38,7 +38,8 @@ var IndexStateSchema = z.object({
38
38
  dimension: z.number().int(),
39
39
  indexedAt: z.string().datetime(),
40
40
  fileCount: z.number().int(),
41
- chunkCount: z.number().int()
41
+ chunkCount: z.number().int(),
42
+ totalTokens: z.number().int().default(0)
42
43
  });
43
44
 
44
45
  // src/services/capability.ts
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IndexStateSchema
4
- } from "./chunk-MSI4MDIM.js";
4
+ } from "./chunk-DDDLTKDT.js";
5
5
  import {
6
6
  DEFAULT_EMBEDDING_DIMENSION,
7
7
  EMBEDDING_DIMENSIONS,
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- assembleContext,
4
- countChunkTokens
3
+ assembleContext
5
4
  } from "./chunk-5FXXZBZV.js";
6
5
  import {
7
6
  RETRIEVAL_STRATEGIES,
@@ -18,16 +17,15 @@ import {
18
17
  import {
19
18
  openDatabase,
20
19
  readIndexState
21
- } from "./chunk-6MACVOTO.js";
20
+ } from "./chunk-DTJNPRN6.js";
22
21
  import {
23
22
  readProfile
24
- } from "./chunk-MSI4MDIM.js";
23
+ } from "./chunk-DDDLTKDT.js";
25
24
  import {
26
25
  DEFAULT_TOKEN_BUDGET
27
26
  } from "./chunk-3SFDFUEX.js";
28
27
 
29
28
  // src/workflows/buildContext.ts
30
- import { readFile } from "fs/promises";
31
29
  import { resolve } from "path";
32
30
  async function runBuildContext(query, opts) {
33
31
  const profile = await readProfile();
@@ -64,15 +62,7 @@ async function runBuildContext(query, opts) {
64
62
  const results = await searchChunks(table, queryVector, strategy);
65
63
  const deduped = deduplicateChunks(results);
66
64
  const assembled = assembleContext(deduped, { maxTokens });
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
- }
65
+ const estimatedWithoutBraincache = indexState.totalTokens;
76
66
  const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - assembled.tokenCount / estimatedWithoutBraincache) * 100) : 0;
77
67
  const result = {
78
68
  content: assembled.content,
package/dist/cli.js CHANGED
@@ -5,23 +5,23 @@ import {
5
5
 
6
6
  // src/cli/index.ts
7
7
  import { Command } from "commander";
8
- var version = "0.3.1";
8
+ var version = "0.3.3";
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-SXC4MWOR.js");
12
+ const { runInit } = await import("./init-ILR3VJNO.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-3RIVSSNB.js");
16
+ const { runDoctor } = await import("./doctor-DRVKTWPW.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-TWA2GDHJ.js");
20
+ const { runIndex } = await import("./workflows-SYWKVVOK.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) => {
24
- const { runSearch } = await import("./search-ZP4NKKAZ.js");
24
+ const { runSearch } = await import("./search-RGK2FEM5.js");
25
25
  await runSearch(query, {
26
26
  limit: parseInt(opts.limit, 10),
27
27
  path: opts.path
@@ -30,12 +30,12 @@ program.command("search").description("Search indexed codebase with a natural la
30
30
  program.command("status").description(
31
31
  "Show index stats: files indexed, chunks stored, last indexed time"
32
32
  ).argument("[path]", "Project root directory (defaults to current directory)").action(async (path) => {
33
- const { runStatus } = await import("./status-JYNMLSXZ.js");
33
+ const { runStatus } = await import("./status-4IWQTGPA.js");
34
34
  await runStatus(path);
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-AHUWIN6M.js");
38
+ const { runBuildContext } = await import("./buildContext-QIMH5LQY.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-GXUB6477.js");
64
+ const { runAskCodebase } = await import("./askCodebase-OAAG35G5.js");
65
65
  const result = await runAskCodebase(question, {
66
66
  path: opts.path,
67
67
  maxContextTokens: parseInt(opts.budget, 10)
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  detectCapabilities,
10
10
  readProfile
11
- } from "./chunk-MSI4MDIM.js";
11
+ } from "./chunk-DDDLTKDT.js";
12
12
  import {
13
13
  PROFILE_PATH
14
14
  } from "./chunk-3SFDFUEX.js";
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  detectCapabilities,
11
11
  writeProfile
12
- } from "./chunk-MSI4MDIM.js";
12
+ } from "./chunk-DDDLTKDT.js";
13
13
  import "./chunk-3SFDFUEX.js";
14
14
 
15
15
  // src/workflows/init.ts
package/dist/mcp.js CHANGED
@@ -91,7 +91,8 @@ var IndexStateSchema = z.object({
91
91
  dimension: z.number().int(),
92
92
  indexedAt: z.string().datetime(),
93
93
  fileCount: z.number().int(),
94
- chunkCount: z.number().int()
94
+ chunkCount: z.number().int(),
95
+ totalTokens: z.number().int().default(0)
95
96
  });
96
97
 
97
98
  // src/lib/config.ts
@@ -796,6 +797,10 @@ async function runIndex(targetPath, opts) {
796
797
  delete updatedHashes[filePath];
797
798
  }
798
799
  const filesToProcess = [...newFiles, ...changedFiles];
800
+ let allFilesTotalTokens = 0;
801
+ for (const [, content] of contentMap) {
802
+ allFilesTotalTokens += countChunkTokens(content);
803
+ }
799
804
  if (filesToProcess.length === 0) {
800
805
  process.stderr.write(`brain-cache: nothing to re-index
801
806
  `);
@@ -811,7 +816,8 @@ async function runIndex(targetPath, opts) {
811
816
  dimension: dim,
812
817
  indexedAt: (/* @__PURE__ */ new Date()).toISOString(),
813
818
  fileCount: totalFiles2,
814
- chunkCount: chunkCount2
819
+ chunkCount: chunkCount2,
820
+ totalTokens: allFilesTotalTokens
815
821
  });
816
822
  process.stderr.write(
817
823
  `brain-cache: indexing complete
@@ -902,7 +908,8 @@ async function runIndex(targetPath, opts) {
902
908
  dimension: dim,
903
909
  indexedAt: (/* @__PURE__ */ new Date()).toISOString(),
904
910
  fileCount: totalFiles,
905
- chunkCount
911
+ chunkCount,
912
+ totalTokens: allFilesTotalTokens
906
913
  });
907
914
  const reductionPct = totalRawTokens > 0 ? Math.round((1 - totalChunkTokens / totalRawTokens) * 100) : 0;
908
915
  const savingsBlock = formatTokenSavings({
@@ -1080,7 +1087,6 @@ async function runSearch(query, opts) {
1080
1087
  }
1081
1088
 
1082
1089
  // src/workflows/buildContext.ts
1083
- import { readFile as readFile5 } from "fs/promises";
1084
1090
  import { resolve as resolve3 } from "path";
1085
1091
  async function runBuildContext(query, opts) {
1086
1092
  const profile = await readProfile();
@@ -1117,15 +1123,7 @@ async function runBuildContext(query, opts) {
1117
1123
  const results = await searchChunks(table, queryVector, strategy);
1118
1124
  const deduped = deduplicateChunks(results);
1119
1125
  const assembled = assembleContext(deduped, { maxTokens });
1120
- const uniqueFiles = [...new Set(assembled.chunks.map((c) => c.filePath))];
1121
- let estimatedWithoutBraincache = 0;
1122
- for (const filePath of uniqueFiles) {
1123
- try {
1124
- const fileContent = await readFile5(filePath, "utf-8");
1125
- estimatedWithoutBraincache += countChunkTokens(fileContent);
1126
- } catch {
1127
- }
1128
- }
1126
+ const estimatedWithoutBraincache = indexState.totalTokens;
1129
1127
  const reductionPct = estimatedWithoutBraincache > 0 ? Math.round((1 - assembled.tokenCount / estimatedWithoutBraincache) * 100) : 0;
1130
1128
  const result = {
1131
1129
  content: assembled.content,
@@ -1146,7 +1144,7 @@ async function runBuildContext(query, opts) {
1146
1144
  }
1147
1145
 
1148
1146
  // src/mcp/index.ts
1149
- var version = "0.3.1";
1147
+ var version = "0.3.3";
1150
1148
  var log9 = childLogger("mcp");
1151
1149
  var server = new McpServer({ name: "brain-cache", version });
1152
1150
  server.registerTool(
@@ -14,10 +14,10 @@ import {
14
14
  import {
15
15
  openDatabase,
16
16
  readIndexState
17
- } from "./chunk-6MACVOTO.js";
17
+ } from "./chunk-DTJNPRN6.js";
18
18
  import {
19
19
  readProfile
20
- } from "./chunk-MSI4MDIM.js";
20
+ } from "./chunk-DDDLTKDT.js";
21
21
  import "./chunk-3SFDFUEX.js";
22
22
 
23
23
  // src/workflows/search.ts
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readIndexState
4
- } from "./chunk-6MACVOTO.js";
4
+ } from "./chunk-DTJNPRN6.js";
5
5
  import {
6
6
  readProfile
7
- } from "./chunk-MSI4MDIM.js";
7
+ } from "./chunk-DDDLTKDT.js";
8
8
  import "./chunk-3SFDFUEX.js";
9
9
 
10
10
  // src/workflows/status.ts
@@ -20,10 +20,10 @@ import {
20
20
  readFileHashes,
21
21
  writeFileHashes,
22
22
  writeIndexState
23
- } from "./chunk-6MACVOTO.js";
23
+ } from "./chunk-DTJNPRN6.js";
24
24
  import {
25
25
  readProfile
26
- } from "./chunk-MSI4MDIM.js";
26
+ } from "./chunk-DDDLTKDT.js";
27
27
  import {
28
28
  DEFAULT_BATCH_SIZE,
29
29
  DEFAULT_EMBEDDING_DIMENSION,
@@ -345,6 +345,10 @@ async function runIndex(targetPath, opts) {
345
345
  delete updatedHashes[filePath];
346
346
  }
347
347
  const filesToProcess = [...newFiles, ...changedFiles];
348
+ let allFilesTotalTokens = 0;
349
+ for (const [, content] of contentMap) {
350
+ allFilesTotalTokens += countChunkTokens(content);
351
+ }
348
352
  if (filesToProcess.length === 0) {
349
353
  process.stderr.write(`brain-cache: nothing to re-index
350
354
  `);
@@ -360,7 +364,8 @@ async function runIndex(targetPath, opts) {
360
364
  dimension: dim,
361
365
  indexedAt: (/* @__PURE__ */ new Date()).toISOString(),
362
366
  fileCount: totalFiles2,
363
- chunkCount: chunkCount2
367
+ chunkCount: chunkCount2,
368
+ totalTokens: allFilesTotalTokens
364
369
  });
365
370
  process.stderr.write(
366
371
  `brain-cache: indexing complete
@@ -451,7 +456,8 @@ async function runIndex(targetPath, opts) {
451
456
  dimension: dim,
452
457
  indexedAt: (/* @__PURE__ */ new Date()).toISOString(),
453
458
  fileCount: totalFiles,
454
- chunkCount
459
+ chunkCount,
460
+ totalTokens: allFilesTotalTokens
455
461
  });
456
462
  const reductionPct = totalRawTokens > 0 ? Math.round((1 - totalChunkTokens / totalRawTokens) * 100) : 0;
457
463
  const savingsBlock = formatTokenSavings({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brain-cache",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
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",
@@ -26,6 +26,7 @@
26
26
  "scripts": {
27
27
  "dev": "tsx src/cli/index.ts",
28
28
  "build": "tsup",
29
+ "prepare": "npm run build",
29
30
  "link": "npm link",
30
31
  "test": "vitest run",
31
32
  "test:watch": "vitest"