ctxloom-pro 1.7.2 → 1.7.4

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 CHANGED
@@ -69,7 +69,7 @@ The full first-run flow is **one install + one trial + one init per project.** E
69
69
  npm install -g ctxloom-pro
70
70
  ```
71
71
 
72
- > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.1`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
72
+ > **For local trial / dev use the unpinned command above is fine.** For unattended CI usage, pin to the exact version (`ctxloom-pro@1.7.4`) so future CLI releases don't silently desync your agent-spec coverage — see the workflow example below.
73
73
 
74
74
  ### 2 — Start your free trial (once per email)
75
75
 
@@ -383,7 +383,7 @@ jobs:
383
383
  # Exact pin (not `@^1`) so future CLI releases that add/remove MCP
384
384
  # tools don't silently desync your reviewer-agent specs. Bump on
385
385
  # every release; see CHANGELOG.md for the live version table.
386
- - run: npm install -g ctxloom-pro@1.7.1
386
+ - run: npm install -g ctxloom-pro@1.7.4
387
387
  - run: ctxloom index
388
388
  - run: ctxloom rules check --json
389
389
  ```
@@ -101,71 +101,28 @@ function resolveEmbeddingModel(env = process.env) {
101
101
  };
102
102
  }
103
103
  function collectFiles(dir, results = []) {
104
- const IGNORED_DIRS = /* @__PURE__ */ new Set([
105
- // Build artifacts + dependency caches
106
- "node_modules",
107
- "dist",
108
- "build",
109
- "out",
110
- "target",
111
- "coverage",
112
- ".cache",
113
- ".turbo",
114
- ".next",
115
- ".nuxt",
116
- // Version control + ctxloom state
117
- ".git",
118
- ".ctxloom",
119
- // Other tools' working state (often contains duplicated source)
120
- ".claude",
121
- ".code-review-graph",
122
- ".vscode-test"
123
- ]);
124
- const SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
125
- ".ts",
126
- ".tsx",
127
- ".js",
128
- ".jsx",
129
- ".mjs",
130
- ".vue",
131
- ".py",
132
- ".rs",
133
- ".go",
134
- ".java",
135
- ".cs",
136
- ".rb",
137
- ".kt",
138
- ".kts",
139
- ".swift",
140
- ".php",
141
- ".dart",
142
- ".c",
143
- ".cpp",
144
- ".h",
145
- ".md",
146
- ".json",
147
- ".yaml",
148
- ".yml",
149
- ".toml",
150
- ".ipynb"
151
- ]);
152
104
  const entries = fs3.readdirSync(dir, { withFileTypes: true });
153
105
  for (const entry of entries) {
154
106
  const fullPath = path3.join(dir, entry.name);
155
107
  if (entry.isDirectory()) {
156
- if (!IGNORED_DIRS.has(entry.name)) {
108
+ if (!isIgnoredDir(entry.name)) {
157
109
  collectFiles(fullPath, results);
158
110
  }
159
111
  } else if (entry.isFile()) {
160
112
  const ext = path3.extname(entry.name);
161
- if (SUPPORTED_EXTENSIONS.has(ext)) {
113
+ if (INDEX_SUPPORTED_EXTENSIONS.has(ext)) {
162
114
  results.push(fullPath);
163
115
  }
164
116
  }
165
117
  }
166
118
  return results;
167
119
  }
168
- var MODEL_REGISTRY, ACTIVE_MODEL, EMBEDDING_DIMENSION, MODEL_ID, MIN_MODEL_BYTES;
120
+ function isIgnoredDir(name) {
121
+ if (INDEXER_IGNORED_DIRS.has(name)) return true;
122
+ if (name.endsWith(".egg-info") || name.endsWith(".dist-info")) return true;
123
+ return false;
124
+ }
125
+ var MODEL_REGISTRY, ACTIVE_MODEL, EMBEDDING_DIMENSION, MODEL_ID, MIN_MODEL_BYTES, INDEXER_IGNORED_DIRS, INDEX_SUPPORTED_EXTENSIONS;
169
126
  var init_embedder = __esm({
170
127
  "../../packages/core/src/indexer/embedder.ts"() {
171
128
  "use strict";
@@ -196,6 +153,69 @@ var init_embedder = __esm({
196
153
  EMBEDDING_DIMENSION = ACTIVE_MODEL.dim;
197
154
  MODEL_ID = ACTIVE_MODEL.hfId;
198
155
  MIN_MODEL_BYTES = ACTIVE_MODEL.minBytes;
156
+ INDEXER_IGNORED_DIRS = /* @__PURE__ */ new Set([
157
+ // Build artifacts + dependency caches (JS/TS, Rust, Java)
158
+ "node_modules",
159
+ "dist",
160
+ "build",
161
+ "out",
162
+ "target",
163
+ "coverage",
164
+ ".cache",
165
+ ".turbo",
166
+ ".next",
167
+ ".nuxt",
168
+ // Python virtualenvs + caches. Real-world repro: EasyMoney (a 63-
169
+ // source-file FastAPI project) had a `.venv/` with 8,192 installed-
170
+ // package files. Pre-fix, `ctxloom index` reported 8,120 files /
171
+ // 14,138 edges instead of the expected 63 / 97, because none of the
172
+ // standard Python virtualenv/cache directory names were in this set.
173
+ // The `__pycache__` + `.pytest_cache` + `.ruff_cache` + `.mypy_cache`
174
+ // additions catch the bulk of Python noise on top of the venv.
175
+ ".venv",
176
+ "venv",
177
+ "env",
178
+ "__pycache__",
179
+ ".pytest_cache",
180
+ ".ruff_cache",
181
+ ".mypy_cache",
182
+ ".tox",
183
+ // Version control + ctxloom state
184
+ ".git",
185
+ ".ctxloom",
186
+ // Other tools' working state (often contains duplicated source)
187
+ ".claude",
188
+ ".code-review-graph",
189
+ ".vscode-test"
190
+ ]);
191
+ INDEX_SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
192
+ ".ts",
193
+ ".tsx",
194
+ ".js",
195
+ ".jsx",
196
+ ".mjs",
197
+ ".vue",
198
+ ".py",
199
+ ".rs",
200
+ ".go",
201
+ ".java",
202
+ ".cs",
203
+ ".rb",
204
+ ".kt",
205
+ ".kts",
206
+ ".swift",
207
+ ".php",
208
+ ".dart",
209
+ ".c",
210
+ ".cpp",
211
+ ".h",
212
+ ".md",
213
+ ".json",
214
+ ".yaml",
215
+ ".yml",
216
+ ".toml",
217
+ ".ipynb"
218
+ ]);
199
219
  }
200
220
  });
201
221
 
@@ -2909,7 +2929,7 @@ var CallGraphIndex = class _CallGraphIndex {
2909
2929
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2910
2930
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2911
2931
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2912
- var CTXLOOM_VERSION = "1.7.2".length > 0 ? "1.7.2" : "dev";
2932
+ var CTXLOOM_VERSION = "1.7.4".length > 0 ? "1.7.4" : "dev";
2913
2933
  var SNAPSHOT_SCHEMA_VERSION = 2;
2914
2934
  function compareCtxloomVersions(snapshotVer, currentVer) {
2915
2935
  if (snapshotVer === currentVer) return "same";
@@ -12141,7 +12161,7 @@ function resolveTelemetryLevel() {
12141
12161
  }
12142
12162
  var TELEMETRY_LEVEL = resolveTelemetryLevel();
12143
12163
  var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
12144
- var CTXLOOM_VERSION2 = "1.7.2".length > 0 ? "1.7.2" : "dev";
12164
+ var CTXLOOM_VERSION2 = "1.7.4".length > 0 ? "1.7.4" : "dev";
12145
12165
  var POSTHOG_HOST = "https://eu.i.posthog.com";
12146
12166
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
12147
12167
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -12382,12 +12402,17 @@ those instead of guessing.
12382
12402
  | \`ctx_architecture_overview\` | High-level codebase map |
12383
12403
  | \`ctx_refactor_preview\` / \`ctx_apply_refactor\` | Plan a rename |
12384
12404
 
12385
- ### Hooks keep the graph fresh
12386
-
12387
- \`ctxloom init\` installed a PostToolUse hook on \`Write|Edit\` that
12388
- runs \`ctxloom update --incremental --quiet\` \u2014 so the graph is
12389
- always up to date when you query it. No "did the index update yet?"
12390
- guessing.`;
12405
+ ### How the graph stays fresh
12406
+
12407
+ The ctxloom MCP server's built-in \`FileWatcher\` (chokidar with 200ms
12408
+ debounce) keeps the graph + vectors in sync in real time as you edit
12409
+ files \u2014 no manual reindex needed. A belt-and-suspenders PostToolUse
12410
+ hook (\`ctxloom update --incremental --quiet\`) is also installed; in
12411
+ v1.7.3+ it's a no-op that exits cleanly. In earlier versions the
12412
+ \`update\` subcommand silently didn't exist, which made the hook spawn
12413
+ orphan MCP servers and accumulate LanceDB fragments \u2014 if you ever see
12414
+ \`ctx_search\` stalling for minutes, run \`ctxloom vectors-cleanup\`
12415
+ to fix.`;
12391
12416
  var SESSION_START_HEADER = `#!/usr/bin/env bash
12392
12417
  # ctxloom \u2014 agent-harness session-start hook
12393
12418
  # Generated by \`ctxloom init\`. Re-run \`ctxloom init\` to update.
@@ -0,0 +1,9 @@
1
+ import {
2
+ VectorStore
3
+ } from "./chunk-XQEQLXY5.js";
4
+ import "./chunk-JZOJC3S7.js";
5
+ import "./chunk-TYDMSHV7.js";
6
+ export {
7
+ VectorStore
8
+ };
9
+ //# sourceMappingURL=VectorStore-5ALWL6XF.js.map
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  VectorStore
3
- } from "./chunk-7S2ELKNU.js";
3
+ } from "./chunk-XQEQLXY5.js";
4
4
  import {
5
- INDEXER_IGNORED_DIRS,
6
5
  collectFiles,
7
- generateEmbedding
8
- } from "./chunk-6FGTNOCP.js";
6
+ generateEmbedding,
7
+ isIgnoredDir
8
+ } from "./chunk-JZOJC3S7.js";
9
9
  import {
10
10
  diskSink,
11
11
  readEvents
@@ -2705,7 +2705,7 @@ var CallGraphIndex = class _CallGraphIndex {
2705
2705
  var TS_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".vue"]);
2706
2706
  var PY_EXTENSIONS = /* @__PURE__ */ new Set([".py", ".ipynb"]);
2707
2707
  var AST_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".py", ".go", ".rs", ".java", ".cs", ".rb", ".kt", ".kts", ".swift", ".ipynb", ".php", ".dart"]);
2708
- var CTXLOOM_VERSION = "1.7.2".length > 0 ? "1.7.2" : "dev";
2708
+ var CTXLOOM_VERSION = "1.7.4".length > 0 ? "1.7.4" : "dev";
2709
2709
  var SNAPSHOT_SCHEMA_VERSION = 2;
2710
2710
  function compareCtxloomVersions(snapshotVer, currentVer) {
2711
2711
  if (snapshotVer === currentVer) return "same";
@@ -8687,7 +8687,7 @@ function registerFullTextSearchTool(registry, ctx) {
8687
8687
  };
8688
8688
  if (mode === "semantic") {
8689
8689
  try {
8690
- const { generateEmbedding: generateEmbedding2 } = await import("./embedder-2JWDJUE2.js");
8690
+ const { generateEmbedding: generateEmbedding2 } = await import("./embedder-4MM7D3UE.js");
8691
8691
  const store = await ctx.getStore(project_root);
8692
8692
  const embedding = await generateEmbedding2(query);
8693
8693
  const results = await store.search(embedding, limit);
@@ -8724,7 +8724,7 @@ function registerFullTextSearchTool(registry, ctx) {
8724
8724
  let merged = keywordResults.slice(0, limit);
8725
8725
  if (mode === "hybrid") {
8726
8726
  try {
8727
- const { generateEmbedding: generateEmbedding2 } = await import("./embedder-2JWDJUE2.js");
8727
+ const { generateEmbedding: generateEmbedding2 } = await import("./embedder-4MM7D3UE.js");
8728
8728
  const store = await ctx.getStore(project_root);
8729
8729
  const embedding = await generateEmbedding2(query);
8730
8730
  const vectorResults = await store.search(embedding, Math.ceil(limit / 2));
@@ -10599,7 +10599,7 @@ import chokidar from "chokidar";
10599
10599
  function isIgnoredPath(absPath) {
10600
10600
  const segments = absPath.split(/[\\/]/);
10601
10601
  for (const seg of segments) {
10602
- if (INDEXER_IGNORED_DIRS.has(seg)) return true;
10602
+ if (isIgnoredDir(seg)) return true;
10603
10603
  }
10604
10604
  return false;
10605
10605
  }
@@ -10959,7 +10959,7 @@ var TELEMETRY_DISABLED = TELEMETRY_LEVEL === "off";
10959
10959
  function getTelemetryLevel() {
10960
10960
  return TELEMETRY_LEVEL;
10961
10961
  }
10962
- var CTXLOOM_VERSION2 = "1.7.2".length > 0 ? "1.7.2" : "dev";
10962
+ var CTXLOOM_VERSION2 = "1.7.4".length > 0 ? "1.7.4" : "dev";
10963
10963
  var POSTHOG_HOST = "https://eu.i.posthog.com";
10964
10964
  var POSTHOG_KEY = process.env["POSTHOG_API_KEY"] ?? (true ? "phc_CiDkmFLcZ2K6uCpcoSUQLmFrnnUvsyXGhSxopX5TVKE6" : "");
10965
10965
  var SENTRY_DSN = process.env["SENTRY_DSN"] ?? (true ? "https://81c94a0f04a8e242dee493ac1e17f733@o4508531702497280.ingest.de.sentry.io/4511256875368528" : "");
@@ -11670,12 +11670,17 @@ those instead of guessing.
11670
11670
  | \`ctx_architecture_overview\` | High-level codebase map |
11671
11671
  | \`ctx_refactor_preview\` / \`ctx_apply_refactor\` | Plan a rename |
11672
11672
 
11673
- ### Hooks keep the graph fresh
11674
-
11675
- \`ctxloom init\` installed a PostToolUse hook on \`Write|Edit\` that
11676
- runs \`ctxloom update --incremental --quiet\` \u2014 so the graph is
11677
- always up to date when you query it. No "did the index update yet?"
11678
- guessing.`;
11673
+ ### How the graph stays fresh
11674
+
11675
+ The ctxloom MCP server's built-in \`FileWatcher\` (chokidar with 200ms
11676
+ debounce) keeps the graph + vectors in sync in real time as you edit
11677
+ files \u2014 no manual reindex needed. A belt-and-suspenders PostToolUse
11678
+ hook (\`ctxloom update --incremental --quiet\`) is also installed; in
11679
+ v1.7.3+ it's a no-op that exits cleanly. In earlier versions the
11680
+ \`update\` subcommand silently didn't exist, which made the hook spawn
11681
+ orphan MCP servers and accumulate LanceDB fragments \u2014 if you ever see
11682
+ \`ctx_search\` stalling for minutes, run \`ctxloom vectors-cleanup\`
11683
+ to fix.`;
11679
11684
  var SESSION_START_HEADER = `#!/usr/bin/env bash
11680
11685
  # ctxloom \u2014 agent-harness session-start hook
11681
11686
  # Generated by \`ctxloom init\`. Re-run \`ctxloom init\` to update.
@@ -12635,4 +12640,4 @@ export {
12635
12640
  skillFilePath,
12636
12641
  installHarness
12637
12642
  };
12638
- //# sourceMappingURL=chunk-QL5UJTQL.js.map
12643
+ //# sourceMappingURL=chunk-AF76TJPL.js.map
@@ -153,64 +153,16 @@ async function generateEmbeddingBatch(texts) {
153
153
  return data;
154
154
  }
155
155
  function collectFiles(dir, results = []) {
156
- const IGNORED_DIRS = /* @__PURE__ */ new Set([
157
- // Build artifacts + dependency caches
158
- "node_modules",
159
- "dist",
160
- "build",
161
- "out",
162
- "target",
163
- "coverage",
164
- ".cache",
165
- ".turbo",
166
- ".next",
167
- ".nuxt",
168
- // Version control + ctxloom state
169
- ".git",
170
- ".ctxloom",
171
- // Other tools' working state (often contains duplicated source)
172
- ".claude",
173
- ".code-review-graph",
174
- ".vscode-test"
175
- ]);
176
- const SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
177
- ".ts",
178
- ".tsx",
179
- ".js",
180
- ".jsx",
181
- ".mjs",
182
- ".vue",
183
- ".py",
184
- ".rs",
185
- ".go",
186
- ".java",
187
- ".cs",
188
- ".rb",
189
- ".kt",
190
- ".kts",
191
- ".swift",
192
- ".php",
193
- ".dart",
194
- ".c",
195
- ".cpp",
196
- ".h",
197
- ".md",
198
- ".json",
199
- ".yaml",
200
- ".yml",
201
- ".toml",
202
- ".ipynb"
203
- ]);
204
156
  const entries = fs.readdirSync(dir, { withFileTypes: true });
205
157
  for (const entry of entries) {
206
158
  const fullPath = path.join(dir, entry.name);
207
159
  if (entry.isDirectory()) {
208
- if (!IGNORED_DIRS.has(entry.name)) {
160
+ if (!isIgnoredDir(entry.name)) {
209
161
  collectFiles(fullPath, results);
210
162
  }
211
163
  } else if (entry.isFile()) {
212
164
  const ext = path.extname(entry.name);
213
- if (SUPPORTED_EXTENSIONS.has(ext)) {
165
+ if (INDEX_SUPPORTED_EXTENSIONS.has(ext)) {
214
166
  results.push(fullPath);
215
167
  }
216
168
  }
@@ -222,7 +174,7 @@ async function* collectFilesStream(dir) {
222
174
  for (const entry of entries) {
223
175
  const fullPath = path.join(dir, entry.name);
224
176
  if (entry.isDirectory()) {
225
- if (!INDEX_IGNORED_DIRS.has(entry.name)) {
177
+ if (!isIgnoredDir(entry.name)) {
226
178
  yield* collectFilesStream(fullPath);
227
179
  }
228
180
  } else if (entry.isFile()) {
@@ -233,7 +185,7 @@ async function* collectFilesStream(dir) {
233
185
  }
234
186
  }
235
187
  var INDEXER_IGNORED_DIRS = /* @__PURE__ */ new Set([
236
- // Build artifacts + dependency caches
188
+ // Build artifacts + dependency caches (JS/TS, Rust, Java)
237
189
  "node_modules",
238
190
  "dist",
239
191
  "build",
@@ -244,6 +196,21 @@ var INDEXER_IGNORED_DIRS = /* @__PURE__ */ new Set([
244
196
  ".turbo",
245
197
  ".next",
246
198
  ".nuxt",
199
+ // Python virtualenvs + caches. Real-world repro: EasyMoney (a 63-
200
+ // source-file FastAPI project) had a `.venv/` with 8,192 installed-
201
+ // package files. Pre-fix, `ctxloom index` reported 8,120 files /
202
+ // 14,138 edges instead of the expected 63 / 97, because none of the
203
+ // standard Python virtualenv/cache directory names were in this set.
204
+ // The `__pycache__` + `.pytest_cache` + `.ruff_cache` + `.mypy_cache`
205
+ // additions catch the bulk of Python noise on top of the venv.
206
+ ".venv",
207
+ "venv",
208
+ "env",
209
+ "__pycache__",
210
+ ".pytest_cache",
211
+ ".ruff_cache",
212
+ ".mypy_cache",
213
+ ".tox",
247
214
  // Version control + ctxloom state
248
215
  ".git",
249
216
  ".ctxloom",
@@ -252,7 +219,11 @@ var INDEXER_IGNORED_DIRS = /* @__PURE__ */ new Set([
252
219
  ".code-review-graph",
253
220
  ".vscode-test"
254
221
  ]);
255
- var INDEX_IGNORED_DIRS = INDEXER_IGNORED_DIRS;
222
+ function isIgnoredDir(name) {
223
+ if (INDEXER_IGNORED_DIRS.has(name)) return true;
224
+ if (name.endsWith(".egg-info") || name.endsWith(".dist-info")) return true;
225
+ return false;
226
+ }
256
227
  var INDEX_SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
257
228
  ".ts",
258
229
  ".tsx",
@@ -282,7 +253,7 @@ var INDEX_SUPPORTED_EXTENSIONS = /* @__PURE__ */ new Set([
282
253
  ".ipynb"
283
254
  ]);
284
255
  async function indexDirectory(rootDir, onProgress) {
285
- const { VectorStore } = await import("./VectorStore-WDL3H7QT.js");
256
+ const { VectorStore } = await import("./VectorStore-5ALWL6XF.js");
286
257
  const store = new VectorStore(path.join(rootDir, ".ctxloom", "vectors.lancedb"));
287
258
  await store.init();
288
259
  let indexed = 0;
@@ -390,8 +361,9 @@ export {
390
361
  collectFiles,
391
362
  collectFilesStream,
392
363
  INDEXER_IGNORED_DIRS,
364
+ isIgnoredDir,
393
365
  indexDirectory,
394
366
  EMBEDDING_MODEL_ID,
395
367
  getActiveEmbeddingModel
396
368
  };
397
- //# sourceMappingURL=chunk-6FGTNOCP.js.map
369
+ //# sourceMappingURL=chunk-JZOJC3S7.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  EMBEDDING_DIMENSION,
3
3
  EMBEDDING_MODEL_ID
4
- } from "./chunk-6FGTNOCP.js";
4
+ } from "./chunk-JZOJC3S7.js";
5
5
  import {
6
6
  logger
7
7
  } from "./chunk-TYDMSHV7.js";
@@ -307,4 +307,4 @@ Or revert CTXLOOM_EMBEDDING_MODEL to "${existing.model}" to keep the existing in
307
307
  export {
308
308
  VectorStore
309
309
  };
310
- //# sourceMappingURL=chunk-7S2ELKNU.js.map
310
+ //# sourceMappingURL=chunk-XQEQLXY5.js.map
@@ -8,8 +8,9 @@ import {
8
8
  generateEmbeddingBatch,
9
9
  getActiveEmbeddingModel,
10
10
  indexDirectory,
11
+ isIgnoredDir,
11
12
  resolveEmbeddingModel
12
- } from "./chunk-6FGTNOCP.js";
13
+ } from "./chunk-JZOJC3S7.js";
13
14
  import "./chunk-TYDMSHV7.js";
14
15
  export {
15
16
  EMBEDDING_DIMENSION,
@@ -21,6 +22,7 @@ export {
21
22
  generateEmbeddingBatch,
22
23
  getActiveEmbeddingModel,
23
24
  indexDirectory,
25
+ isIgnoredDir,
24
26
  resolveEmbeddingModel
25
27
  };
26
- //# sourceMappingURL=embedder-2JWDJUE2.js.map
28
+ //# sourceMappingURL=embedder-4MM7D3UE.js.map
package/dist/index.js CHANGED
@@ -47,18 +47,19 @@ import {
47
47
  validateDefaultRoot,
48
48
  wrapWithIndexingEnvelope,
49
49
  writeCODEOWNERS
50
- } from "./chunk-QL5UJTQL.js";
50
+ } from "./chunk-AF76TJPL.js";
51
51
  import {
52
52
  addCtxloomToConfig,
53
53
  detectInstalledClients
54
54
  } from "./chunk-YHLMQVBV.js";
55
55
  import {
56
56
  VectorStore
57
- } from "./chunk-7S2ELKNU.js";
57
+ } from "./chunk-XQEQLXY5.js";
58
58
  import {
59
+ collectFiles,
59
60
  generateEmbedding,
60
61
  indexDirectory
61
- } from "./chunk-6FGTNOCP.js";
62
+ } from "./chunk-JZOJC3S7.js";
62
63
  import "./chunk-5I6CJITG.js";
63
64
  import {
64
65
  logger
@@ -435,6 +436,33 @@ async function startServer(opts = {}) {
435
436
  }
436
437
  } catch {
437
438
  }
439
+ if (PROJECT_ROOT) {
440
+ try {
441
+ const fragCounts = inspectVectorsDb(PROJECT_ROOT);
442
+ const fragTotal = fragCounts.txn + fragCounts.manifest + fragCounts.lance;
443
+ if (fragTotal > 500) {
444
+ const sourceFileCount = collectFiles(PROJECT_ROOT).length;
445
+ const FRAGMENT_RATIO_THRESHOLD = 50;
446
+ if (sourceFileCount > 0 && fragTotal > sourceFileCount * FRAGMENT_RATIO_THRESHOLD) {
447
+ const mb = (fragCounts.totalBytes / 1024 / 1024).toFixed(0);
448
+ logger.warn(
449
+ "LanceDB fragment count is pathological \u2014 MCP tools may stall for minutes on first call. Run `ctxloom vectors-cleanup` (close other ctxloom MCP servers first) to fix.",
450
+ {
451
+ sourceFiles: sourceFileCount,
452
+ fragments: fragTotal,
453
+ ratio: Math.round(fragTotal / sourceFileCount),
454
+ ratioThreshold: FRAGMENT_RATIO_THRESHOLD,
455
+ sizeMB: Number(mb),
456
+ txn: fragCounts.txn,
457
+ manifest: fragCounts.manifest,
458
+ lance: fragCounts.lance
459
+ }
460
+ );
461
+ }
462
+ }
463
+ } catch {
464
+ }
465
+ }
438
466
  if (!ctx.noDefaultMode) {
439
467
  Promise.all([ctx.getGraph(), generateEmbedding("warmup")]).then(async ([graph]) => {
440
468
  logger.info("Ready", { edges: graph.edgeCount() });
@@ -1039,7 +1067,7 @@ try {
1039
1067
  } catch {
1040
1068
  }
1041
1069
  var args = process.argv.slice(2);
1042
- var ctxloomVersion = "1.7.2".length > 0 ? "1.7.2" : "dev";
1070
+ var ctxloomVersion = "1.7.4".length > 0 ? "1.7.4" : "dev";
1043
1071
  if (args.includes("--version") || args.includes("-v")) {
1044
1072
  process.stdout.write(`ctxloom ${ctxloomVersion}
1045
1073
  `);
@@ -1107,12 +1135,34 @@ function buildActivityFromOverlay(store) {
1107
1135
  lastCommitTimestamp
1108
1136
  }));
1109
1137
  }
1110
- var LICENSE_GATE_BYPASS_COMMANDS = /* @__PURE__ */ new Set(["trial", "activate", "deactivate", "status", "budget-stats", "--help"]);
1138
+ var LICENSE_GATE_BYPASS_COMMANDS = /* @__PURE__ */ new Set(["trial", "activate", "deactivate", "status", "budget-stats", "--help", "update"]);
1139
+ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
1140
+ "trial",
1141
+ "activate",
1142
+ "deactivate",
1143
+ "status",
1144
+ "init",
1145
+ "index",
1146
+ "setup",
1147
+ "install-pr-bot",
1148
+ "register",
1149
+ "repos",
1150
+ "grammars",
1151
+ "vectors-cleanup",
1152
+ "budget-stats",
1153
+ "dashboard",
1154
+ "review-suggest",
1155
+ "authors-sync",
1156
+ "rules",
1157
+ "update",
1158
+ "--help",
1159
+ "-h"
1160
+ ]);
1111
1161
  async function checkLicense() {
1112
1162
  if (command !== void 0 && LICENSE_GATE_BYPASS_COMMANDS.has(command)) return;
1113
1163
  const ciKey = process.env["CTXLOOM_LICENSE_KEY"];
1114
1164
  if (ciKey) {
1115
- const { ApiClient } = await import("./src-GTPLDFUS.js");
1165
+ const { ApiClient } = await import("./src-ZUDJHQ3T.js");
1116
1166
  const client = new ApiClient(process.env["CTXLOOM_API_BASE"]);
1117
1167
  try {
1118
1168
  const result = await client.validate(ciKey, "ci-ephemeral");
@@ -1339,8 +1389,23 @@ async function main() {
1339
1389
  if (command !== void 0 && shouldEmitInstallCompleted()) {
1340
1390
  track("install_completed", { command });
1341
1391
  }
1392
+ if (command !== void 0 && !KNOWN_COMMANDS.has(command)) {
1393
+ process.stderr.write(
1394
+ `${error(`Unknown command: ${style.bold(String(command))}`)}
1395
+
1396
+ Run ${style.highlight("ctxloom --help")} for the list of available commands.
1397
+ To start the MCP server, run ${style.highlight("ctxloom")} with no arguments.
1398
+
1399
+ `
1400
+ );
1401
+ process.exit(1);
1402
+ }
1342
1403
  await checkLicense();
1343
1404
  switch (command) {
1405
+ case void 0: {
1406
+ await startServer({ withGit, gitWindowDays });
1407
+ break;
1408
+ }
1344
1409
  case "trial": {
1345
1410
  await runTrial();
1346
1411
  break;
@@ -1490,7 +1555,7 @@ async function main() {
1490
1555
  }
1491
1556
  if (!skipHarness) {
1492
1557
  process.stdout.write("\n");
1493
- const { installHarness } = await import("./src-GTPLDFUS.js");
1558
+ const { installHarness } = await import("./src-ZUDJHQ3T.js");
1494
1559
  const h = installHarness({ cwd: initRoot, dryRun, force, extraHosts });
1495
1560
  const harnessFiles = [
1496
1561
  h.claudeMd,
@@ -1553,7 +1618,7 @@ async function main() {
1553
1618
  process.exit(1);
1554
1619
  }
1555
1620
  if (alias !== void 0) {
1556
- const { validateAlias } = await import("./src-GTPLDFUS.js");
1621
+ const { validateAlias } = await import("./src-ZUDJHQ3T.js");
1557
1622
  const v = validateAlias(alias);
1558
1623
  if (!v.ok) {
1559
1624
  console.error(`[ctxloom] Invalid alias: ${v.reason}`);
@@ -1912,7 +1977,7 @@ Suggested reviewers for ${files.length} file(s):`);
1912
1977
  process.stderr.write("[ctxloom] --limit must be a non-negative integer (0 for unlimited)\n");
