grepmax 0.1.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.
Files changed (70) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +33 -0
  3. package/README.md +375 -0
  4. package/dist/commands/claude-code.js +60 -0
  5. package/dist/commands/codex.js +98 -0
  6. package/dist/commands/doctor.js +92 -0
  7. package/dist/commands/droid.js +189 -0
  8. package/dist/commands/index.js +125 -0
  9. package/dist/commands/list.js +120 -0
  10. package/dist/commands/mcp.js +567 -0
  11. package/dist/commands/opencode.js +199 -0
  12. package/dist/commands/search.js +539 -0
  13. package/dist/commands/serve.js +502 -0
  14. package/dist/commands/setup.js +160 -0
  15. package/dist/commands/skeleton.js +288 -0
  16. package/dist/commands/symbols.js +129 -0
  17. package/dist/commands/trace.js +50 -0
  18. package/dist/commands/verify.js +174 -0
  19. package/dist/config.js +120 -0
  20. package/dist/eval.js +618 -0
  21. package/dist/index.js +82 -0
  22. package/dist/lib/core/languages.js +237 -0
  23. package/dist/lib/graph/graph-builder.js +105 -0
  24. package/dist/lib/index/chunker.js +663 -0
  25. package/dist/lib/index/grammar-loader.js +110 -0
  26. package/dist/lib/index/ignore-patterns.js +63 -0
  27. package/dist/lib/index/index-config.js +86 -0
  28. package/dist/lib/index/sync-helpers.js +97 -0
  29. package/dist/lib/index/syncer.js +396 -0
  30. package/dist/lib/index/walker.js +164 -0
  31. package/dist/lib/index/watcher.js +245 -0
  32. package/dist/lib/output/formatter.js +161 -0
  33. package/dist/lib/output/json-formatter.js +6 -0
  34. package/dist/lib/search/intent.js +23 -0
  35. package/dist/lib/search/searcher.js +475 -0
  36. package/dist/lib/setup/model-loader.js +107 -0
  37. package/dist/lib/setup/setup-helpers.js +106 -0
  38. package/dist/lib/skeleton/body-fields.js +175 -0
  39. package/dist/lib/skeleton/index.js +24 -0
  40. package/dist/lib/skeleton/retriever.js +36 -0
  41. package/dist/lib/skeleton/skeletonizer.js +483 -0
  42. package/dist/lib/skeleton/summary-formatter.js +92 -0
  43. package/dist/lib/store/meta-cache.js +143 -0
  44. package/dist/lib/store/types.js +2 -0
  45. package/dist/lib/store/vector-db.js +340 -0
  46. package/dist/lib/utils/cleanup.js +33 -0
  47. package/dist/lib/utils/exit.js +38 -0
  48. package/dist/lib/utils/file-utils.js +131 -0
  49. package/dist/lib/utils/filter-builder.js +17 -0
  50. package/dist/lib/utils/formatter.js +230 -0
  51. package/dist/lib/utils/git.js +83 -0
  52. package/dist/lib/utils/lock.js +157 -0
  53. package/dist/lib/utils/project-root.js +107 -0
  54. package/dist/lib/utils/server-registry.js +97 -0
  55. package/dist/lib/workers/colbert-math.js +107 -0
  56. package/dist/lib/workers/colbert-tokenizer.js +113 -0
  57. package/dist/lib/workers/download-worker.js +169 -0
  58. package/dist/lib/workers/embeddings/colbert.js +213 -0
  59. package/dist/lib/workers/embeddings/granite.js +180 -0
  60. package/dist/lib/workers/embeddings/mlx-client.js +144 -0
  61. package/dist/lib/workers/orchestrator.js +350 -0
  62. package/dist/lib/workers/pool.js +373 -0
  63. package/dist/lib/workers/process-child.js +92 -0
  64. package/dist/lib/workers/worker.js +31 -0
  65. package/package.json +80 -0
  66. package/plugins/osgrep/.claude-plugin/plugin.json +20 -0
  67. package/plugins/osgrep/hooks/start.js +90 -0
  68. package/plugins/osgrep/hooks/stop.js +3 -0
  69. package/plugins/osgrep/hooks.json +26 -0
  70. package/plugins/osgrep/skills/osgrep/SKILL.md +82 -0
