grepmax 0.26.18 → 0.26.20
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/.claude-plugin/marketplace.json +1 -1
- package/dist/commands/add.js +7 -0
- package/dist/commands/index.js +4 -0
- package/dist/commands/llm.js +5 -1
- package/dist/commands/repair.js +7 -2
- package/dist/config.js +4 -0
- package/dist/lib/store/store-lease.js +25 -6
- package/dist/lib/utils/autostart.js +88 -0
- package/dist/lib/utils/daemon-client.js +7 -0
- package/dist/lib/utils/watcher-launcher.js +8 -1
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/start.js +3 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"name": "grepmax",
|
|
11
11
|
"source": "./plugins/grepmax",
|
|
12
12
|
"description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
|
|
13
|
-
"version": "0.26.
|
|
13
|
+
"version": "0.26.20",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "Robert Owens",
|
|
16
16
|
"email": "robowens@me.com"
|
package/dist/commands/add.js
CHANGED
|
@@ -54,6 +54,7 @@ const sync_helpers_1 = require("../lib/index/sync-helpers");
|
|
|
54
54
|
const syncer_1 = require("../lib/index/syncer");
|
|
55
55
|
const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
56
56
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
57
|
+
const autostart_1 = require("../lib/utils/autostart");
|
|
57
58
|
const blocked_roots_1 = require("../lib/utils/blocked-roots");
|
|
58
59
|
const exit_1 = require("../lib/utils/exit");
|
|
59
60
|
const project_marker_1 = require("../lib/utils/project-marker");
|
|
@@ -226,6 +227,12 @@ Examples:
|
|
|
226
227
|
}
|
|
227
228
|
else {
|
|
228
229
|
// Fallback: direct mode with lock
|
|
230
|
+
const notice = (0, autostart_1.autostartDisabledNotice)();
|
|
231
|
+
if (notice) {
|
|
232
|
+
spinner.stop();
|
|
233
|
+
console.log(notice);
|
|
234
|
+
spinner.start();
|
|
235
|
+
}
|
|
229
236
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
230
237
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
231
238
|
try {
|
package/dist/commands/index.js
CHANGED
|
@@ -51,6 +51,7 @@ const sync_helpers_1 = require("../lib/index/sync-helpers");
|
|
|
51
51
|
const syncer_1 = require("../lib/index/syncer");
|
|
52
52
|
const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
53
53
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
54
|
+
const autostart_1 = require("../lib/utils/autostart");
|
|
54
55
|
const exit_1 = require("../lib/utils/exit");
|
|
55
56
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
56
57
|
const project_root_1 = require("../lib/utils/project-root");
|
|
@@ -149,6 +150,9 @@ Examples:
|
|
|
149
150
|
}
|
|
150
151
|
else {
|
|
151
152
|
// Fallback: direct mode with lock — stop any watcher first
|
|
153
|
+
const notice = (0, autostart_1.autostartDisabledNotice)();
|
|
154
|
+
if (notice)
|
|
155
|
+
console.log(notice);
|
|
152
156
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
153
157
|
vectorDb = new vector_db_1.VectorDB(paths.lancedbDir);
|
|
154
158
|
let restartWatcher = false;
|
package/dist/commands/llm.js
CHANGED
|
@@ -93,7 +93,11 @@ exports.llm
|
|
|
93
93
|
try {
|
|
94
94
|
const { ensureDaemonRunning, sendDaemonCommand } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/daemon-client")));
|
|
95
95
|
if (!(yield ensureDaemonRunning())) {
|
|
96
|
-
|
|
96
|
+
const { autostartDisabledUndo } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/autostart")));
|
|
97
|
+
const undo = autostartDisabledUndo();
|
|
98
|
+
console.error(undo
|
|
99
|
+
? `Daemon autostart is disabled and the LLM server needs the daemon. Re-enable with: ${undo}`
|
|
100
|
+
: "Failed to start daemon");
|
|
97
101
|
process.exitCode = 1;
|
|
98
102
|
return;
|
|
99
103
|
}
|
package/dist/commands/repair.js
CHANGED
|
@@ -14,6 +14,7 @@ const commander_1 = require("commander");
|
|
|
14
14
|
const config_1 = require("../config");
|
|
15
15
|
const index_config_1 = require("../lib/index/index-config");
|
|
16
16
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
17
|
+
const autostart_1 = require("../lib/utils/autostart");
|
|
17
18
|
const daemon_client_1 = require("../lib/utils/daemon-client");
|
|
18
19
|
const exit_1 = require("../lib/utils/exit");
|
|
19
20
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -38,8 +39,12 @@ Examples:
|
|
|
38
39
|
try {
|
|
39
40
|
if (opts.rebuild) {
|
|
40
41
|
const running = yield (0, daemon_client_1.ensureDaemonRunning)();
|
|
41
|
-
if (!running)
|
|
42
|
-
|
|
42
|
+
if (!running) {
|
|
43
|
+
const undo = (0, autostart_1.autostartDisabledUndo)();
|
|
44
|
+
throw new Error(undo
|
|
45
|
+
? `daemon autostart is disabled and --rebuild needs the daemon; re-enable with: ${undo}`
|
|
46
|
+
: "failed to start the gmax daemon");
|
|
47
|
+
}
|
|
43
48
|
const ping = yield (0, daemon_client_1.sendDaemonCommand)({ cmd: "ping" }, { timeoutMs: 10000 });
|
|
44
49
|
const capabilities = ping.capabilities && typeof ping.capabilities === "object"
|
|
45
50
|
? ping.capabilities
|
package/dist/config.js
CHANGED
|
@@ -229,6 +229,10 @@ exports.PATHS = {
|
|
|
229
229
|
// never SIGKILLs a peer mid-cleanup once the peer has already dropped its
|
|
230
230
|
// socket/PID/lock liveness markers.
|
|
231
231
|
daemonDrainingFile: path.join(GLOBAL_ROOT, "daemon.draining"),
|
|
232
|
+
// Kill switch for implicit daemon auto-start (see lib/utils/autostart.ts).
|
|
233
|
+
// Its presence stops hooks and CLI commands from reviving a quarantined
|
|
234
|
+
// daemon; explicit `gmax watch --daemon` still works.
|
|
235
|
+
autostartDisabledFile: path.join(GLOBAL_ROOT, "autostart-disabled"),
|
|
232
236
|
// Centralized index storage — one database for all indexed directories
|
|
233
237
|
lancedbDir: path.join(GLOBAL_ROOT, "lancedb"),
|
|
234
238
|
cacheDir: path.join(GLOBAL_ROOT, "cache"),
|
|
@@ -47,6 +47,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
48
|
exports.StoreLease = exports.StoreLeaseTimeoutError = void 0;
|
|
49
49
|
exports.storeLeasePaths = storeLeasePaths;
|
|
50
|
+
exports.defaultProbeOwner = defaultProbeOwner;
|
|
50
51
|
exports.hasStoreExclusiveIntent = hasStoreExclusiveIntent;
|
|
51
52
|
const node_child_process_1 = require("node:child_process");
|
|
52
53
|
const node_crypto_1 = require("node:crypto");
|
|
@@ -97,19 +98,37 @@ function currentProcessStart(pid) {
|
|
|
97
98
|
return fallback;
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
+
const defaultProbeDeps = {
|
|
102
|
+
signal: (pid) => {
|
|
103
|
+
process.kill(pid, 0);
|
|
104
|
+
},
|
|
105
|
+
processStartOf: (pid) => (0, node_child_process_1.execFileSync)("ps", ["-p", String(pid), "-o", "lstart="], {
|
|
106
|
+
encoding: "utf8",
|
|
107
|
+
timeout: 1000,
|
|
108
|
+
}).trim(),
|
|
109
|
+
};
|
|
110
|
+
function defaultProbeOwner(owner, deps = defaultProbeDeps) {
|
|
101
111
|
try {
|
|
102
|
-
|
|
112
|
+
deps.signal(owner.pid);
|
|
103
113
|
}
|
|
104
114
|
catch (error) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
115
|
+
const code = error.code;
|
|
116
|
+
if (code === "ESRCH")
|
|
117
|
+
return "dead";
|
|
118
|
+
// EPERM means the PID exists but is not signalable by us -- the signature
|
|
119
|
+
// of a recycled PID that now belongs to another user. That is not evidence
|
|
120
|
+
// the lease owner is alive, so fall through to the processStart comparison
|
|
121
|
+
// below, which `ps` answers across user boundaries. Returning "unknown"
|
|
122
|
+
// here instead would make the reader marker immortal and hang every
|
|
123
|
+
// exclusive operation for the life of the store.
|
|
124
|
+
if (code !== "EPERM")
|
|
125
|
+
return "unknown";
|
|
108
126
|
}
|
|
109
127
|
if (owner.processStart.startsWith(`pid:${owner.pid}:started:`))
|
|
110
128
|
return "same";
|
|
111
129
|
try {
|
|
112
|
-
const start =
|
|
130
|
+
const start = deps.processStartOf(owner.pid);
|
|
131
|
+
// Reserve "unknown" for a start-time lookup that could not answer.
|
|
113
132
|
if (!start)
|
|
114
133
|
return "unknown";
|
|
115
134
|
return start === owner.processStart ? "same" : "reused";
|
|
@@ -0,0 +1,88 @@
|
|
|
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.autostartDisabledReason = autostartDisabledReason;
|
|
37
|
+
exports.isAutostartDisabled = isAutostartDisabled;
|
|
38
|
+
exports.autostartDisabledUndo = autostartDisabledUndo;
|
|
39
|
+
exports.autostartDisabledNotice = autostartDisabledNotice;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const config_1 = require("../../config");
|
|
42
|
+
/**
|
|
43
|
+
* Kill switch for *implicit* daemon auto-start. Create
|
|
44
|
+
* ~/.gmax/autostart-disabled (or export GMAX_NO_AUTOSTART=1) to keep session
|
|
45
|
+
* hooks and ordinary commands (`gmax add`, `gmax index`, search, MCP) from
|
|
46
|
+
* reviving the daemon — needed when the host is quarantined and the daemon's
|
|
47
|
+
* write volume is the thing under investigation.
|
|
48
|
+
*
|
|
49
|
+
* Explicit `gmax watch --daemon` is never gated: typing it is the user asking
|
|
50
|
+
* for a daemon in that moment.
|
|
51
|
+
*
|
|
52
|
+
* plugins/grepmax/hooks/start.js carries a plain-JS copy of these semantics
|
|
53
|
+
* (env var checked first, then the file) because a SessionStart hook cannot
|
|
54
|
+
* import from dist. Keep the two in sync.
|
|
55
|
+
*/
|
|
56
|
+
function autostartDisabledReason() {
|
|
57
|
+
if (process.env.GMAX_NO_AUTOSTART === "1")
|
|
58
|
+
return "env";
|
|
59
|
+
try {
|
|
60
|
+
return fs.existsSync(config_1.PATHS.autostartDisabledFile) ? "file" : null;
|
|
61
|
+
}
|
|
62
|
+
catch (_a) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function isAutostartDisabled() {
|
|
67
|
+
return autostartDisabledReason() !== null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* One-line notice for commands that fell back to in-process work because the
|
|
71
|
+
* kill switch is on, or null when it isn't. Names the specific undo step so
|
|
72
|
+
* the message is actionable whichever way autostart was disabled.
|
|
73
|
+
*/
|
|
74
|
+
/** The shell command that re-enables autostart, or null when it is not disabled. */
|
|
75
|
+
function autostartDisabledUndo() {
|
|
76
|
+
const reason = autostartDisabledReason();
|
|
77
|
+
if (!reason)
|
|
78
|
+
return null;
|
|
79
|
+
return reason === "env"
|
|
80
|
+
? "unset GMAX_NO_AUTOSTART"
|
|
81
|
+
: `rm ${config_1.PATHS.autostartDisabledFile}`;
|
|
82
|
+
}
|
|
83
|
+
function autostartDisabledNotice() {
|
|
84
|
+
const undo = autostartDisabledUndo();
|
|
85
|
+
if (!undo)
|
|
86
|
+
return null;
|
|
87
|
+
return `Daemon autostart is disabled — running in-process. Re-enable with: ${undo}`;
|
|
88
|
+
}
|
|
@@ -269,12 +269,19 @@ function isDaemonDraining(pid) {
|
|
|
269
269
|
/**
|
|
270
270
|
* Ensure the daemon is running — start it if needed, then wait for resources.
|
|
271
271
|
* Returns true if daemon is ready, false if it couldn't be started.
|
|
272
|
+
*
|
|
273
|
+
* This is the implicit spawn path, so it honors the autostart kill switch: with
|
|
274
|
+
* it on, an already-running daemon is still used, but a dead one is not
|
|
275
|
+
* revived and callers fall back to in-process work.
|
|
272
276
|
*/
|
|
273
277
|
function ensureDaemonRunning() {
|
|
274
278
|
return __awaiter(this, void 0, void 0, function* () {
|
|
275
279
|
if (yield isDaemonReady())
|
|
276
280
|
return true;
|
|
277
281
|
if (!(yield isDaemonRunning())) {
|
|
282
|
+
const { isAutostartDisabled } = yield Promise.resolve().then(() => __importStar(require("./autostart")));
|
|
283
|
+
if (isAutostartDisabled())
|
|
284
|
+
return false;
|
|
278
285
|
const { spawnDaemon } = yield Promise.resolve().then(() => __importStar(require("./daemon-launcher")));
|
|
279
286
|
const pid = yield spawnDaemon();
|
|
280
287
|
if (!pid)
|
|
@@ -16,6 +16,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.launchWatcher = launchWatcher;
|
|
18
18
|
const node_child_process_1 = require("node:child_process");
|
|
19
|
+
const autostart_1 = require("./autostart");
|
|
19
20
|
const daemon_client_1 = require("./daemon-client");
|
|
20
21
|
const daemon_launcher_1 = require("./daemon-launcher");
|
|
21
22
|
const project_registry_1 = require("./project-registry");
|
|
@@ -48,7 +49,13 @@ function launchWatcher(projectRoot) {
|
|
|
48
49
|
if (resp.ok && typeof resp.pid === "number") {
|
|
49
50
|
return { ok: true, pid: resp.pid, reused: true };
|
|
50
51
|
}
|
|
51
|
-
// 4. Daemon not running — try to start it, poll until ready
|
|
52
|
+
// 4. Daemon not running — try to start it, poll until ready.
|
|
53
|
+
// Both remaining steps spawn a background process, so stop here when the
|
|
54
|
+
// autostart kill switch is on: a quarantined daemon must stay down.
|
|
55
|
+
const notice = (0, autostart_1.autostartDisabledNotice)();
|
|
56
|
+
if (notice) {
|
|
57
|
+
return { ok: false, reason: "autostart-disabled", message: notice };
|
|
58
|
+
}
|
|
52
59
|
const error = resp.error;
|
|
53
60
|
if (error === "ENOENT" || error === "ECONNREFUSED") {
|
|
54
61
|
const daemonPid = yield (0, daemon_launcher_1.spawnDaemon)();
|
package/package.json
CHANGED
|
@@ -82,6 +82,9 @@ function isProjectRegistered() {
|
|
|
82
82
|
// GMAX_NO_AUTOSTART=1) to keep sessions from reviving the daemon — needed when the
|
|
83
83
|
// host is quarantined after a kernel-zone incident and the daemon's write volume is
|
|
84
84
|
// the thing under investigation. Delete the file to restore normal behavior.
|
|
85
|
+
//
|
|
86
|
+
// The CLI honors the same switch via src/lib/utils/autostart.ts (PATHS.autostartDisabledFile).
|
|
87
|
+
// This copy exists because a hook cannot import from dist — keep the two in sync.
|
|
85
88
|
function isAutostartDisabled() {
|
|
86
89
|
if (process.env.GMAX_NO_AUTOSTART === "1") return true;
|
|
87
90
|
try {
|