1913
1978
  process.exit(2);
1914
1979
  }
1915
- const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-GTPLDFUS.js");
1980
+ const { loadRulesConfig, RulesChecker, formatText, formatJson, RulesConfigError } = await import("./src-ZUDJHQ3T.js");
1916
1981
  let config;
1917
1982
  try {
1918
1983
  config = await loadRulesConfig(root);
@@ -1936,7 +2001,7 @@ Suggested reviewers for ${files.length} file(s):`);
1936
2001
  }
1937
2002
  let graph;
1938
2003
  if (useSnapshot) {
1939
- const { DependencyGraph: DG } = await import("./src-GTPLDFUS.js");
2004
+ const { DependencyGraph: DG } = await import("./src-ZUDJHQ3T.js");
1940
2005
  graph = new DG();
1941
2006
  const loaded = await graph.loadSnapshotOnly(root);
1942
2007
  if (!loaded) {
@@ -1945,7 +2010,7 @@ Suggested reviewers for ${files.length} file(s):`);
1945
2010
  }
1946
2011
  } else {
1947
2012
  process.stderr.write("[ctxloom] Building dependency graph...\n");
1948
- const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-GTPLDFUS.js");
2013
+ const { ASTParser: ASTParser2, DependencyGraph: DependencyGraph2 } = await import("./src-ZUDJHQ3T.js");
1949
2014
  let parser;
1950
2015
  try {
1951
2016
  parser = new ASTParser2();
@@ -2062,10 +2127,23 @@ Tools Exposed:
2062
2127
  `);
2063
2128
  break;
2064
2129
  }
2065
- default: {
2066
- await startServer({ withGit, gitWindowDays });
2130
+ case "update": {
2131
+ const isQuiet = args.includes("--quiet");
2132
+ if (!isQuiet) {
2133
+ process.stdout.write(
2134
+ `${success("ctxloom update: no-op (MCP server FileWatcher handles incremental updates)")}
2135
+ `
2136
+ );
2137
+ }
2067
2138
  break;
2068
2139
  }
2140
+ default: {
2141
+ process.stderr.write(
2142
+ `${error(`Internal error: unhandled command '${String(command)}' reached switch default. This indicates KNOWN_COMMANDS and the switch are out of sync.`)}
2143
+ `
2144
+ );
2145
+ process.exit(1);
2146
+ }
2069
2147
  }
2070
2148
  }
2071
2149
  main().catch((err) => {
@@ -132,16 +132,18 @@ import {
132
132
  wrapBlock,
133
133
  wrapWithIndexingEnvelope,
134
134
  writeCODEOWNERS
135
- } from "./chunk-QL5UJTQL.js";
135
+ } from "./chunk-AF76TJPL.js";
136
136
  import {
137
137
  VectorStore
138
- } from "./chunk-7S2ELKNU.js";
138
+ } from "./chunk-XQEQLXY5.js";
139
139
  import {
140
140
  EMBEDDING_DIMENSION,
141
+ INDEXER_IGNORED_DIRS,
141
142
  collectFiles,
142
143
  generateEmbedding,
143
- indexDirectory
144
- } from "./chunk-6FGTNOCP.js";
144
+ indexDirectory,
145
+ isIgnoredDir
146
+ } from "./chunk-JZOJC3S7.js";
145
147
  import {
146
148
  filenameForDate,
147
149
  readEvents,
@@ -182,6 +184,7 @@ export {
182
184
  GrammarLoader,
183
185
  GraphExporter,
184
186
  HOST_ADAPTERS,
187
+ INDEXER_IGNORED_DIRS,
185
188
  InvalidKeyError,
186
189
  LicenseRequiredError,
187
190
  LicenseRevokedError,
@@ -256,6 +259,7 @@ export {
256
259
  inspectVectorsDb,
257
260
  installHarness,
258
261
  isActive,
262
+ isIgnoredDir,
259
263
  isSiloed,
260
264
  learnSuggestionsFromTelemetry,
261
265
  listNamedSnapshots,
@@ -300,4 +304,4 @@ export {
300
304
  wrapWithIndexingEnvelope,
301
305
  writeCODEOWNERS
302
306
  };
303
- //# sourceMappingURL=src-GTPLDFUS.js.map
307
+ //# sourceMappingURL=src-ZUDJHQ3T.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  VectorStore
3
- } from "../chunk-7S2ELKNU.js";
3
+ } from "../chunk-XQEQLXY5.js";
4
4
  import {
5
5
  generateEmbedding
6
- } from "../chunk-6FGTNOCP.js";
6
+ } from "../chunk-JZOJC3S7.js";
7
7
  import "../chunk-TYDMSHV7.js";
8
8
 
9
9
  // packages/core/src/workers/indexerWorker.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxloom-pro",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "ctxloom — The Universal Code Context Engine. A local-first MCP server providing intelligent code context via hybrid Vector + AST + Graph search with Skeletonization (92% token reduction).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,9 +0,0 @@
1
- import {
2
- VectorStore
3
- } from "./chunk-7S2ELKNU.js";
4
- import "./chunk-6FGTNOCP.js";
5
- import "./chunk-TYDMSHV7.js";
6
- export {
7
- VectorStore
8
- };
9
- //# sourceMappingURL=VectorStore-WDL3H7QT.js.map