@@ -0,0 +1,373 @@
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.WorkerPool = void 0;
46
+ exports.getWorkerPool = getWorkerPool;
47
+ exports.destroyWorkerPool = destroyWorkerPool;
48
+ exports.isWorkerPoolInitialized = isWorkerPoolInitialized;
49
+ /**
50
+ * Architecture Note: We use a custom Child Process pool instead of Worker Threads
51
+ * to ensure the ONNX Runtime segfaults do not crash the main process.
52
+ */
53
+ const childProcess = __importStar(require("node:child_process"));
54
+ const fs = __importStar(require("node:fs"));
55
+ const path = __importStar(require("node:path"));
56
+ const config_1 = require("../../config");
57
+ function reviveBufferLike(input) {
58
+ if (input &&
59
+ typeof input === "object" &&
60
+ "type" in input &&
61
+ input.type === "Buffer" &&
62
+ Array.isArray(input.data)) {
63
+ return Buffer.from(input.data);
64
+ }
65
+ return input;
66
+ }
67
+ function reviveProcessFileResult(result) {
68
+ if (!result || !Array.isArray(result.vectors))
69
+ return result;
70
+ const vectors = result.vectors.map((v) => {
71
+ const revived = reviveBufferLike(v.colbert);
72
+ return revived && (Buffer.isBuffer(revived) || revived instanceof Int8Array)
73
+ ? Object.assign(Object.assign({}, v), { colbert: revived }) : v;
74
+ });
75
+ return Object.assign(Object.assign({}, result), { vectors });
76
+ }
77
+ const TASK_TIMEOUT_MS = (() => {
78
+ var _a;
79
+ const fromEnv = Number.parseInt((_a = process.env.OSGREP_WORKER_TASK_TIMEOUT_MS) !== null && _a !== void 0 ? _a : "", 10);
80
+ if (Number.isFinite(fromEnv) && fromEnv > 0)
81
+ return fromEnv;
82
+ return 120000;
83
+ })();
84
+ const FORCE_KILL_GRACE_MS = 200;
85
+ class ProcessWorker {
86
+ constructor(modulePath, execArgv) {
87
+ this.modulePath = modulePath;
88
+ this.execArgv = execArgv;
89
+ this.busy = false;
90
+ this.pendingTaskId = null;
91
+ this.child = childProcess.fork(modulePath, {
92
+ execArgv,
93
+ env: Object.assign({}, process.env),
94
+ });
95
+ }
96
+ }
97
+ function resolveProcessWorker() {
98
+ const jsWorker = path.join(__dirname, "process-child.js");
99
+ const tsWorker = path.join(__dirname, "process-child.ts");
100
+ if (fs.existsSync(jsWorker)) {
101
+ return { filename: jsWorker, execArgv: [] };
102
+ }
103
+ if (fs.existsSync(tsWorker)) {
104
+ return { filename: tsWorker, execArgv: ["-r", "ts-node/register"] };
105
+ }
106
+ throw new Error("Process worker file not found");
107
+ }
108
+ class WorkerPool {
109
+ constructor() {
110
+ this.workers = [];
111
+ this.taskQueue = [];
112
+ this.tasks = new Map();
113
+ this.nextId = 1;
114
+ this.destroyed = false;
115
+ this.destroyPromise = null;
116
+ const resolved = resolveProcessWorker();
117
+ this.modulePath = resolved.filename;
118
+ this.execArgv = resolved.execArgv;
119
+ const workerCount = Math.max(1, config_1.CONFIG.WORKER_THREADS);
120
+ for (let i = 0; i < workerCount; i++) {
121
+ this.spawnWorker();
122
+ }
123
+ }
124
+ clearTaskTimeout(task) {
125
+ if (task.timeout) {
126
+ clearTimeout(task.timeout);
127
+ task.timeout = undefined;
128
+ }
129
+ }
130
+ removeFromQueue(taskId) {
131
+ const idx = this.taskQueue.indexOf(taskId);
132
+ if (idx !== -1)
133
+ this.taskQueue.splice(idx, 1);
134
+ }
135
+ completeTask(task, worker) {
136
+ this.clearTaskTimeout(task);
137
+ this.tasks.delete(task.id);
138
+ this.removeFromQueue(task.id);
139
+ if (worker) {
140
+ worker.busy = false;
141
+ worker.pendingTaskId = null;
142
+ }
143
+ }
144
+ handleWorkerExit(worker, code, signal) {
145
+ worker.busy = false;
146
+ const failedTasks = Array.from(this.tasks.values()).filter((t) => t.worker === worker);
147
+ for (const task of failedTasks) {
148
+ this.clearTaskTimeout(task);
149
+ task.reject(new Error(`Worker exited unexpectedly${code ? ` (code ${code})` : ""}${signal ? ` signal ${signal}` : ""}`));
150
+ this.completeTask(task, null);
151
+ }
152
+ this.workers = this.workers.filter((w) => w !== worker);
153
+ if (!this.destroyed) {
154
+ this.spawnWorker();
155
+ this.dispatch();
156
+ }
157
+ }
158
+ spawnWorker() {
159
+ const worker = new ProcessWorker(this.modulePath, this.execArgv);
160
+ const onMessage = (msg) => {
161
+ const task = this.tasks.get(msg.id);
162
+ if (!task)
163
+ return;
164
+ if ("heartbeat" in msg) {
165
+ // Reset timeout
166
+ this.clearTaskTimeout(task);
167
+ if (task.worker) {
168
+ task.timeout = setTimeout(() => this.handleTaskTimeout(task, task.worker), TASK_TIMEOUT_MS);
169
+ }
170
+ return;
171
+ }
172
+ if ("error" in msg) {
173
+ task.reject(new Error(msg.error));
174
+ }
175
+ else {
176
+ let result = msg.result;
177
+ if (task.method === "processFile") {
178
+ result = reviveProcessFileResult(result);
179
+ }
180
+ task.resolve(result);
181
+ }
182
+ this.completeTask(task, worker);
183
+ this.dispatch();
184
+ };
185
+ const onExit = (code, signal) => this.handleWorkerExit(worker, code, signal);
186
+ worker.child.on("message", onMessage);
187
+ worker.child.on("exit", onExit);
188
+ this.workers.push(worker);
189
+ }
190
+ enqueue(method, payload, signal) {
191
+ if (this.destroyed) {
192
+ return Promise.reject(new Error("Worker pool destroyed"));
193
+ }
194
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
195
+ const err = new Error("Aborted");
196
+ err.name = "AbortError";
197
+ return Promise.reject(err);
198
+ }
199
+ const id = this.nextId++;
200
+ return new Promise((resolve, reject) => {
201
+ let settled = false;
202
+ const safeResolve = (val) => {
203
+ if (!settled) {
204
+ settled = true;
205
+ resolve(val);
206
+ }
207
+ };
208
+ const safeReject = (reason) => {
209
+ if (!settled) {
210
+ settled = true;
211
+ reject(reason);
212
+ }
213
+ };
214
+ const task = {
215
+ id,
216
+ method,
217
+ payload,
218
+ resolve: safeResolve,
219
+ reject: safeReject,
220
+ };
221
+ if (signal) {
222
+ signal.addEventListener("abort", () => {
223
+ // If task is still in queue, remove it
224
+ const idx = this.taskQueue.indexOf(id);
225
+ if (idx !== -1) {
226
+ this.taskQueue.splice(idx, 1);
227
+ this.tasks.delete(id);
228
+ const err = new Error("Aborted");
229
+ err.name = "AbortError";
230
+ safeReject(err);
231
+ }
232
+ // If task is already running (assigned to worker), we can't easily kill it without
233
+ // killing the worker. For now, we just let it finish but reject the promise early so
234
+ // the caller doesn't wait. The worker will eventually finish and we'll ignore the result.
235
+ else if (this.tasks.has(id)) {
236
+ // Task is running. Reject caller immediately.
237
+ const err = new Error("Aborted");
238
+ err.name = "AbortError";
239
+ safeReject(err);
240
+ // We intentionally do NOT delete the task map entry here,
241
+ // because we need handleWorkerMessage to cleanly cleanup the worker state
242
+ // when it eventually finishes.
243
+ }
244
+ }, { once: true });
245
+ }
246
+ this.tasks.set(id, task);
247
+ this.taskQueue.push(id);
248
+ this.dispatch();
249
+ });
250
+ }
251
+ handleTaskTimeout(task, worker) {
252
+ if (this.destroyed || !this.tasks.has(task.id))
253
+ return;
254
+ this.clearTaskTimeout(task);
255
+ if (task.method !== "processFile") {
256
+ console.warn(`[worker-pool] ${task.method} timed out after ${TASK_TIMEOUT_MS}ms; restarting worker.`);
257
+ }
258
+ this.completeTask(task, null);
259
+ task.reject(new Error(`Worker task ${task.method} timed out after ${TASK_TIMEOUT_MS}ms`));
260
+ worker.child.removeAllListeners("message");
261
+ worker.child.removeAllListeners("exit");
262
+ try {
263
+ worker.child.kill("SIGKILL");
264
+ }
265
+ catch (_a) { }
266
+ this.workers = this.workers.filter((w) => w !== worker);
267
+ if (!this.destroyed) {
268
+ this.spawnWorker();
269
+ }
270
+ this.dispatch();
271
+ }
272
+ dispatch() {
273
+ if (this.destroyed)
274
+ return;
275
+ const idle = this.workers.find((w) => !w.busy);
276
+ const nextTaskId = this.taskQueue.find((id) => {
277
+ const t = this.tasks.get(id);
278
+ return t && !t.worker;
279
+ });
280
+ if (!idle || nextTaskId === undefined)
281
+ return;
282
+ const task = this.tasks.get(nextTaskId);
283
+ if (!task) {
284
+ this.removeFromQueue(nextTaskId);
285
+ this.dispatch();
286
+ return;
287
+ }
288
+ idle.busy = true;
289
+ idle.pendingTaskId = task.id;
290
+ task.worker = idle;
291
+ task.timeout = setTimeout(() => this.handleTaskTimeout(task, idle), TASK_TIMEOUT_MS);
292
+ try {
293
+ idle.child.send({
294
+ id: task.id,
295
+ method: task.method,
296
+ payload: task.payload,
297
+ });
298
+ }
299
+ catch (err) {
300
+ this.clearTaskTimeout(task);
301
+ this.completeTask(task, idle);
302
+ task.reject(err);
303
+ return;
304
+ }
305
+ this.dispatch();
306
+ }
307
+ processFile(input) {
308
+ // ProcessFile doesn't currently use cancellation, but we could add it later
309
+ return this.enqueue("processFile", input);
310
+ }
311
+ encodeQuery(text, signal) {
312
+ return this.enqueue("encodeQuery", { text }, signal);
313
+ }
314
+ rerank(input, signal) {
315
+ return this.enqueue("rerank", input, signal);
316
+ }
317
+ destroy() {
318
+ return __awaiter(this, void 0, void 0, function* () {
319
+ if (this.destroyPromise)
320
+ return this.destroyPromise;
321
+ if (this.destroyed)
322
+ return;
323
+ this.destroyed = true;
324
+ for (const task of this.tasks.values()) {
325
+ this.clearTaskTimeout(task);
326
+ task.reject(new Error("Worker pool destroyed"));
327
+ }
328
+ this.tasks.clear();
329
+ this.taskQueue = [];
330
+ const killPromises = this.workers.map((w) => new Promise((resolve) => {
331
+ w.child.removeAllListeners("message");
332
+ w.child.removeAllListeners("exit");
333
+ w.child.once("exit", () => resolve());
334
+ w.child.kill("SIGTERM");
335
+ const force = setTimeout(() => {
336
+ try {
337
+ w.child.kill("SIGKILL");
338
+ }
339
+ catch (_a) { }
340
+ }, FORCE_KILL_GRACE_MS);
341
+ setTimeout(() => {
342
+ clearTimeout(force);
343
+ resolve();
344
+ }, config_1.WORKER_TIMEOUT_MS);
345
+ }));
346
+ this.destroyPromise = Promise.allSettled(killPromises).then(() => {
347
+ this.workers = [];
348
+ this.destroyPromise = null;
349
+ });
350
+ yield this.destroyPromise;
351
+ });
352
+ }
353
+ }
354
+ exports.WorkerPool = WorkerPool;
355
+ let singleton = null;
356
+ function getWorkerPool() {
357
+ if (!singleton) {
358
+ singleton = new WorkerPool();
359
+ }
360
+ return singleton;
361
+ }
362
+ function destroyWorkerPool() {
363
+ return __awaiter(this, void 0, void 0, function* () {
364
+ if (!singleton)
365
+ return;
366
+ const pool = singleton;
367
+ singleton = null;
368
+ yield pool.destroy();
369
+ });
370
+ }
371
+ function isWorkerPoolInitialized() {
372
+ return singleton !== null;
373
+ }
@@ -0,0 +1,92 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ const node_process_1 = __importDefault(require("node:process"));
49
+ const worker_1 = __importStar(require("./worker"));
50
+ const send = (msg) => {
51
+ if (node_process_1.default.send) {
52
+ node_process_1.default.send(msg);
53
+ }
54
+ };
55
+ node_process_1.default.on("message", (msg) => __awaiter(void 0, void 0, void 0, function* () {
56
+ const { id, method, payload } = msg;
57
+ try {
58
+ if (method === "processFile") {
59
+ const onProgress = () => {
60
+ send({ id, heartbeat: true });
61
+ };
62
+ const result = yield (0, worker_1.default)(payload, onProgress);
63
+ send({ id, result });
64
+ return;
65
+ }
66
+ if (method === "encodeQuery") {
67
+ const result = yield (0, worker_1.encodeQuery)(payload);
68
+ send({ id, result });
69
+ return;
70
+ }
71
+ if (method === "rerank") {
72
+ const result = yield (0, worker_1.rerank)(payload);
73
+ send({ id, result });
74
+ return;
75
+ }
76
+ send({ id, error: `Unknown method: ${method}` });
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : String(err);
80
+ send({ id, error: message });
81
+ }
82
+ }));
83
+ node_process_1.default.on("uncaughtException", (err) => {
84
+ console.error("[process-worker] uncaughtException", err);
85
+ node_process_1.default.exitCode = 1;
86
+ node_process_1.default.exit();
87
+ });
88
+ node_process_1.default.on("unhandledRejection", (reason) => {
89
+ console.error("[process-worker] unhandledRejection", reason);
90
+ node_process_1.default.exitCode = 1;
91
+ node_process_1.default.exit();
92
+ });
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.default = processFile;
13
+ exports.encodeQuery = encodeQuery;
14
+ exports.rerank = rerank;
15
+ const orchestrator_1 = require("./orchestrator");
16
+ const orchestrator = new orchestrator_1.WorkerOrchestrator();
17
+ function processFile(input, onProgress) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ return orchestrator.processFile(input, onProgress);
20
+ });
21
+ }
22
+ function encodeQuery(input) {
23
+ return __awaiter(this, void 0, void 0, function* () {
24
+ return orchestrator.encodeQuery(input.text);
25
+ });
26
+ }
27
+ function rerank(input) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ return orchestrator.rerank(input);
30
+ });
31
+ }
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "grepmax",
3
+ "version": "0.1.0",
4
+ "author": "Robert Owens <robowens@me.com>",
5
+ "homepage": "https://github.com/reowens/grepmax",
6
+ "bugs": {
7
+ "url": "https://github.com/reowens/grepmax/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/reowens/grepmax.git"
12
+ },
13
+ "main": "index.js",
14
+ "bin": {
15
+ "osgrep": "dist/index.js"
16
+ },
17
+ "scripts": {
18
+ "prebuild": "mkdir -p dist",
19
+ "build": "tsc",
20
+ "postbuild": "chmod +x dist/index.js",
21
+ "dev": "npx tsc && node dist/index.js",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "benchmark": "./run-benchmark.sh",
25
+ "benchmark:index": "./run-benchmark.sh $HOME/osgrep-benchmarks --index",
26
+ "benchmark:agent": "npx tsx src/bench/benchmark-agent.ts",
27
+ "benchmark:chart": "npx tsx src/bench/generate-benchmark-chart.ts",
28
+ "format": "biome check --write .",
29
+ "format:check": "biome check .",
30
+ "lint": "biome lint .",
31
+ "typecheck": "tsc --noEmit",
32
+ "prepublishOnly": "pnpm build"
33
+ },
34
+ "keywords": [
35
+ "osgrep",
36
+ "grep",
37
+ "glob",
38
+ "search"
39
+ ],
40
+ "files": [
41
+ "dist",
42
+ "plugins",
43
+ "README.md",
44
+ "LICENSE",
45
+ "NOTICE"
46
+ ],
47
+ "license": "Apache-2.0",
48
+ "description": "Local grep-like search tool for your codebase.",
49
+ "dependencies": {
50
+ "@clack/prompts": "^1.1.0",
51
+ "@huggingface/transformers": "^3.8.0",
52
+ "@lancedb/lancedb": "^0.26.2",
53
+ "@modelcontextprotocol/sdk": "^1.24.3",
54
+ "apache-arrow": "^18.1.0",
55
+ "chalk": "^5.6.2",
56
+ "chokidar": "^5.0.0",
57
+ "cli-highlight": "^2.1.11",
58
+ "commander": "^14.0.2",
59
+ "dotenv": "^17.2.3",
60
+ "fast-glob": "^3.3.3",
61
+ "ignore": "^7.0.5",
62
+ "lmdb": "^3.4.4",
63
+ "onnxruntime-node": "1.24.3",
64
+ "ora": "^5.4.1",
65
+ "piscina": "^5.1.4",
66
+ "simsimd": "^6.5.5",
67
+ "uuid": "^13.0.0",
68
+ "web-tree-sitter": "^0.26.6",
69
+ "zod": "^4.1.12"
70
+ },
71
+ "devDependencies": {
72
+ "@anthropic-ai/claude-agent-sdk": "^0.2.76",
73
+ "@biomejs/biome": "2.4.7",
74
+ "@types/node": "^25.5.0",
75
+ "node-gyp": "^12.1.0",
76
+ "ts-node": "^10.9.2",
77
+ "typescript": "^5.9.3",
78
+ "vitest": "^1.6.1"
79
+ }
80
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "osgrep",
3
+ "version": "0.1.0",
4
+ "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
+ "author": {
6
+ "name": "Robert Owens",
7
+ "email": "robowens@me.com"
8
+ },
9
+ "hooks": "./hooks.json",
10
+ "homepage": "https://github.com/reowens/osgrep-max",
11
+ "repository": "https://github.com/reowens/osgrep-max",
12
+ "license": "Apache-2.0",
13
+ "keywords": [
14
+ "search",
15
+ "semantic",
16
+ "grep",
17
+ "code-search",
18
+ "semantic-search"
19
+ ]
20
+ }
@@ -0,0 +1,90 @@
1
+ const fs = require("node:fs");
2
+ const os = require("node:os");
3
+ const _path = require("node:path");
4
+ const http = require("node:http");
5
+ const { spawn } = require("node:child_process");
6
+
7
+ function readPayload() {
8
+ try {
9
+ const raw = fs.readFileSync(0, "utf-8");
10
+ return raw ? JSON.parse(raw) : {};
11
+ } catch {
12
+ return {};
13
+ }
14
+ }
15
+
16
+ function isServerRunning(cwd) {
17
+ // Read the global server registry (matches how osgrep serve registers)
18
+ const registryPath = _path.join(os.homedir(), ".osgrep", "servers.json");
19
+ try {
20
+ const servers = JSON.parse(fs.readFileSync(registryPath, "utf-8"));
21
+ const match = servers.find((s) => s.projectRoot === cwd);
22
+ if (match && typeof match.pid === "number") {
23
+ process.kill(match.pid, 0); // throws if not running
24
+ return true;
25
+ }
26
+ } catch {}
27
+ return false;
28
+ }
29
+
30
+ function isMlxRunning() {
31
+ return new Promise((resolve) => {
32
+ const req = http.get(
33
+ { hostname: "127.0.0.1", port: 8100, path: "/health", timeout: 1000 },
34
+ (res) => {
35
+ res.resume();
36
+ resolve(res.statusCode === 200);
37
+ }
38
+ );
39
+ req.on("error", () => resolve(false));
40
+ req.on("timeout", () => { req.destroy(); resolve(false); });
41
+ });
42
+ }
43
+
44
+ function startMlxServer() {
45
+ // Find the mlx-embed-server directory relative to plugin root
46
+ const pluginRoot = __dirname.replace(/\/hooks$/, "");
47
+ const osgrepRoot = _path.resolve(pluginRoot, "../..");
48
+ const serverDir = _path.join(osgrepRoot, "mlx-embed-server");
49
+
50
+ if (!fs.existsSync(_path.join(serverDir, "server.py"))) return;
51
+
52
+ const logPath = "/tmp/mlx-embed-server.log";
53
+ const out = fs.openSync(logPath, "a");
54
+
55
+ const child = spawn("uv", ["run", "python", "server.py"], {
56
+ cwd: serverDir,
57
+ detached: true,
58
+ stdio: ["ignore", out, out],
59
+ });
60
+ child.unref();
61
+ }
62
+
63
+ async function main() {
64
+ const payload = readPayload();
65
+ const cwd = payload.cwd || process.cwd();
66
+
67
+ // Check if osgrep serve is running (read-only — MCP server owns daemon lifecycle)
68
+ const daemonUp = isServerRunning(cwd);
69
+
70
+ // Start MLX embed server if not running (set OSGREP_EMBED_MODE=cpu to skip)
71
+ const embedMode = process.env.OSGREP_EMBED_MODE || "auto";
72
+ if (embedMode !== "cpu") {
73
+ const mlxUp = await isMlxRunning();
74
+ if (!mlxUp) {
75
+ startMlxServer();
76
+ }
77
+ }
78
+
79
+ const status = daemonUp ? "running" : "starting via MCP";
80
+ const response = {
81
+ hookSpecificOutput: {
82
+ hookEventName: "SessionStart",
83
+ additionalContext:
84
+ `osgrep serve ${status}; prefer \`osgrep "<complete question>"\` over grep (plain output is agent-friendly).`,
85
+ },
86
+ };
87
+ process.stdout.write(JSON.stringify(response));
88
+ }
89
+
90
+ main();
@@ -0,0 +1,3 @@
1
+ // No-op: let osgrep serve persist across sessions.
2
+ // The start hook ensures exactly one is running.
3
+ // Use `osgrep serve stop` to explicitly shut it down.