grepmax 0.7.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.
Potentially problematic release.
This version of grepmax might be problematic. Click here for more details.
- package/LICENSE +202 -0
- package/NOTICE +33 -0
- package/README.md +375 -0
- package/dist/commands/claude-code.js +60 -0
- package/dist/commands/codex.js +98 -0
- package/dist/commands/doctor.js +92 -0
- package/dist/commands/droid.js +189 -0
- package/dist/commands/index.js +125 -0
- package/dist/commands/list.js +120 -0
- package/dist/commands/mcp.js +572 -0
- package/dist/commands/opencode.js +199 -0
- package/dist/commands/search.js +539 -0
- package/dist/commands/serve.js +512 -0
- package/dist/commands/setup.js +162 -0
- package/dist/commands/skeleton.js +288 -0
- package/dist/commands/symbols.js +129 -0
- package/dist/commands/trace.js +50 -0
- package/dist/commands/verify.js +174 -0
- package/dist/config.js +120 -0
- package/dist/eval.js +618 -0
- package/dist/index.js +82 -0
- package/dist/lib/core/languages.js +237 -0
- package/dist/lib/graph/graph-builder.js +105 -0
- package/dist/lib/index/chunker.js +663 -0
- package/dist/lib/index/grammar-loader.js +110 -0
- package/dist/lib/index/ignore-patterns.js +63 -0
- package/dist/lib/index/index-config.js +86 -0
- package/dist/lib/index/sync-helpers.js +97 -0
- package/dist/lib/index/syncer.js +396 -0
- package/dist/lib/index/walker.js +164 -0
- package/dist/lib/index/watcher.js +245 -0
- package/dist/lib/output/formatter.js +161 -0
- package/dist/lib/output/json-formatter.js +6 -0
- package/dist/lib/search/intent.js +23 -0
- package/dist/lib/search/searcher.js +475 -0
- package/dist/lib/setup/model-loader.js +107 -0
- package/dist/lib/setup/setup-helpers.js +106 -0
- package/dist/lib/skeleton/body-fields.js +175 -0
- package/dist/lib/skeleton/index.js +24 -0
- package/dist/lib/skeleton/retriever.js +36 -0
- package/dist/lib/skeleton/skeletonizer.js +483 -0
- package/dist/lib/skeleton/summary-formatter.js +90 -0
- package/dist/lib/store/meta-cache.js +143 -0
- package/dist/lib/store/types.js +2 -0
- package/dist/lib/store/vector-db.js +340 -0
- package/dist/lib/utils/cleanup.js +33 -0
- package/dist/lib/utils/exit.js +38 -0
- package/dist/lib/utils/file-utils.js +131 -0
- package/dist/lib/utils/filter-builder.js +17 -0
- package/dist/lib/utils/formatter.js +230 -0
- package/dist/lib/utils/git.js +83 -0
- package/dist/lib/utils/lock.js +157 -0
- package/dist/lib/utils/project-root.js +107 -0
- package/dist/lib/utils/server-registry.js +97 -0
- package/dist/lib/workers/colbert-math.js +107 -0
- package/dist/lib/workers/colbert-tokenizer.js +113 -0
- package/dist/lib/workers/download-worker.js +169 -0
- package/dist/lib/workers/embeddings/colbert.js +213 -0
- package/dist/lib/workers/embeddings/granite.js +180 -0
- package/dist/lib/workers/embeddings/mlx-client.js +144 -0
- package/dist/lib/workers/orchestrator.js +350 -0
- package/dist/lib/workers/pool.js +373 -0
- package/dist/lib/workers/process-child.js +92 -0
- package/dist/lib/workers/worker.js +31 -0
- package/package.json +80 -0
- package/plugins/osgrep/.claude-plugin/plugin.json +20 -0
- package/plugins/osgrep/hooks/start.js +92 -0
- package/plugins/osgrep/hooks/stop.js +3 -0
- package/plugins/osgrep/hooks.json +26 -0
- package/plugins/osgrep/skills/osgrep/SKILL.md +82 -0
|
@@ -0,0 +1,245 @@
|
|
|
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
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.WATCHER_IGNORE_PATTERNS = void 0;
|
|
46
|
+
exports.startWatcher = startWatcher;
|
|
47
|
+
const fs = __importStar(require("node:fs"));
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const chokidar_1 = require("chokidar");
|
|
50
|
+
const file_utils_1 = require("../utils/file-utils");
|
|
51
|
+
const lock_1 = require("../utils/lock");
|
|
52
|
+
const pool_1 = require("../workers/pool");
|
|
53
|
+
// Chokidar ignored — must exclude heavy directories to keep FD count low.
|
|
54
|
+
// On macOS, chokidar uses FSEvents (single FD) but falls back to fs.watch()
|
|
55
|
+
// (one FD per directory) if FSEvents isn't available or for some subdirs.
|
|
56
|
+
exports.WATCHER_IGNORE_PATTERNS = [
|
|
57
|
+
"**/node_modules/**",
|
|
58
|
+
"**/.git/**",
|
|
59
|
+
"**/.osgrep/**",
|
|
60
|
+
"**/dist/**",
|
|
61
|
+
"**/build/**",
|
|
62
|
+
"**/out/**",
|
|
63
|
+
"**/target/**",
|
|
64
|
+
"**/__pycache__/**",
|
|
65
|
+
"**/coverage/**",
|
|
66
|
+
"**/venv/**",
|
|
67
|
+
"**/.next/**",
|
|
68
|
+
"**/lancedb/**",
|
|
69
|
+
/(^|[/\\])\../, // dotfiles
|
|
70
|
+
];
|
|
71
|
+
const DEBOUNCE_MS = 2000;
|
|
72
|
+
const FTS_REBUILD_INTERVAL_MS = 5 * 60 * 1000;
|
|
73
|
+
function startWatcher(opts) {
|
|
74
|
+
const { projectRoot, vectorDb, metaCache, osgrepDir, onReindex } = opts;
|
|
75
|
+
const pending = new Map();
|
|
76
|
+
let debounceTimer = null;
|
|
77
|
+
let processing = false;
|
|
78
|
+
let closed = false;
|
|
79
|
+
const watcher = (0, chokidar_1.watch)(projectRoot, {
|
|
80
|
+
ignored: exports.WATCHER_IGNORE_PATTERNS,
|
|
81
|
+
ignoreInitial: true,
|
|
82
|
+
persistent: true,
|
|
83
|
+
// Use polling to avoid EMFILE in large monorepos.
|
|
84
|
+
// fs.watch() uses one FD per directory (kqueue on macOS) and hits ulimit.
|
|
85
|
+
// Polling 2-3k source files every 5s is negligible CPU.
|
|
86
|
+
usePolling: true,
|
|
87
|
+
interval: 5000,
|
|
88
|
+
binaryInterval: 10000,
|
|
89
|
+
});
|
|
90
|
+
watcher.on("error", (err) => {
|
|
91
|
+
console.error("[watch] Watcher error:", err);
|
|
92
|
+
});
|
|
93
|
+
const scheduleBatch = () => {
|
|
94
|
+
if (debounceTimer)
|
|
95
|
+
clearTimeout(debounceTimer);
|
|
96
|
+
debounceTimer = setTimeout(() => processBatch(), DEBOUNCE_MS);
|
|
97
|
+
};
|
|
98
|
+
const processBatch = () => __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
if (closed || processing || pending.size === 0)
|
|
100
|
+
return;
|
|
101
|
+
processing = true;
|
|
102
|
+
const batch = new Map(pending);
|
|
103
|
+
pending.clear();
|
|
104
|
+
const start = Date.now();
|
|
105
|
+
let reindexed = 0;
|
|
106
|
+
try {
|
|
107
|
+
const lock = yield (0, lock_1.acquireWriterLockWithRetry)(osgrepDir, {
|
|
108
|
+
maxRetries: 3,
|
|
109
|
+
retryDelayMs: 500,
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
const pool = (0, pool_1.getWorkerPool)();
|
|
113
|
+
const deletes = [];
|
|
114
|
+
const vectors = [];
|
|
115
|
+
const metaUpdates = new Map();
|
|
116
|
+
const metaDeletes = [];
|
|
117
|
+
for (const [absPath, event] of batch) {
|
|
118
|
+
const relPath = path.relative(projectRoot, absPath);
|
|
119
|
+
if (event === "unlink") {
|
|
120
|
+
deletes.push(relPath);
|
|
121
|
+
metaDeletes.push(relPath);
|
|
122
|
+
reindexed++;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
// change or add
|
|
126
|
+
try {
|
|
127
|
+
const stats = yield fs.promises.stat(absPath);
|
|
128
|
+
if (!(0, file_utils_1.isIndexableFile)(absPath, stats.size))
|
|
129
|
+
continue;
|
|
130
|
+
// Check if content actually changed via hash
|
|
131
|
+
const cached = metaCache.get(relPath);
|
|
132
|
+
const result = yield pool.processFile({
|
|
133
|
+
path: relPath,
|
|
134
|
+
absolutePath: absPath,
|
|
135
|
+
});
|
|
136
|
+
const metaEntry = {
|
|
137
|
+
hash: result.hash,
|
|
138
|
+
mtimeMs: result.mtimeMs,
|
|
139
|
+
size: result.size,
|
|
140
|
+
};
|
|
141
|
+
if (cached && cached.hash === result.hash) {
|
|
142
|
+
// Content unchanged (mtime changed but hash same) — just update meta
|
|
143
|
+
metaUpdates.set(relPath, metaEntry);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (result.shouldDelete) {
|
|
147
|
+
deletes.push(relPath);
|
|
148
|
+
metaUpdates.set(relPath, metaEntry);
|
|
149
|
+
reindexed++;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
// Delete old vectors, insert new
|
|
153
|
+
deletes.push(relPath);
|
|
154
|
+
if (result.vectors.length > 0) {
|
|
155
|
+
vectors.push(...result.vectors);
|
|
156
|
+
}
|
|
157
|
+
metaUpdates.set(relPath, metaEntry);
|
|
158
|
+
reindexed++;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
const code = err === null || err === void 0 ? void 0 : err.code;
|
|
162
|
+
if (code === "ENOENT") {
|
|
163
|
+
deletes.push(relPath);
|
|
164
|
+
metaDeletes.push(relPath);
|
|
165
|
+
reindexed++;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
console.error(`[watch] Failed to process ${relPath}:`, err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Flush to VectorDB
|
|
173
|
+
if (deletes.length > 0) {
|
|
174
|
+
yield vectorDb.deletePaths(deletes);
|
|
175
|
+
}
|
|
176
|
+
if (vectors.length > 0) {
|
|
177
|
+
yield vectorDb.insertBatch(vectors);
|
|
178
|
+
}
|
|
179
|
+
// Update MetaCache
|
|
180
|
+
for (const [p, entry] of metaUpdates) {
|
|
181
|
+
metaCache.put(p, entry);
|
|
182
|
+
}
|
|
183
|
+
for (const p of metaDeletes) {
|
|
184
|
+
metaCache.delete(p);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
yield lock.release();
|
|
189
|
+
}
|
|
190
|
+
if (reindexed > 0) {
|
|
191
|
+
const duration = Date.now() - start;
|
|
192
|
+
onReindex === null || onReindex === void 0 ? void 0 : onReindex(reindexed, duration);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
console.error("[watch] Batch processing failed:", err);
|
|
197
|
+
// Re-queue failed items for retry
|
|
198
|
+
for (const [absPath, event] of batch) {
|
|
199
|
+
if (!pending.has(absPath)) {
|
|
200
|
+
pending.set(absPath, event);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
scheduleBatch();
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
processing = false;
|
|
207
|
+
// Process any events that came in while we were processing
|
|
208
|
+
if (pending.size > 0) {
|
|
209
|
+
scheduleBatch();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
const onFileEvent = (event, absPath) => {
|
|
214
|
+
if (closed)
|
|
215
|
+
return;
|
|
216
|
+
if (event !== "unlink" && !(0, file_utils_1.isIndexableFile)(absPath))
|
|
217
|
+
return;
|
|
218
|
+
pending.set(absPath, event);
|
|
219
|
+
scheduleBatch();
|
|
220
|
+
};
|
|
221
|
+
watcher.on("add", (p) => onFileEvent("change", p));
|
|
222
|
+
watcher.on("change", (p) => onFileEvent("change", p));
|
|
223
|
+
watcher.on("unlink", (p) => onFileEvent("unlink", p));
|
|
224
|
+
// Periodic FTS rebuild
|
|
225
|
+
const ftsInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
226
|
+
if (closed)
|
|
227
|
+
return;
|
|
228
|
+
try {
|
|
229
|
+
yield vectorDb.createFTSIndex();
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
console.error("[watch] FTS rebuild failed:", err);
|
|
233
|
+
}
|
|
234
|
+
}), FTS_REBUILD_INTERVAL_MS);
|
|
235
|
+
ftsInterval.unref();
|
|
236
|
+
return {
|
|
237
|
+
close: () => __awaiter(this, void 0, void 0, function* () {
|
|
238
|
+
closed = true;
|
|
239
|
+
if (debounceTimer)
|
|
240
|
+
clearTimeout(debounceTimer);
|
|
241
|
+
clearInterval(ftsInterval);
|
|
242
|
+
yield watcher.close();
|
|
243
|
+
}),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.formatResult = formatResult;
|
|
37
|
+
exports.formatResults = formatResults;
|
|
38
|
+
exports.formatTrace = formatTrace;
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const cli_highlight_1 = require("cli-highlight");
|
|
41
|
+
const languages_1 = require("../core/languages");
|
|
42
|
+
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
43
|
+
const style = {
|
|
44
|
+
bold: (s) => (useColors ? `\x1b[1m${s}\x1b[22m` : s),
|
|
45
|
+
dim: (s) => (useColors ? `\x1b[2m${s}\x1b[22m` : s),
|
|
46
|
+
green: (s) => (useColors ? `\x1b[32m${s}\x1b[39m` : s),
|
|
47
|
+
blue: (s) => (useColors ? `\x1b[34m${s}\x1b[39m` : s),
|
|
48
|
+
cyan: (s) => (useColors ? `\x1b[36m${s}\x1b[39m` : s),
|
|
49
|
+
gray: (s) => (useColors ? `\x1b[90m${s}\x1b[39m` : s),
|
|
50
|
+
};
|
|
51
|
+
function detectLanguage(filePath) {
|
|
52
|
+
const ext = path.extname(filePath);
|
|
53
|
+
const lang = (0, languages_1.getLanguageByExtension)(ext);
|
|
54
|
+
return (lang === null || lang === void 0 ? void 0 : lang.id) || "plaintext";
|
|
55
|
+
}
|
|
56
|
+
function formatScore(score) {
|
|
57
|
+
if (typeof score !== "number")
|
|
58
|
+
return "";
|
|
59
|
+
const fixed = score.toFixed(3);
|
|
60
|
+
return fixed
|
|
61
|
+
.replace(/^0\./, ".")
|
|
62
|
+
.replace(/\.?0+$/, (m) => (m.startsWith(".") ? "" : m));
|
|
63
|
+
}
|
|
64
|
+
function formatResult(result, root, options = {}) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
const metadata = result.metadata;
|
|
67
|
+
const relPath = path.relative(root, metadata.path);
|
|
68
|
+
const line = ((_a = result.generated_metadata) === null || _a === void 0 ? void 0 : _a.start_line) || 0;
|
|
69
|
+
// Header: Role + File + Location
|
|
70
|
+
const role = result.role || "IMPLEMENTATION";
|
|
71
|
+
const roleColor = role === "DEFINITION"
|
|
72
|
+
? style.green
|
|
73
|
+
: role === "ORCHESTRATION"
|
|
74
|
+
? style.cyan
|
|
75
|
+
: style.blue;
|
|
76
|
+
const header = `${roleColor(role)} ${style.gray(relPath)}:${line}`;
|
|
77
|
+
// Breadcrumb
|
|
78
|
+
const breadcrumb = (_b = result.context) === null || _b === void 0 ? void 0 : _b.filter((c) => !c.startsWith("File:")).join(" > ");
|
|
79
|
+
const breadcrumbLine = breadcrumb ? `\n${style.dim(breadcrumb)}` : "";
|
|
80
|
+
// Context: What defines this, what it calls
|
|
81
|
+
const context = [];
|
|
82
|
+
if (Array.isArray(result.defined_symbols) &&
|
|
83
|
+
result.defined_symbols.length > 0) {
|
|
84
|
+
context.push(`Defines: ${result.defined_symbols.join(", ")}`);
|
|
85
|
+
}
|
|
86
|
+
if (Array.isArray(result.referenced_symbols) &&
|
|
87
|
+
result.referenced_symbols.length > 0) {
|
|
88
|
+
context.push(`Calls: ${result.referenced_symbols.slice(0, 3).join(", ")}${result.referenced_symbols.length > 3 ? "..." : ""}`);
|
|
89
|
+
}
|
|
90
|
+
// Add score if available
|
|
91
|
+
const scoreStr = formatScore(result.score);
|
|
92
|
+
if (scoreStr) {
|
|
93
|
+
context.push(`Score: ${scoreStr}`);
|
|
94
|
+
}
|
|
95
|
+
const contextLine = context.length > 0 ? `\n${style.gray(context.join(" | "))}` : "";
|
|
96
|
+
// Code snippet
|
|
97
|
+
let code = result.text || "";
|
|
98
|
+
// Clean up noise
|
|
99
|
+
code = code
|
|
100
|
+
.split("\n")
|
|
101
|
+
.filter((l) => !l.startsWith("// File:") && !l.startsWith("File:"))
|
|
102
|
+
.join("\n")
|
|
103
|
+
.trim();
|
|
104
|
+
if (!options.content && code.split("\n").length > 15) {
|
|
105
|
+
const lines = code.split("\n");
|
|
106
|
+
code = [...lines.slice(0, 15), style.dim(`...`)].join("\n");
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const lang = detectLanguage(metadata.path);
|
|
110
|
+
code = (0, cli_highlight_1.highlight)(code, { language: lang, ignoreIllegals: true });
|
|
111
|
+
}
|
|
112
|
+
catch (_c) {
|
|
113
|
+
// ignore
|
|
114
|
+
}
|
|
115
|
+
return `
|
|
116
|
+
${header}${breadcrumbLine}${contextLine}
|
|
117
|
+
|
|
118
|
+
${code}
|
|
119
|
+
|
|
120
|
+
${style.dim("─".repeat(80))}
|
|
121
|
+
`.trim();
|
|
122
|
+
}
|
|
123
|
+
function formatResults(results, root, options = {}) {
|
|
124
|
+
if (results.length === 0)
|
|
125
|
+
return "No results found.";
|
|
126
|
+
return results.map((r) => formatResult(r, root, options)).join("\n\n");
|
|
127
|
+
}
|
|
128
|
+
function formatTrace(graph) {
|
|
129
|
+
if (!graph.center) {
|
|
130
|
+
return style.dim("Symbol not found.");
|
|
131
|
+
}
|
|
132
|
+
const lines = [];
|
|
133
|
+
// 1. Callers (Upstream)
|
|
134
|
+
if (graph.callers.length > 0) {
|
|
135
|
+
lines.push(style.bold("Callers (Who calls this?):"));
|
|
136
|
+
graph.callers.forEach((caller) => {
|
|
137
|
+
lines.push(` ${style.blue("↑")} ${style.green(caller.symbol)} ${style.dim(`(${caller.file}:${caller.line})`)}`);
|
|
138
|
+
});
|
|
139
|
+
lines.push("");
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
lines.push(style.dim("No known callers."));
|
|
143
|
+
lines.push("");
|
|
144
|
+
}
|
|
145
|
+
// 2. Center (The Symbol)
|
|
146
|
+
lines.push(style.bold("▶ " + graph.center.symbol));
|
|
147
|
+
lines.push(` ${style.dim(`Defined in ${graph.center.file}:${graph.center.line}`)}`);
|
|
148
|
+
lines.push(` ${style.dim(`Role: ${graph.center.role}`)}`);
|
|
149
|
+
lines.push("");
|
|
150
|
+
// 3. Callees (Downstream)
|
|
151
|
+
if (graph.callees.length > 0) {
|
|
152
|
+
lines.push(style.bold("Callees (What does this call?):"));
|
|
153
|
+
graph.callees.forEach((callee) => {
|
|
154
|
+
lines.push(` ${style.cyan("↓")} ${callee}`);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
lines.push(style.dim("No known callees."));
|
|
159
|
+
}
|
|
160
|
+
return lines.join("\n");
|
|
161
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectIntent = detectIntent;
|
|
4
|
+
function detectIntent(query) {
|
|
5
|
+
const normalized = query.toLowerCase();
|
|
6
|
+
// Definition queries
|
|
7
|
+
if (/where is|what is|define/.test(normalized)) {
|
|
8
|
+
return { type: "DEFINITION", filters: { definitionsOnly: true } };
|
|
9
|
+
}
|
|
10
|
+
// Implementation queries
|
|
11
|
+
if (/how does|how is|implementation/.test(normalized)) {
|
|
12
|
+
return { type: "FLOW", mode: "orchestration_first" };
|
|
13
|
+
}
|
|
14
|
+
// Usage queries
|
|
15
|
+
if (/example|how to use|usage/.test(normalized)) {
|
|
16
|
+
return { type: "USAGE", mode: "show_examples" };
|
|
17
|
+
}
|
|
18
|
+
// Architecture queries
|
|
19
|
+
if (/architecture|system|overview/.test(normalized)) {
|
|
20
|
+
return { type: "ARCHITECTURE", mode: "group_by_role" };
|
|
21
|
+
}
|
|
22
|
+
return { type: "GENERAL" };
|
|
23
|
+
}
|