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.
- 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 +567 -0
- package/dist/commands/opencode.js +199 -0
- package/dist/commands/search.js +539 -0
- package/dist/commands/serve.js +502 -0
- package/dist/commands/setup.js +160 -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 +92 -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 +90 -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,98 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.uninstallCodex = exports.installCodex = void 0;
|
|
16
|
+
const node_child_process_1 = require("node:child_process");
|
|
17
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
18
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
19
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
20
|
+
const node_util_1 = require("node:util");
|
|
21
|
+
const commander_1 = require("commander");
|
|
22
|
+
const shell = process.env.SHELL || (process.platform === "win32" ? "cmd.exe" : "/bin/sh");
|
|
23
|
+
const execAsync = (0, node_util_1.promisify)(node_child_process_1.exec);
|
|
24
|
+
const SKILL = `
|
|
25
|
+
---
|
|
26
|
+
name: osgrep
|
|
27
|
+
description: Semantic code search and call-graph tracing via osgrep.
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## ⚠️ CRITICAL: Handling "Indexing" State
|
|
31
|
+
If the tool output says **"Indexing"**, **"Building"**, or **"Syncing"**:
|
|
32
|
+
1. **STOP.** Do not hallucinate results.
|
|
33
|
+
2. **INFORM** the user: "The semantic index is still building. Results are partial."
|
|
34
|
+
3. **ASK** if they want to proceed or wait.
|
|
35
|
+
|
|
36
|
+
## Commands
|
|
37
|
+
- Search: \`osgrep "auth logic" --compact\`
|
|
38
|
+
- Trace: \`osgrep trace "AuthService"\`
|
|
39
|
+
`;
|
|
40
|
+
function installPlugin() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
try {
|
|
43
|
+
// 1. Register the MCP Tool
|
|
44
|
+
// 'osgrep mcp' acts as the server.
|
|
45
|
+
yield execAsync("codex mcp add osgrep osgrep mcp", {
|
|
46
|
+
shell,
|
|
47
|
+
env: process.env,
|
|
48
|
+
});
|
|
49
|
+
console.log("✅ osgrep MCP tool registered with Codex");
|
|
50
|
+
// 2. Add Instructions to AGENTS.md
|
|
51
|
+
const destPath = node_path_1.default.join(node_os_1.default.homedir(), ".codex", "AGENTS.md");
|
|
52
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(destPath), { recursive: true });
|
|
53
|
+
const content = node_fs_1.default.existsSync(destPath)
|
|
54
|
+
? node_fs_1.default.readFileSync(destPath, "utf-8")
|
|
55
|
+
: "";
|
|
56
|
+
// Only append if not present
|
|
57
|
+
if (!content.includes("name: osgrep")) {
|
|
58
|
+
node_fs_1.default.appendFileSync(destPath, "\n" + SKILL);
|
|
59
|
+
console.log("✅ osgrep skill instructions added to Codex");
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log("ℹ️ osgrep skill instructions already present");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error(`❌ Error installing Codex plugin: ${error}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function uninstallPlugin() {
|
|
72
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
try {
|
|
74
|
+
yield execAsync("codex mcp remove osgrep", { shell, env: process.env });
|
|
75
|
+
console.log("✅ osgrep MCP tool removed");
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
/* ignore if not found */
|
|
79
|
+
}
|
|
80
|
+
const destPath = node_path_1.default.join(node_os_1.default.homedir(), ".codex", "AGENTS.md");
|
|
81
|
+
if (node_fs_1.default.existsSync(destPath)) {
|
|
82
|
+
let content = node_fs_1.default.readFileSync(destPath, "utf-8");
|
|
83
|
+
// Naive removal: strictly matches the block we added.
|
|
84
|
+
// For robust removal, you might need regex, but this works if the string is exact.
|
|
85
|
+
if (content.includes(SKILL)) {
|
|
86
|
+
content = content.replace(SKILL, "").trim();
|
|
87
|
+
node_fs_1.default.writeFileSync(destPath, content);
|
|
88
|
+
console.log("✅ osgrep instructions removed from AGENTS.md");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
exports.installCodex = new commander_1.Command("install-codex")
|
|
94
|
+
.description("Install osgrep for Codex")
|
|
95
|
+
.action(installPlugin);
|
|
96
|
+
exports.uninstallCodex = new commander_1.Command("uninstall-codex")
|
|
97
|
+
.description("Uninstall osgrep from Codex")
|
|
98
|
+
.action(uninstallPlugin);
|
|
@@ -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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.doctor = void 0;
|
|
46
|
+
const fs = __importStar(require("node:fs"));
|
|
47
|
+
const os = __importStar(require("node:os"));
|
|
48
|
+
const path = __importStar(require("node:path"));
|
|
49
|
+
const commander_1 = require("commander");
|
|
50
|
+
const config_1 = require("../config");
|
|
51
|
+
const exit_1 = require("../lib/utils/exit");
|
|
52
|
+
const project_root_1 = require("../lib/utils/project-root");
|
|
53
|
+
exports.doctor = new commander_1.Command("doctor")
|
|
54
|
+
.description("Check osgrep health and paths")
|
|
55
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
56
|
+
console.log("🏥 osgrep Doctor\n");
|
|
57
|
+
const root = config_1.PATHS.globalRoot;
|
|
58
|
+
const models = config_1.PATHS.models;
|
|
59
|
+
const grammars = config_1.PATHS.grammars;
|
|
60
|
+
const modelIds = [config_1.MODEL_IDS.embed, config_1.MODEL_IDS.colbert];
|
|
61
|
+
const checkDir = (name, p) => {
|
|
62
|
+
const exists = fs.existsSync(p);
|
|
63
|
+
const symbol = exists ? "✅" : "❌";
|
|
64
|
+
console.log(`${symbol} ${name}: ${p}`);
|
|
65
|
+
};
|
|
66
|
+
checkDir("Root", root);
|
|
67
|
+
checkDir("Models", models);
|
|
68
|
+
checkDir("Grammars", grammars);
|
|
69
|
+
const modelStatuses = modelIds.map((id) => {
|
|
70
|
+
const modelPath = path.join(models, ...id.split("/"));
|
|
71
|
+
return { id, path: modelPath, exists: fs.existsSync(modelPath) };
|
|
72
|
+
});
|
|
73
|
+
modelStatuses.forEach(({ id, path: p, exists }) => {
|
|
74
|
+
const symbol = exists ? "✅" : "❌";
|
|
75
|
+
console.log(`${symbol} Model: ${id} (${p})`);
|
|
76
|
+
});
|
|
77
|
+
const missingModels = modelStatuses.filter(({ exists }) => !exists);
|
|
78
|
+
if (missingModels.length > 0) {
|
|
79
|
+
console.log("❌ Some models are missing; osgrep will try bundled copies first, then download.");
|
|
80
|
+
}
|
|
81
|
+
console.log(`\nLocal Project: ${process.cwd()}`);
|
|
82
|
+
const projectRoot = (0, project_root_1.findProjectRoot)(process.cwd());
|
|
83
|
+
if (projectRoot) {
|
|
84
|
+
console.log(`✅ Index found at: ${path.join(projectRoot, ".osgrep")}`);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
console.log(`ℹ️ No index found in current directory (run 'osgrep index' to create one)`);
|
|
88
|
+
}
|
|
89
|
+
console.log(`\nSystem: ${os.platform()} ${os.arch()} | Node: ${process.version}`);
|
|
90
|
+
console.log("\nIf you see ✅ everywhere, you are ready to search!");
|
|
91
|
+
yield (0, exit_1.gracefulExit)();
|
|
92
|
+
}));
|
|
@@ -0,0 +1,189 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.uninstallDroid = exports.installDroid = void 0;
|
|
16
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
17
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
18
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
+
const commander_1 = require("commander");
|
|
20
|
+
const SKILL = `
|
|
21
|
+
---
|
|
22
|
+
name: osgrep
|
|
23
|
+
description: Semantic code search and call-graph tracing for AI agents. Finds code by concept, surfaces roles (ORCHESTRATION vs DEFINITION), and traces dependencies.
|
|
24
|
+
allowed-tools: "Bash(osgrep:*), Read"
|
|
25
|
+
license: Apache-2.0
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⚠️ CRITICAL: Handling "Indexing" State
|
|
29
|
+
If any \`osgrep\` command returns a status indicating **"Indexing"**, **"Building"**, or **"Syncing"**:
|
|
30
|
+
1. **STOP** your current train of thought.
|
|
31
|
+
2. **INFORM** the user: "The semantic index is currently building. Search results will be incomplete."
|
|
32
|
+
3. **ASK**: "Do you want me to proceed with partial results, or wait for indexing to finish?"
|
|
33
|
+
*(Do not assume you should proceed without confirmation).*
|
|
34
|
+
|
|
35
|
+
## Core Commands
|
|
36
|
+
- Search: \`osgrep "how does auth work" --compact\`
|
|
37
|
+
- Trace: \`osgrep trace "AuthService"\`
|
|
38
|
+
- Symbols: \`osgrep symbols "Auth"\`
|
|
39
|
+
|
|
40
|
+
## Output (Default = Compact TSV)
|
|
41
|
+
- One line per hit: \`path\\tlines\\tscore\\trole\\tconf\\tdefined\\tpreview\`
|
|
42
|
+
- Roles: \`ORCH\` (Orchestration), \`DEF\` (Definition), \`IMPL\` (Implementation).
|
|
43
|
+
- **Note:** If output is empty but valid, say "No semantic matches found."
|
|
44
|
+
|
|
45
|
+
## Typical Workflow
|
|
46
|
+
|
|
47
|
+
1. **Discover**
|
|
48
|
+
\`\`\`bash
|
|
49
|
+
osgrep "worker pool lifecycle" --compact
|
|
50
|
+
\`\`\`
|
|
51
|
+
|
|
52
|
+
2. **Explore**
|
|
53
|
+
\`\`\`bash
|
|
54
|
+
osgrep symbols Worker
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
3. **Trace**
|
|
58
|
+
\`\`\`bash
|
|
59
|
+
osgrep trace WorkerPool
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
4. **Read**
|
|
63
|
+
\`\`\`bash
|
|
64
|
+
Read src/lib/workers/pool.ts:112-186
|
|
65
|
+
\`\`\`
|
|
66
|
+
`;
|
|
67
|
+
function resolveDroidRoot() {
|
|
68
|
+
const root = node_path_1.default.join(node_os_1.default.homedir(), ".factory");
|
|
69
|
+
if (!node_fs_1.default.existsSync(root)) {
|
|
70
|
+
throw new Error(`Factory Droid directory not found at ${root}. Run Factory Droid once to initialize.`);
|
|
71
|
+
}
|
|
72
|
+
return root;
|
|
73
|
+
}
|
|
74
|
+
function writeFileIfChanged(filePath, content) {
|
|
75
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(filePath), { recursive: true });
|
|
76
|
+
const already = node_fs_1.default.existsSync(filePath)
|
|
77
|
+
? node_fs_1.default.readFileSync(filePath, "utf-8")
|
|
78
|
+
: undefined;
|
|
79
|
+
if (already !== content)
|
|
80
|
+
node_fs_1.default.writeFileSync(filePath, content);
|
|
81
|
+
}
|
|
82
|
+
function parseJsonWithComments(content) {
|
|
83
|
+
const stripped = content
|
|
84
|
+
.split("\n")
|
|
85
|
+
.map((line) => line.replace(/^\s*\/\/.*$/, ""))
|
|
86
|
+
.join("\n");
|
|
87
|
+
try {
|
|
88
|
+
return JSON.parse(stripped);
|
|
89
|
+
}
|
|
90
|
+
catch (_a) {
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function loadSettings(settingsPath) {
|
|
95
|
+
if (!node_fs_1.default.existsSync(settingsPath))
|
|
96
|
+
return {};
|
|
97
|
+
return parseJsonWithComments(node_fs_1.default.readFileSync(settingsPath, "utf-8"));
|
|
98
|
+
}
|
|
99
|
+
function saveSettings(settingsPath, settings) {
|
|
100
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(settingsPath), { recursive: true });
|
|
101
|
+
node_fs_1.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
102
|
+
}
|
|
103
|
+
function mergeHooks(existing, incoming) {
|
|
104
|
+
const merged = existing ? JSON.parse(JSON.stringify(existing)) : {};
|
|
105
|
+
for (const [event, entries] of Object.entries(incoming)) {
|
|
106
|
+
const current = merged[event] || [];
|
|
107
|
+
for (const entry of entries) {
|
|
108
|
+
// Simple duplicate check based on command string
|
|
109
|
+
const cmd = entry.hooks[0].command;
|
|
110
|
+
if (!current.some((c) => c.hooks[0].command === cmd)) {
|
|
111
|
+
current.push(entry);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
merged[event] = current;
|
|
115
|
+
}
|
|
116
|
+
return merged;
|
|
117
|
+
}
|
|
118
|
+
// --- MAIN INSTALLER ---
|
|
119
|
+
function installPlugin() {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
const root = resolveDroidRoot();
|
|
122
|
+
const hooksDir = node_path_1.default.join(root, "hooks", "osgrep");
|
|
123
|
+
const skillsDir = node_path_1.default.join(root, "skills", "osgrep");
|
|
124
|
+
const settingsPath = node_path_1.default.join(root, "settings.json");
|
|
125
|
+
// 1. Install Hook Scripts (Start/Stop Daemon)
|
|
126
|
+
// We expect these files to exist in your dist/hooks folder
|
|
127
|
+
const startJsPath = node_path_1.default.join(hooksDir, "osgrep_start.js");
|
|
128
|
+
const stopJsPath = node_path_1.default.join(hooksDir, "osgrep_stop.js");
|
|
129
|
+
// Create these scripts dynamically if we don't want to read from dist
|
|
130
|
+
const startScript = `
|
|
131
|
+
const { spawn } = require("child_process");
|
|
132
|
+
const fs = require("fs");
|
|
133
|
+
const out = fs.openSync("/tmp/osgrep.log", "a");
|
|
134
|
+
const child = spawn("osgrep", ["serve"], { detached: true, stdio: ["ignore", out, out] });
|
|
135
|
+
child.unref();
|
|
136
|
+
`;
|
|
137
|
+
const stopScript = `
|
|
138
|
+
const { spawnSync, execSync } = require("child_process");
|
|
139
|
+
try { execSync("pkill -f 'osgrep serve'"); } catch {}
|
|
140
|
+
`;
|
|
141
|
+
writeFileIfChanged(startJsPath, startScript.trim());
|
|
142
|
+
writeFileIfChanged(stopJsPath, stopScript.trim());
|
|
143
|
+
// 2. Install Skill (with Indexing Warning)
|
|
144
|
+
writeFileIfChanged(node_path_1.default.join(skillsDir, "SKILL.md"), SKILL.trimStart());
|
|
145
|
+
// 3. Configure Settings
|
|
146
|
+
const hookConfig = {
|
|
147
|
+
SessionStart: [
|
|
148
|
+
{
|
|
149
|
+
matcher: "startup|resume",
|
|
150
|
+
hooks: [
|
|
151
|
+
{ type: "command", command: `node "${startJsPath}"`, timeout: 10 },
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
SessionEnd: [
|
|
156
|
+
{
|
|
157
|
+
hooks: [
|
|
158
|
+
{ type: "command", command: `node "${stopJsPath}"`, timeout: 10 },
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
const settings = loadSettings(settingsPath);
|
|
164
|
+
settings.enableHooks = true;
|
|
165
|
+
settings.allowBackgroundProcesses = true;
|
|
166
|
+
settings.hooks = mergeHooks(settings.hooks, hookConfig);
|
|
167
|
+
saveSettings(settingsPath, settings);
|
|
168
|
+
console.log(`✅ osgrep installed for Factory Droid (Hooks + Skill)`);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function uninstallPlugin() {
|
|
172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
const root = resolveDroidRoot();
|
|
174
|
+
const hooksDir = node_path_1.default.join(root, "hooks", "osgrep");
|
|
175
|
+
const skillsDir = node_path_1.default.join(root, "skills", "osgrep");
|
|
176
|
+
if (node_fs_1.default.existsSync(hooksDir))
|
|
177
|
+
node_fs_1.default.rmSync(hooksDir, { recursive: true, force: true });
|
|
178
|
+
if (node_fs_1.default.existsSync(skillsDir))
|
|
179
|
+
node_fs_1.default.rmSync(skillsDir, { recursive: true, force: true });
|
|
180
|
+
console.log("✅ osgrep removed from Factory Droid");
|
|
181
|
+
console.log("NOTE: You may want to manually clean up 'hooks' in ~/.factory/settings.json");
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
exports.installDroid = new commander_1.Command("install-droid")
|
|
185
|
+
.description("Install osgrep for Factory Droid")
|
|
186
|
+
.action(installPlugin);
|
|
187
|
+
exports.uninstallDroid = new commander_1.Command("uninstall-droid")
|
|
188
|
+
.description("Uninstall osgrep from Factory Droid")
|
|
189
|
+
.action(uninstallPlugin);
|
|
@@ -0,0 +1,125 @@
|
|
|
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.index = void 0;
|
|
46
|
+
const path = __importStar(require("node:path"));
|
|
47
|
+
const commander_1 = require("commander");
|
|
48
|
+
const grammar_loader_1 = require("../lib/index/grammar-loader");
|
|
49
|
+
const sync_helpers_1 = require("../lib/index/sync-helpers");
|
|
50
|
+
const syncer_1 = require("../lib/index/syncer");
|
|
51
|
+
const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
52
|
+
const vector_db_1 = require("../lib/store/vector-db");
|
|
53
|
+
const exit_1 = require("../lib/utils/exit");
|
|
54
|
+
const project_root_1 = require("../lib/utils/project-root");
|
|
55
|
+
exports.index = new commander_1.Command("index")
|
|
56
|
+
.description("Index the current directory and create searchable store")
|
|
57
|
+
.option("-d, --dry-run", "Dry run the indexing process (no actual file syncing)", false)
|
|
58
|
+
.option("-p, --path <dir>", "Path to index (defaults to current directory)", "")
|
|
59
|
+
.option("-r, --reset", "Remove existing index and re-index from scratch", false)
|
|
60
|
+
.option("-v, --verbose", "Show detailed progress with file names", false)
|
|
61
|
+
.action((_args, cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
var _a;
|
|
63
|
+
const options = cmd.optsWithGlobals();
|
|
64
|
+
let vectorDb = null;
|
|
65
|
+
try {
|
|
66
|
+
yield (0, setup_helpers_1.ensureSetup)();
|
|
67
|
+
const indexRoot = options.path
|
|
68
|
+
? path.resolve(options.path)
|
|
69
|
+
: process.cwd();
|
|
70
|
+
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(indexRoot)) !== null && _a !== void 0 ? _a : indexRoot;
|
|
71
|
+
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
72
|
+
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
73
|
+
if (options.reset) {
|
|
74
|
+
console.log(`Resetting index at ${paths.osgrepDir}...`);
|
|
75
|
+
// We do NOT manually drop/rm here anymore to avoid race conditions.
|
|
76
|
+
// The syncer handles it inside the lock.
|
|
77
|
+
}
|
|
78
|
+
// Ensure grammars are present before indexing (silent if already exist)
|
|
79
|
+
yield (0, grammar_loader_1.ensureGrammars)(console.log, { silent: true });
|
|
80
|
+
const { spinner, onProgress } = (0, sync_helpers_1.createIndexingSpinner)(projectRoot, "Indexing...", { verbose: options.verbose });
|
|
81
|
+
try {
|
|
82
|
+
const result = yield (0, syncer_1.initialSync)({
|
|
83
|
+
projectRoot,
|
|
84
|
+
dryRun: options.dryRun,
|
|
85
|
+
reset: options.reset,
|
|
86
|
+
onProgress,
|
|
87
|
+
});
|
|
88
|
+
if (options.dryRun) {
|
|
89
|
+
spinner.succeed(`Dry run complete(${result.processed} / ${result.total}) • would have indexed ${result.indexed} `);
|
|
90
|
+
console.log((0, sync_helpers_1.formatDryRunSummary)(result, {
|
|
91
|
+
actionDescription: "would have indexed",
|
|
92
|
+
includeTotal: true,
|
|
93
|
+
}));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const failedSuffix = result.failedFiles > 0 ? ` • ${result.failedFiles} failed` : "";
|
|
97
|
+
spinner.succeed(`Indexing complete(${result.processed} / ${result.total}) • indexed ${result.indexed}${failedSuffix} `);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
spinner.fail("Indexing failed");
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
106
|
+
console.error("Failed to index:", message);
|
|
107
|
+
process.exitCode = 1;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
if (vectorDb) {
|
|
111
|
+
try {
|
|
112
|
+
yield vectorDb.close();
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
console.error("Failed to close VectorDB:", err);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const code = typeof process.exitCode === "number"
|
|
119
|
+
? process.exitCode
|
|
120
|
+
: process.exitCode === undefined
|
|
121
|
+
? 0
|
|
122
|
+
: 1;
|
|
123
|
+
yield (0, exit_1.gracefulExit)(code);
|
|
124
|
+
}
|
|
125
|
+
}));
|
|
@@ -0,0 +1,120 @@
|
|
|
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.list = void 0;
|
|
46
|
+
const fs = __importStar(require("node:fs"));
|
|
47
|
+
const path = __importStar(require("node:path"));
|
|
48
|
+
const commander_1 = require("commander");
|
|
49
|
+
const exit_1 = require("../lib/utils/exit");
|
|
50
|
+
const project_root_1 = require("../lib/utils/project-root");
|
|
51
|
+
const style = {
|
|
52
|
+
bold: (s) => `\x1b[1m${s}\x1b[22m`,
|
|
53
|
+
dim: (s) => `\x1b[2m${s}\x1b[22m`,
|
|
54
|
+
green: (s) => `\x1b[32m${s}\x1b[39m`,
|
|
55
|
+
};
|
|
56
|
+
function formatSize(bytes) {
|
|
57
|
+
if (bytes < 1024)
|
|
58
|
+
return `${bytes} B`;
|
|
59
|
+
if (bytes < 1024 * 1024)
|
|
60
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
61
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
62
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
63
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
64
|
+
}
|
|
65
|
+
function formatDate(date) {
|
|
66
|
+
const now = new Date();
|
|
67
|
+
const diff = now.getTime() - date.getTime();
|
|
68
|
+
const seconds = Math.floor(diff / 1000);
|
|
69
|
+
const minutes = Math.floor(seconds / 60);
|
|
70
|
+
const hours = Math.floor(minutes / 60);
|
|
71
|
+
const days = Math.floor(hours / 24);
|
|
72
|
+
if (days > 0)
|
|
73
|
+
return `${days}d ago`;
|
|
74
|
+
if (hours > 0)
|
|
75
|
+
return `${hours}h ago`;
|
|
76
|
+
if (minutes > 0)
|
|
77
|
+
return `${minutes}m ago`;
|
|
78
|
+
return "just now";
|
|
79
|
+
}
|
|
80
|
+
function getDirectorySize(dirPath) {
|
|
81
|
+
let totalSize = 0;
|
|
82
|
+
try {
|
|
83
|
+
const items = fs.readdirSync(dirPath);
|
|
84
|
+
for (const item of items) {
|
|
85
|
+
const itemPath = path.join(dirPath, item);
|
|
86
|
+
const stats = fs.statSync(itemPath);
|
|
87
|
+
if (stats.isDirectory()) {
|
|
88
|
+
totalSize += getDirectorySize(itemPath);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
totalSize += stats.size;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (_a) { }
|
|
96
|
+
return totalSize;
|
|
97
|
+
}
|
|
98
|
+
exports.list = new commander_1.Command("list")
|
|
99
|
+
.description("Show the current project's .osgrep contents")
|
|
100
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
|
+
var _a;
|
|
102
|
+
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _a !== void 0 ? _a : process.cwd();
|
|
103
|
+
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
104
|
+
const entries = [
|
|
105
|
+
{ label: "LanceDB", dir: paths.lancedbDir },
|
|
106
|
+
{ label: "Cache", dir: paths.cacheDir },
|
|
107
|
+
];
|
|
108
|
+
console.log(`\n${style.bold("Project")}: ${style.green(projectRoot)}`);
|
|
109
|
+
console.log(`${style.dim("Data directory")}: ${paths.osgrepDir}\n`);
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (!fs.existsSync(entry.dir)) {
|
|
112
|
+
console.log(`${entry.label}: ${style.dim("not created yet")}`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const stats = fs.statSync(entry.dir);
|
|
116
|
+
const size = getDirectorySize(entry.dir);
|
|
117
|
+
console.log(`${entry.label}: ${style.green(formatSize(size))} ${style.dim(`(updated ${formatDate(stats.mtime)})`)}`);
|
|
118
|
+
}
|
|
119
|
+
yield (0, exit_1.gracefulExit)();
|
|
120
|
+
}));
|