grepmax 0.16.1 → 0.16.2

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.
@@ -44,13 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.context = void 0;
46
46
  const fs = __importStar(require("node:fs"));
47
- const path = __importStar(require("node:path"));
48
47
  const commander_1 = require("commander");
49
48
  const searcher_1 = require("../lib/search/searcher");
50
49
  const skeleton_1 = require("../lib/skeleton");
51
50
  const vector_db_1 = require("../lib/store/vector-db");
52
51
  const filter_builder_1 = require("../lib/utils/filter-builder");
53
52
  const exit_1 = require("../lib/utils/exit");
53
+ const project_registry_1 = require("../lib/utils/project-registry");
54
54
  const project_root_1 = require("../lib/utils/project-root");
55
55
  const arrow_1 = require("../lib/utils/arrow");
56
56
  function estimateTokens(text) {
@@ -69,7 +69,9 @@ exports.context = new commander_1.Command("context")
69
69
  const maxResults = Number.parseInt(opts.maxResults || "10", 10) || 10;
70
70
  let vectorDb = null;
71
71
  try {
72
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
72
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
73
+ if (root === null)
74
+ return;
73
75
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
74
76
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
75
77
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -43,13 +10,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
43
10
  };
44
11
  Object.defineProperty(exports, "__esModule", { value: true });
45
12
  exports.diff = void 0;
46
- const path = __importStar(require("node:path"));
47
13
  const commander_1 = require("commander");
48
14
  const searcher_1 = require("../lib/search/searcher");
49
15
  const vector_db_1 = require("../lib/store/vector-db");
50
16
  const filter_builder_1 = require("../lib/utils/filter-builder");
51
17
  const exit_1 = require("../lib/utils/exit");
52
18
  const git_1 = require("../lib/utils/git");
19
+ const project_registry_1 = require("../lib/utils/project-registry");
53
20
  const project_root_1 = require("../lib/utils/project-root");
54
21
  const arrow_1 = require("../lib/utils/arrow");
55
22
  exports.diff = new commander_1.Command("diff")
@@ -65,7 +32,9 @@ exports.diff = new commander_1.Command("diff")
65
32
  const limit = Math.min(Math.max(Number.parseInt(opts.maxCount || "10", 10), 1), 50);
66
33
  let vectorDb = null;
67
34
  try {
68
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
35
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
36
+ if (root === null)
37
+ return;
69
38
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
70
39
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
71
40
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
@@ -44,13 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.extract = void 0;
46
46
  const fs = __importStar(require("node:fs"));
47
- const path = __importStar(require("node:path"));
48
47
  const commander_1 = require("commander");
49
48
  const vector_db_1 = require("../lib/store/vector-db");
50
49
  const exit_1 = require("../lib/utils/exit");
51
50
  const filter_builder_1 = require("../lib/utils/filter-builder");
52
51
  const import_extractor_1 = require("../lib/utils/import-extractor");
53
52
  const language_1 = require("../lib/utils/language");
53
+ const project_registry_1 = require("../lib/utils/project-registry");
54
54
  const project_root_1 = require("../lib/utils/project-root");
55
55
  const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
56
56
  const style = {
@@ -64,10 +64,9 @@ const ROLE_PRIORITY = {
64
64
  DEFINITION: 2,
65
65
  IMPLEMENTATION: 1,
66
66
  };
67
- function findSymbolChunks(symbol, db, projectRoot) {
67
+ function findSymbolChunks(db, whereClause) {
68
68
  return __awaiter(this, void 0, void 0, function* () {
69
69
  const table = yield db.ensureTable();
70
- const prefix = projectRoot.endsWith("/") ? projectRoot : `${projectRoot}/`;
71
70
  const rows = yield table
72
71
  .query()
73
72
  .select([
@@ -78,7 +77,7 @@ function findSymbolChunks(symbol, db, projectRoot) {
78
77
  "is_exported",
79
78
  "defined_symbols",
80
79
  ])
81
- .where(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}') AND path LIKE '${(0, filter_builder_1.escapeSqlString)(prefix)}%'`)
80
+ .where(whereClause)
82
81
  .limit(10)
83
82
  .toArray();
84
83
  return rows.map((row) => ({
@@ -107,17 +106,28 @@ exports.extract = new commander_1.Command("extract")
107
106
  .description("Extract full function/class body by symbol name")
108
107
  .argument("<symbol>", "The symbol to extract")
109
108
  .option("--root <dir>", "Project root directory")
109
+ .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
110
+ .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
110
111
  .option("--agent", "Compact output for AI agents", false)
111
112
  .option("--imports", "Prepend file imports", false)
112
113
  .action((symbol, opts) => __awaiter(void 0, void 0, void 0, function* () {
113
114
  var _a;
114
115
  let vectorDb = null;
115
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
116
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
117
+ if (root === null)
118
+ return;
116
119
  try {
117
120
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
118
121
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
119
122
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
120
- const chunks = yield findSymbolChunks(symbol, vectorDb, projectRoot);
123
+ const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
124
+ const scope = resolveScope({
125
+ projectRoot,
126
+ in: opts.in,
127
+ exclude: opts.exclude,
128
+ });
129
+ const where = buildScopeWhere(scope, `array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`);
130
+ const chunks = yield findSymbolChunks(vectorDb, where);
121
131
  if (chunks.length === 0) {
122
132
  const lines = [
123
133
  `Symbol not found: ${opts.agent ? symbol : style.bold(symbol)}`,
@@ -48,19 +48,24 @@ const commander_1 = require("commander");
48
48
  const impact_1 = require("../lib/graph/impact");
49
49
  const vector_db_1 = require("../lib/store/vector-db");
50
50
  const exit_1 = require("../lib/utils/exit");
51
+ const project_registry_1 = require("../lib/utils/project-registry");
51
52
  const project_root_1 = require("../lib/utils/project-root");
52
53
  exports.impact = new commander_1.Command("impact")
53
54
  .description("Analyze change impact: dependents and affected tests")
54
55
  .argument("<target>", "Symbol name or file path")
55
56
  .option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
56
57
  .option("--root <dir>", "Project root directory")
58
+ .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
59
+ .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
57
60
  .option("--agent", "Compact output for AI agents", false)
58
61
  .action((target, opts) => __awaiter(void 0, void 0, void 0, function* () {
59
62
  var _a;
60
63
  const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
61
64
  let vectorDb = null;
62
65
  try {
63
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
66
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
67
+ if (root === null)
68
+ return;
64
69
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
65
70
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
66
71
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
@@ -77,10 +82,23 @@ exports.impact = new commander_1.Command("impact")
77
82
  ? (target.startsWith("/") ? target : path.resolve(projectRoot, target))
78
83
  : undefined;
79
84
  const excludePaths = targetPath ? new Set([targetPath]) : undefined;
85
+ const { resolveScope } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
86
+ const scope = resolveScope({
87
+ projectRoot,
88
+ in: opts.in,
89
+ exclude: opts.exclude,
90
+ });
91
+ // Treat --in as an exclude-everything-else when set: any prefix that
92
+ // isn't the --in scope becomes effectively excluded. Today findDependents
93
+ // always queries within projectRoot; passing scope.pathPrefix when --in
94
+ // is set narrows it. Reuse the existing projectRoot semantic when no --in.
95
+ const queryRoot = opts.in && opts.in.length > 0
96
+ ? scope.pathPrefix.replace(/\/$/, "")
97
+ : projectRoot;
80
98
  // Run dependents and tests in parallel
81
99
  const [dependents, tests] = yield Promise.all([
82
- (0, impact_1.findDependents)(symbols, vectorDb, projectRoot, excludePaths),
83
- (0, impact_1.findTests)(symbols, vectorDb, projectRoot, depth),
100
+ (0, impact_1.findDependents)(symbols, vectorDb, queryRoot, excludePaths, undefined, scope.excludePrefixes),
101
+ (0, impact_1.findTests)(symbols, vectorDb, queryRoot, depth, scope.excludePrefixes),
84
102
  ]);
85
103
  // Separate test files from non-test dependents
86
104
  const nonTestDeps = dependents.filter((d) => !(0, impact_1.isTestPath)(d.file));
@@ -43,9 +43,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
43
43
  };
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.investigateCmd = void 0;
46
- const path = __importStar(require("node:path"));
47
46
  const commander_1 = require("commander");
48
47
  const exit_1 = require("../lib/utils/exit");
48
+ const project_registry_1 = require("../lib/utils/project-registry");
49
49
  const project_root_1 = require("../lib/utils/project-root");
50
50
  exports.investigateCmd = new commander_1.Command("investigate")
51
51
  .description("Ask a question about the codebase using local LLM + gmax tools")
@@ -62,7 +62,9 @@ Examples:
62
62
  .action((question, opts) => __awaiter(void 0, void 0, void 0, function* () {
63
63
  var _a;
64
64
  try {
65
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
65
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
66
+ if (root === null)
67
+ return;
66
68
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
67
69
  const maxRounds = Math.min(Math.max(Number.parseInt(opts.rounds || "10", 10), 1), 20);
68
70
  // Ensure LLM server is running
@@ -44,13 +44,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.peek = void 0;
46
46
  const fs = __importStar(require("node:fs"));
47
- const path = __importStar(require("node:path"));
48
47
  const commander_1 = require("commander");
49
48
  const graph_builder_1 = require("../lib/graph/graph-builder");
50
49
  const vector_db_1 = require("../lib/store/vector-db");
51
50
  const exit_1 = require("../lib/utils/exit");
52
51
  const filter_builder_1 = require("../lib/utils/filter-builder");
53
52
  const language_1 = require("../lib/utils/language");
53
+ const project_registry_1 = require("../lib/utils/project-registry");
54
54
  const project_root_1 = require("../lib/utils/project-root");
55
55
  const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
56
56
  const style = {
@@ -95,29 +95,37 @@ exports.peek = new commander_1.Command("peek")
95
95
  .argument("<symbol>", "The symbol to peek at")
96
96
  .option("-d, --depth <n>", "Caller traversal depth (default 1, max 3)", "1")
97
97
  .option("--root <dir>", "Project root directory")
98
+ .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
99
+ .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
98
100
  .option("--agent", "Compact output for AI agents", false)
99
101
  .action((symbol, opts) => __awaiter(void 0, void 0, void 0, function* () {
100
102
  var _a;
101
103
  let vectorDb = null;
102
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
104
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
105
+ if (root === null)
106
+ return;
103
107
  const depth = Math.min(Math.max(Number.parseInt(opts.depth || "1", 10), 1), 3);
104
108
  try {
105
109
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
106
110
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
107
111
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
112
+ const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
113
+ const scope = resolveScope({
114
+ projectRoot,
115
+ in: opts.in,
116
+ exclude: opts.exclude,
117
+ });
118
+ const scopeWhere = (cond) => buildScopeWhere(scope, cond);
108
119
  // Cross-language disambiguation: when the symbol is defined in 2+
109
120
  // languages, refuse to silently pick one. The graph builder otherwise
110
121
  // picks one chunk arbitrarily and lists callers from a different
111
122
  // language — verified failure mode.
112
123
  {
113
124
  const tableForCheck = yield vectorDb.ensureTable();
114
- const prefixForCheck = projectRoot.endsWith("/")
115
- ? projectRoot
116
- : `${projectRoot}/`;
117
125
  const allDefs = yield tableForCheck
118
126
  .query()
119
127
  .select(["path", "start_line"])
120
- .where(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}') AND path LIKE '${(0, filter_builder_1.escapeSqlString)(prefixForCheck)}%'`)
128
+ .where(scopeWhere(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`))
121
129
  .limit(20)
122
130
  .toArray();
123
131
  const chunks = allDefs.map((row) => ({
@@ -140,7 +148,7 @@ exports.peek = new commander_1.Command("peek")
140
148
  return;
141
149
  }
142
150
  }
143
- const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, projectRoot);
151
+ const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, scope.pathPrefix, scope.excludePrefixes);
144
152
  const graph = yield graphBuilder.buildGraph(symbol);
145
153
  if (!graph.center) {
146
154
  const lines = [
@@ -159,13 +167,10 @@ exports.peek = new commander_1.Command("peek")
159
167
  : p;
160
168
  // Get chunk metadata for is_exported and end_line
161
169
  const table = yield vectorDb.ensureTable();
162
- const prefix = projectRoot.endsWith("/")
163
- ? projectRoot
164
- : `${projectRoot}/`;
165
170
  const metaRows = yield table
166
171
  .query()
167
172
  .select(["is_exported", "start_line", "end_line"])
168
- .where(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}') AND path LIKE '${(0, filter_builder_1.escapeSqlString)(prefix)}%'`)
173
+ .where(scopeWhere(`array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`))
169
174
  .limit(1)
170
175
  .toArray();
171
176
  const exported = metaRows.length > 0 && Boolean(metaRows[0].is_exported);
@@ -56,12 +56,13 @@ exports.project = new commander_1.Command("project")
56
56
  .option("--root <dir>", "Project root (defaults to current directory)")
57
57
  .option("--agent", "Compact output for AI agents", false)
58
58
  .action((opts) => __awaiter(void 0, void 0, void 0, function* () {
59
- var _a, _b, _c, _d;
59
+ var _a, _b, _c;
60
60
  let vectorDb = null;
61
61
  try {
62
- const root = opts.root
63
- ? (_a = (0, project_root_1.findProjectRoot)(path.resolve(opts.root))) !== null && _a !== void 0 ? _a : path.resolve(opts.root)
64
- : (_b = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _b !== void 0 ? _b : process.cwd();
62
+ const resolvedRoot = (0, project_registry_1.resolveRootOrExit)(opts.root);
63
+ if (resolvedRoot === null)
64
+ return;
65
+ const root = (_a = (0, project_root_1.findProjectRoot)(resolvedRoot)) !== null && _a !== void 0 ? _a : resolvedRoot;
65
66
  const prefix = root.endsWith("/") ? root : `${root}/`;
66
67
  const projectName = path.basename(root);
67
68
  const paths = (0, project_root_1.ensureProjectPaths)(root);
@@ -136,7 +137,7 @@ exports.project = new commander_1.Command("project")
136
137
  console.log(`root\t${root}`);
137
138
  console.log(`chunks\t${rows.length}`);
138
139
  console.log(`files\t${files.size}`);
139
- console.log(`last_indexed\t${(_c = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _c !== void 0 ? _c : "unknown"}`);
140
+ console.log(`last_indexed\t${(_b = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _b !== void 0 ? _b : "unknown"}`);
140
141
  console.log(`languages\t${extEntries.map(([ext]) => ext).join(",")}`);
141
142
  console.log(`top_dirs\t${Array.from(dirCounts.entries()).sort((a, b) => b[1].chunks - a[1].chunks).slice(0, 8).map(([d]) => d).join(",")}`);
142
143
  if (topSymbols.length > 0) {
@@ -148,7 +149,7 @@ exports.project = new commander_1.Command("project")
148
149
  }
149
150
  else {
150
151
  console.log(`Project: ${projectName} (${root})`);
151
- console.log(`Last indexed: ${(_d = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _d !== void 0 ? _d : "unknown"} • ${rows.length} chunks • ${files.size} files\n`);
152
+ console.log(`Last indexed: ${(_c = proj === null || proj === void 0 ? void 0 : proj.lastIndexed) !== null && _c !== void 0 ? _c : "unknown"} • ${rows.length} chunks • ${files.size} files\n`);
152
153
  console.log(`Languages: ${extEntries.map(([ext, count]) => `${ext} (${Math.round((count / rows.length) * 100)}%)`).join(", ")}\n`);
153
154
  console.log("Directory structure:");
154
155
  for (const [dir, data] of Array.from(dirCounts.entries())
@@ -182,7 +183,7 @@ exports.project = new commander_1.Command("project")
182
183
  try {
183
184
  yield vectorDb.close();
184
185
  }
185
- catch (_e) { }
186
+ catch (_d) { }
186
187
  }
187
188
  yield (0, exit_1.gracefulExit)();
188
189
  }
@@ -56,6 +56,7 @@ const config_1 = require("../config");
56
56
  const meta_cache_1 = require("../lib/store/meta-cache");
57
57
  const exit_1 = require("../lib/utils/exit");
58
58
  const format_helpers_1 = require("../lib/utils/format-helpers");
59
+ const project_registry_1 = require("../lib/utils/project-registry");
59
60
  const project_root_1 = require("../lib/utils/project-root");
60
61
  exports.recent = new commander_1.Command("recent")
61
62
  .description("Show recently modified indexed files")
@@ -64,20 +65,21 @@ exports.recent = new commander_1.Command("recent")
64
65
  .option("--agent", "Compact output for AI agents", false)
65
66
  .action((opts) => __awaiter(void 0, void 0, void 0, function* () {
66
67
  var _a, e_1, _b, _c;
67
- var _d, _e;
68
+ var _d;
68
69
  const limit = Math.min(Math.max(Number.parseInt(opts.limit || "20", 10), 1), 50);
69
70
  try {
70
- const root = opts.root
71
- ? (_d = (0, project_root_1.findProjectRoot)(path.resolve(opts.root))) !== null && _d !== void 0 ? _d : path.resolve(opts.root)
72
- : (_e = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _e !== void 0 ? _e : process.cwd();
71
+ const resolvedRoot = (0, project_registry_1.resolveRootOrExit)(opts.root);
72
+ if (resolvedRoot === null)
73
+ return;
74
+ const root = (_d = (0, project_root_1.findProjectRoot)(resolvedRoot)) !== null && _d !== void 0 ? _d : resolvedRoot;
73
75
  const prefix = root.endsWith("/") ? root : `${root}/`;
74
76
  const metaCache = new meta_cache_1.MetaCache(config_1.PATHS.lmdbPath);
75
77
  try {
76
78
  const files = [];
77
79
  try {
78
- for (var _f = true, _g = __asyncValues(metaCache.entries()), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
79
- _c = _h.value;
80
- _f = false;
80
+ for (var _e = true, _f = __asyncValues(metaCache.entries()), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
81
+ _c = _g.value;
82
+ _e = false;
81
83
  const { path: p, entry } = _c;
82
84
  if (p.startsWith(prefix)) {
83
85
  files.push({ path: p, mtimeMs: entry.mtimeMs });
@@ -87,7 +89,7 @@ exports.recent = new commander_1.Command("recent")
87
89
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
88
90
  finally {
89
91
  try {
90
- if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
92
+ if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
91
93
  }
92
94
  finally { if (e_1) throw e_1.error; }
93
95
  }
@@ -48,6 +48,7 @@ const commander_1 = require("commander");
48
48
  const vector_db_1 = require("../lib/store/vector-db");
49
49
  const filter_builder_1 = require("../lib/utils/filter-builder");
50
50
  const exit_1 = require("../lib/utils/exit");
51
+ const project_registry_1 = require("../lib/utils/project-registry");
51
52
  const project_root_1 = require("../lib/utils/project-root");
52
53
  const arrow_1 = require("../lib/utils/arrow");
53
54
  exports.related = new commander_1.Command("related")
@@ -55,19 +56,29 @@ exports.related = new commander_1.Command("related")
55
56
  .argument("<file>", "File path relative to project root")
56
57
  .option("-l, --limit <n>", "Max results per direction (default 10)", "10")
57
58
  .option("--root <dir>", "Project root directory")
59
+ .option("--in <subpath>", "Restrict to a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
60
+ .option("--exclude <subpath>", "Exclude a sub-path of the project (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
58
61
  .option("--agent", "Compact output for AI agents", false)
59
62
  .action((file, opts) => __awaiter(void 0, void 0, void 0, function* () {
60
63
  var _a;
61
64
  const limit = Math.min(Math.max(Number.parseInt(opts.limit || "10", 10), 1), 25);
62
65
  let vectorDb = null;
63
66
  try {
64
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
67
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
68
+ if (root === null)
69
+ return;
65
70
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
66
71
  const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
67
72
  vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
68
73
  const absPath = path.resolve(projectRoot, file);
69
74
  const table = yield vectorDb.ensureTable();
70
- const pathScope = `path LIKE '${(0, filter_builder_1.escapeSqlString)(projectRoot)}/%'`;
75
+ const { resolveScope, buildScopeWhere } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/scope-filter")));
76
+ const scope = resolveScope({
77
+ projectRoot,
78
+ in: opts.in,
79
+ exclude: opts.exclude,
80
+ });
81
+ const pathScope = buildScopeWhere(scope);
71
82
  const fileChunks = yield table
72
83
  .query()
73
84
  .select(["defined_symbols", "referenced_symbols"])
@@ -43,7 +43,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
43
43
  };
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
45
  exports.remove = void 0;
46
- const fs = __importStar(require("node:fs"));
47
46
  const path = __importStar(require("node:path"));
48
47
  const readline = __importStar(require("node:readline"));
49
48
  const commander_1 = require("commander");
@@ -83,41 +82,23 @@ Examples:
83
82
  let vectorDb = null;
84
83
  let metaCache = null;
85
84
  try {
86
- // Resolve name → registered root when arg has no path separator and isn't a dir.
87
- // Avoids the footgun where a typo'd name silently removed the cwd project.
88
- let resolvedDir = dir;
89
- if (dir &&
90
- !dir.includes("/") &&
91
- !dir.includes("\\") &&
92
- !fs.existsSync(path.resolve(dir))) {
93
- const matches = (0, project_registry_1.listProjects)().filter((p) => p.name === dir);
94
- if (matches.length === 0) {
95
- console.error(`No registered project named "${dir}".`);
96
- const all = (0, project_registry_1.listProjects)();
97
- if (all.length > 0) {
98
- console.error("Available projects:");
99
- for (const p of all) {
100
- console.error(` ${p.name.padEnd(24)} ${p.root}`);
101
- }
102
- }
103
- else {
104
- console.error("No projects are currently registered.");
105
- }
106
- process.exitCode = 1;
107
- return;
85
+ // Resolve name → registered root when arg has no path separator and
86
+ // isn't a dir. Avoids the footgun where a typo'd name silently removed
87
+ // the cwd project.
88
+ let targetDir;
89
+ if (dir) {
90
+ try {
91
+ targetDir = (0, project_registry_1.resolveProjectRoot)(dir);
108
92
  }
109
- if (matches.length > 1) {
110
- console.error(`Multiple registered projects named "${dir}":`);
111
- for (const p of matches) {
112
- console.error(` ${p.root}`);
113
- }
114
- console.error("Pass an absolute path to disambiguate.");
93
+ catch (err) {
94
+ console.error(err instanceof Error ? err.message : String(err));
115
95
  process.exitCode = 1;
116
96
  return;
117
97
  }
118
- resolvedDir = matches[0].root;
119
98
  }
120
- const targetDir = resolvedDir ? path.resolve(resolvedDir) : process.cwd();
99
+ else {
100
+ targetDir = process.cwd();
101
+ }
121
102
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(targetDir)) !== null && _a !== void 0 ? _a : targetDir;
122
103
  const projectName = path.basename(projectRoot);
123
104
  const project = (0, project_registry_1.getProject)(projectRoot);
@@ -48,6 +48,7 @@ const fs = __importStar(require("node:fs"));
48
48
  const path = __importStar(require("node:path"));
49
49
  const commander_1 = require("commander");
50
50
  const exit_1 = require("../lib/utils/exit");
51
+ const project_registry_1 = require("../lib/utils/project-registry");
51
52
  const project_root_1 = require("../lib/utils/project-root");
52
53
  exports.review = new commander_1.Command("review")
53
54
  .description("Review code changes using local LLM + codebase context")
@@ -69,7 +70,9 @@ Subcommands:
69
70
  .action((opts) => __awaiter(void 0, void 0, void 0, function* () {
70
71
  var _a;
71
72
  try {
72
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
73
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
74
+ if (root === null)
75
+ return;
73
76
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
74
77
  const commitRef = opts.commit;
75
78
  if (opts.background) {
@@ -135,7 +138,9 @@ exports.review
135
138
  .action((opts) => __awaiter(void 0, void 0, void 0, function* () {
136
139
  var _a;
137
140
  try {
138
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
141
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
142
+ if (root === null)
143
+ return;
139
144
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
140
145
  const { readReport, formatReportText } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
141
146
  const report = readReport(projectRoot);
@@ -166,7 +171,9 @@ exports.review
166
171
  .action((opts) => __awaiter(void 0, void 0, void 0, function* () {
167
172
  var _a;
168
173
  try {
169
- const root = opts.root ? path.resolve(opts.root) : process.cwd();
174
+ const root = (0, project_registry_1.resolveRootOrExit)(opts.root);
175
+ if (root === null)
176
+ return;
170
177
  const projectRoot = (_a = (0, project_root_1.findProjectRoot)(root)) !== null && _a !== void 0 ? _a : root;
171
178
  const { clearReport } = yield Promise.resolve().then(() => __importStar(require("../lib/llm/report")));
172
179
  clearReport(projectRoot);