grepmax 0.17.17 → 0.17.19
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/dist/commands/dead.js +2 -1
- package/dist/commands/extract.js +6 -7
- package/dist/commands/help-agent.js +13 -0
- package/dist/commands/impact.js +2 -1
- package/dist/commands/peek.js +6 -7
- package/dist/commands/related.js +2 -2
- package/dist/commands/similar.js +4 -3
- package/dist/commands/trace.js +2 -1
- package/dist/index.js +2 -0
- package/dist/lib/daemon/daemon.js +3 -2
- package/dist/lib/help/agent-cheatsheet.js +42 -0
- package/dist/lib/search/searcher.js +23 -10
- package/dist/lib/utils/agent-errors.js +60 -0
- package/dist/lib/workers/orchestrator.js +9 -1
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/start.js +60 -24
package/dist/commands/dead.js
CHANGED
|
@@ -46,6 +46,7 @@ exports.dead = void 0;
|
|
|
46
46
|
const commander_1 = require("commander");
|
|
47
47
|
const graph_builder_1 = require("../lib/graph/graph-builder");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
49
50
|
const exit_1 = require("../lib/utils/exit");
|
|
50
51
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
51
52
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -134,7 +135,7 @@ exports.dead = new commander_1.Command("dead")
|
|
|
134
135
|
.limit(1)
|
|
135
136
|
.toArray();
|
|
136
137
|
if (defRows.length === 0) {
|
|
137
|
-
console.log(
|
|
138
|
+
console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, { agent: opts.agent }).join("\n"));
|
|
138
139
|
process.exitCode = 1;
|
|
139
140
|
return;
|
|
140
141
|
}
|
package/dist/commands/extract.js
CHANGED
|
@@ -46,6 +46,7 @@ exports.extract = void 0;
|
|
|
46
46
|
const fs = __importStar(require("node:fs"));
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
49
50
|
const exit_1 = require("../lib/utils/exit");
|
|
50
51
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
51
52
|
const import_extractor_1 = require("../lib/utils/import-extractor");
|
|
@@ -130,13 +131,11 @@ exports.extract = new commander_1.Command("extract")
|
|
|
130
131
|
const where = buildScopeWhere(scope, `array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`);
|
|
131
132
|
const chunks = yield findSymbolChunks(vectorDb, where);
|
|
132
133
|
if (chunks.length === 0) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
console.log(lines.join("\n"));
|
|
134
|
+
console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, {
|
|
135
|
+
agent: opts.agent,
|
|
136
|
+
dim: style.dim,
|
|
137
|
+
bold: style.bold,
|
|
138
|
+
}).join("\n"));
|
|
140
139
|
process.exitCode = 1;
|
|
141
140
|
return;
|
|
142
141
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.helpAgent = void 0;
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const agent_cheatsheet_1 = require("../lib/help/agent-cheatsheet");
|
|
6
|
+
exports.helpAgent = new commander_1.Command("help-agent")
|
|
7
|
+
.description("Print the agent command cheatsheet (re-summon the SessionStart hint on demand)")
|
|
8
|
+
.addHelpText("after", `
|
|
9
|
+
The same survey injected at SessionStart. Useful when a long session has
|
|
10
|
+
compacted away the original hint and you need to re-discover the commands.`)
|
|
11
|
+
.action(() => {
|
|
12
|
+
process.stdout.write(`${agent_cheatsheet_1.AGENT_CHEATSHEET}\n`);
|
|
13
|
+
});
|
package/dist/commands/impact.js
CHANGED
|
@@ -47,6 +47,7 @@ const path = __importStar(require("node:path"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const impact_1 = require("../lib/graph/impact");
|
|
49
49
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
50
51
|
const exit_1 = require("../lib/utils/exit");
|
|
51
52
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
52
53
|
const project_root_1 = require("../lib/utils/project-root");
|
|
@@ -73,7 +74,7 @@ exports.impact = new commander_1.Command("impact")
|
|
|
73
74
|
if (symbols.length === 0) {
|
|
74
75
|
console.log(resolvedAsFile
|
|
75
76
|
? `No symbols found in file: ${target}`
|
|
76
|
-
:
|
|
77
|
+
: (0, agent_errors_1.symbolNotFoundLines)(target, { agent: opts.agent }).join("\n"));
|
|
77
78
|
process.exitCode = 1;
|
|
78
79
|
return;
|
|
79
80
|
}
|
package/dist/commands/peek.js
CHANGED
|
@@ -47,6 +47,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const graph_builder_1 = require("../lib/graph/graph-builder");
|
|
49
49
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
50
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
50
51
|
const exit_1 = require("../lib/utils/exit");
|
|
51
52
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
53
|
const language_1 = require("../lib/utils/language");
|
|
@@ -152,13 +153,11 @@ exports.peek = new commander_1.Command("peek")
|
|
|
152
153
|
const graphBuilder = new graph_builder_1.GraphBuilder(vectorDb, scope.pathPrefix, scope.excludePrefixes);
|
|
153
154
|
const graph = yield graphBuilder.buildGraph(symbol);
|
|
154
155
|
if (!graph.center) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
console.log(lines.join("\n"));
|
|
156
|
+
console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, {
|
|
157
|
+
agent: opts.agent,
|
|
158
|
+
dim: style.dim,
|
|
159
|
+
bold: style.bold,
|
|
160
|
+
}).join("\n"));
|
|
162
161
|
process.exitCode = 1;
|
|
163
162
|
return;
|
|
164
163
|
}
|
package/dist/commands/related.js
CHANGED
|
@@ -46,6 +46,7 @@ exports.related = void 0;
|
|
|
46
46
|
const path = __importStar(require("node:path"));
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
49
50
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
50
51
|
const exit_1 = require("../lib/utils/exit");
|
|
51
52
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -85,8 +86,7 @@ exports.related = new commander_1.Command("related")
|
|
|
85
86
|
.where(`path = '${(0, filter_builder_1.escapeSqlString)(absPath)}'`)
|
|
86
87
|
.toArray();
|
|
87
88
|
if (fileChunks.length === 0) {
|
|
88
|
-
console.log(
|
|
89
|
-
console.log("\nCheck that the path is relative to the project root. Run `gmax status` to see indexed projects.");
|
|
89
|
+
console.log((0, agent_errors_1.fileNotFoundLines)(file, { agent: opts.agent }).join("\n"));
|
|
90
90
|
process.exitCode = 1;
|
|
91
91
|
return;
|
|
92
92
|
}
|
package/dist/commands/similar.js
CHANGED
|
@@ -46,6 +46,7 @@ exports.similar = void 0;
|
|
|
46
46
|
const path = __importStar(require("node:path"));
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
49
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
49
50
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
50
51
|
const exit_1 = require("../lib/utils/exit");
|
|
51
52
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -96,9 +97,9 @@ exports.similar = new commander_1.Command("similar")
|
|
|
96
97
|
.toArray();
|
|
97
98
|
}
|
|
98
99
|
if (sourceRows.length === 0) {
|
|
99
|
-
console.log(isFile
|
|
100
|
-
?
|
|
101
|
-
:
|
|
100
|
+
console.log((isFile
|
|
101
|
+
? (0, agent_errors_1.fileNotFoundLines)(target, { agent: opts.agent })
|
|
102
|
+
: (0, agent_errors_1.symbolNotFoundLines)(target, { agent: opts.agent })).join("\n"));
|
|
102
103
|
process.exitCode = 1;
|
|
103
104
|
return;
|
|
104
105
|
}
|
package/dist/commands/trace.js
CHANGED
|
@@ -48,6 +48,7 @@ const commander_1 = require("commander");
|
|
|
48
48
|
const graph_builder_1 = require("../lib/graph/graph-builder");
|
|
49
49
|
const formatter_1 = require("../lib/output/formatter");
|
|
50
50
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
51
|
+
const agent_errors_1 = require("../lib/utils/agent-errors");
|
|
51
52
|
const exit_1 = require("../lib/utils/exit");
|
|
52
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
53
54
|
const project_root_1 = require("../lib/utils/project-root");
|
|
@@ -221,7 +222,7 @@ exports.trace = new commander_1.Command("trace")
|
|
|
221
222
|
const graph = yield graphBuilder.buildGraphMultiHop(symbol, depth);
|
|
222
223
|
if (opts.inbound) {
|
|
223
224
|
if (!graph.center) {
|
|
224
|
-
console.log(
|
|
225
|
+
console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, { agent: opts.agent }).join("\n"));
|
|
225
226
|
process.exitCode = 1;
|
|
226
227
|
}
|
|
227
228
|
else {
|
package/dist/index.js
CHANGED
|
@@ -48,6 +48,7 @@ const codex_1 = require("./commands/codex");
|
|
|
48
48
|
const config_1 = require("./commands/config");
|
|
49
49
|
const doctor_1 = require("./commands/doctor");
|
|
50
50
|
const extract_1 = require("./commands/extract");
|
|
51
|
+
const help_agent_1 = require("./commands/help-agent");
|
|
51
52
|
const impact_1 = require("./commands/impact");
|
|
52
53
|
const droid_1 = require("./commands/droid");
|
|
53
54
|
const index_1 = require("./commands/index");
|
|
@@ -110,6 +111,7 @@ commander_1.program.addCommand(add_1.add);
|
|
|
110
111
|
commander_1.program.addCommand(remove_1.remove);
|
|
111
112
|
commander_1.program.addCommand(index_1.index);
|
|
112
113
|
commander_1.program.addCommand(status_1.status);
|
|
114
|
+
commander_1.program.addCommand(help_agent_1.helpAgent);
|
|
113
115
|
commander_1.program.addCommand(list_1.list);
|
|
114
116
|
commander_1.program.addCommand(skeleton_1.skeleton);
|
|
115
117
|
commander_1.program.addCommand(symbols_1.symbols);
|
|
@@ -355,8 +355,9 @@ class Daemon {
|
|
|
355
355
|
// index — this is the dominant cost)
|
|
356
356
|
// - FTS index "already exists" round-trip
|
|
357
357
|
// - Two parallel encodeQuery calls so the worker pool spawns + warms
|
|
358
|
-
//
|
|
359
|
-
//
|
|
358
|
+
// workers ahead of the first real search. The reaper floor is
|
|
359
|
+
// MIN_KEEP_WORKERS = 1 (pool.ts), so only one worker stays resident
|
|
360
|
+
// long-term — but the prewarm still pays the model-load cost up front.
|
|
360
361
|
// Fire-and-forget; failures are non-fatal — the next real search just
|
|
361
362
|
// pays the cost once. Delay a few seconds so we don't compete with the
|
|
362
363
|
// catchup scans dispatched on startup.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical agent cheatsheet — the single source of truth for the gmax command
|
|
4
|
+
* survey shown to agent sessions. Consumed by two places:
|
|
5
|
+
* - `gmax help-agent` (re-summon the survey on demand, e.g. after a session
|
|
6
|
+
* has compacted away the original SessionStart injection)
|
|
7
|
+
* - the SessionStart hook (`plugins/grepmax/hooks/start.js`), which loads this
|
|
8
|
+
* compiled module from the installed package and falls back to an inline
|
|
9
|
+
* copy only if the require fails — so the two can never silently drift.
|
|
10
|
+
*
|
|
11
|
+
* Keep this file as plain string data with NO imports so the hook can cheaply
|
|
12
|
+
* `require()` the compiled CommonJS output.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SESSION_START_HINT = exports.AGENT_CHEATSHEET = exports.SESSION_START_PREFIX = void 0;
|
|
16
|
+
/** Intro line shown only at SessionStart (not part of the on-demand command). */
|
|
17
|
+
exports.SESSION_START_PREFIX = "gmax ready. Add --agent to any command for compact output (~89% fewer tokens).";
|
|
18
|
+
/** The command survey — Find / Understand / Survey + scope/roles/recovery. */
|
|
19
|
+
exports.AGENT_CHEATSHEET = `Find:
|
|
20
|
+
gmax "topic" semantic search
|
|
21
|
+
gmax similar <symbol> similar code
|
|
22
|
+
|
|
23
|
+
Understand:
|
|
24
|
+
gmax peek <symbol> signature + callers + callees + tests
|
|
25
|
+
gmax extract <symbol> full body + tests
|
|
26
|
+
gmax trace <symbol> call graph (--inbound = callers + snippets)
|
|
27
|
+
gmax test <symbol> tests for symbol
|
|
28
|
+
gmax impact <symbol> blast radius
|
|
29
|
+
gmax related <file> file deps + dependents
|
|
30
|
+
|
|
31
|
+
Survey:
|
|
32
|
+
gmax project codebase overview (langs, structure, key symbols)
|
|
33
|
+
gmax skeleton <file> file structure (file path, NOT a directory)
|
|
34
|
+
gmax context "topic-or-path" --budget 4000 topic summary or deterministic file/dir context
|
|
35
|
+
gmax log <path-or-symbol> git commits (replaces recent/diff)
|
|
36
|
+
gmax status indexed projects
|
|
37
|
+
|
|
38
|
+
Scope flags: --root <name|path>, --in <subpath>, --exclude <subpath>.
|
|
39
|
+
Roles in results: [DEFI] [ORCH] [IMPL] [DOCS].
|
|
40
|
+
Recovery: "not added yet" → gmax add; stale → gmax index; broken → gmax doctor --fix.`;
|
|
41
|
+
/** Full SessionStart context = prefix + cheatsheet. */
|
|
42
|
+
exports.SESSION_START_HINT = `${exports.SESSION_START_PREFIX}\n\n${exports.AGENT_CHEATSHEET}`;
|
|
@@ -304,9 +304,6 @@ class Searcher {
|
|
|
304
304
|
adjusted *= boostFactor;
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
|
-
if (record.role === "DOCS") {
|
|
308
|
-
adjusted *= 0.6;
|
|
309
|
-
}
|
|
310
307
|
const pathStr = (record.path || "").toLowerCase();
|
|
311
308
|
// Use path-segment and filename patterns to avoid false positives like "latest"
|
|
312
309
|
const isTestPath = /(^|\/)(__tests__|tests?|specs?|benchmark)(\/|$)/i.test(pathStr) ||
|
|
@@ -315,14 +312,21 @@ class Searcher {
|
|
|
315
312
|
const testPenalty = Number.parseFloat((_c = process.env.GMAX_TEST_PENALTY) !== null && _c !== void 0 ? _c : "") || 0.5;
|
|
316
313
|
adjusted *= testPenalty;
|
|
317
314
|
}
|
|
318
|
-
|
|
315
|
+
// Downweight docs/data — applied ONCE whether the chunk is classified DOCS
|
|
316
|
+
// by role OR lives in a doc/data file. GMAX_DOC_PENALTY tunes both. (S2: the
|
|
317
|
+
// role branch was previously a hardcoded 0.6 that stacked with the path
|
|
318
|
+
// branch, double-penalizing a DOCS-role chunk in a .md / /docs/ path to
|
|
319
|
+
// 0.36 — and the role half was not env-tunable.)
|
|
320
|
+
const isDocOrData = record.role === "DOCS" ||
|
|
321
|
+
pathStr.endsWith(".md") ||
|
|
319
322
|
pathStr.endsWith(".mdx") ||
|
|
320
323
|
pathStr.endsWith(".txt") ||
|
|
321
324
|
pathStr.endsWith(".json") ||
|
|
322
325
|
pathStr.endsWith(".lock") ||
|
|
323
|
-
pathStr.includes("/docs/")
|
|
326
|
+
pathStr.includes("/docs/");
|
|
327
|
+
if (isDocOrData) {
|
|
324
328
|
const docPenalty = Number.parseFloat((_d = process.env.GMAX_DOC_PENALTY) !== null && _d !== void 0 ? _d : "") || 0.6;
|
|
325
|
-
adjusted *= docPenalty;
|
|
329
|
+
adjusted *= docPenalty;
|
|
326
330
|
}
|
|
327
331
|
// Import-only penalty
|
|
328
332
|
if ((record.content || "").length < 50 && !record.is_exported) {
|
|
@@ -621,16 +625,25 @@ class Searcher {
|
|
|
621
625
|
const FUSED_WEIGHT = Number.isFinite(envBlend) && envBlend >= 0 ? envBlend : 0.5;
|
|
622
626
|
if (queryPooled && topCandidates.length > STAGE2_K) {
|
|
623
627
|
const cosineScores = topCandidates.map((doc) => {
|
|
624
|
-
|
|
628
|
+
const docVec = doc.pooled_colbert_48d;
|
|
629
|
+
// Reject missing or short vectors. Also treat an all-zero vector as
|
|
630
|
+
// "no pooled signal" rather than a genuine cosine of 0 — chunks indexed
|
|
631
|
+
// before the pooled-IPC fix (orchestrator.ts) stored all-zero padding,
|
|
632
|
+
// and on a mixed index those must sort below chunks that carry real
|
|
633
|
+
// pooled vectors, not tie with orthogonal ones.
|
|
634
|
+
if (!docVec || docVec.length < queryPooled.length)
|
|
625
635
|
return -1;
|
|
626
636
|
// Manual cosine sim since we don't have helper here easily
|
|
627
637
|
// Assuming vectors are normalized (which they should be from orchestrator)
|
|
628
638
|
let dot = 0;
|
|
629
|
-
|
|
639
|
+
let nonZero = false;
|
|
630
640
|
for (let i = 0; i < queryPooled.length; i++) {
|
|
631
|
-
|
|
641
|
+
const c = docVec[i] || 0;
|
|
642
|
+
if (c !== 0)
|
|
643
|
+
nonZero = true;
|
|
644
|
+
dot += queryPooled[i] * c;
|
|
632
645
|
}
|
|
633
|
-
return dot;
|
|
646
|
+
return nonZero ? dot : -1;
|
|
634
647
|
});
|
|
635
648
|
// Sort by cosine score and keep top N
|
|
636
649
|
const withScore = topCandidates.map((doc, i) => ({
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared "not found" / empty-result rendering for the symbol and file lookup
|
|
4
|
+
* commands (peek/extract/trace/dead/impact/similar/related). Two jobs:
|
|
5
|
+
*
|
|
6
|
+
* 1. Unify the format — previously each command emitted its own variant
|
|
7
|
+
* ("Symbol not found: X", "(not found)", bare one-liners), and only
|
|
8
|
+
* peek/extract carried the rich human "Possible reasons / Try:" block.
|
|
9
|
+
* 2. Stop discarding recovery hints under `--agent` — human mode keeps the
|
|
10
|
+
* full block; agent mode now gets a compact trailing `next:` line instead
|
|
11
|
+
* of a bare, dead-end error.
|
|
12
|
+
*
|
|
13
|
+
* Returns lines (caller joins with "\n"). `dim`/`bold` default to identity so
|
|
14
|
+
* the helper stays color-agnostic; commands pass their own `style.*` to
|
|
15
|
+
* preserve existing human coloring.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.symbolNotFoundLines = symbolNotFoundLines;
|
|
19
|
+
exports.fileNotFoundLines = fileNotFoundLines;
|
|
20
|
+
const identity = (s) => s;
|
|
21
|
+
/** `Symbol not found: X` — symbol lookup miss. */
|
|
22
|
+
function symbolNotFoundLines(symbol, opts = {}) {
|
|
23
|
+
const { agent = false, dim = identity, bold = identity } = opts;
|
|
24
|
+
if (agent) {
|
|
25
|
+
return [
|
|
26
|
+
`Symbol not found: ${symbol}`,
|
|
27
|
+
`next: gmax status (indexed projects) · gmax search ${symbol} (fuzzy match)`,
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
return [
|
|
31
|
+
`Symbol not found: ${bold(symbol)}`,
|
|
32
|
+
"",
|
|
33
|
+
dim("Possible reasons:"),
|
|
34
|
+
dim(" • The symbol doesn't exist in any indexed project"),
|
|
35
|
+
dim(" • The containing file hasn't been indexed yet"),
|
|
36
|
+
dim(" • The name is spelled differently in the source"),
|
|
37
|
+
"",
|
|
38
|
+
dim("Try:"),
|
|
39
|
+
dim(" gmax status — see which projects are indexed"),
|
|
40
|
+
dim(" gmax search <name> — fuzzy search for similar symbols"),
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
/** `File not found in index: X` — file lookup miss. */
|
|
44
|
+
function fileNotFoundLines(file, opts = {}) {
|
|
45
|
+
const { agent = false, dim = identity, bold = identity } = opts;
|
|
46
|
+
if (agent) {
|
|
47
|
+
return [
|
|
48
|
+
`File not found in index: ${file}`,
|
|
49
|
+
`next: use a path relative to the project root · gmax status · gmax add <project> (if untracked)`,
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
return [
|
|
53
|
+
`File not found in index: ${bold(file)}`,
|
|
54
|
+
"",
|
|
55
|
+
dim("Try:"),
|
|
56
|
+
dim(" ensure the path is relative to the project root"),
|
|
57
|
+
dim(" gmax status — see which projects are indexed"),
|
|
58
|
+
dim(" gmax add <project> — index a project that isn't tracked yet"),
|
|
59
|
+
];
|
|
60
|
+
}
|
|
@@ -287,7 +287,15 @@ class WorkerOrchestrator {
|
|
|
287
287
|
colbert: new Int8Array(),
|
|
288
288
|
scale: 1,
|
|
289
289
|
};
|
|
290
|
-
return Object.assign(Object.assign({}, chunk), { vector: hybrid.dense, colbert: Buffer.from(hybrid.colbert), colbert_scale: hybrid.scale,
|
|
290
|
+
return Object.assign(Object.assign({}, chunk), { vector: hybrid.dense, colbert: Buffer.from(hybrid.colbert), colbert_scale: hybrid.scale,
|
|
291
|
+
// Convert the pooled Float32Array to a plain number[] so it survives
|
|
292
|
+
// the JSON IPC hop to the parent (process-child.ts → pool.ts). A typed
|
|
293
|
+
// array JSON-serializes to a length-less {"0":..} object, which then
|
|
294
|
+
// Array.from()s to [] on insert and pads to 48 zeros — silently making
|
|
295
|
+
// the stage-1 cosine prefilter a no-op (searcher.ts:732).
|
|
296
|
+
pooled_colbert_48d: hybrid.pooled_colbert_48d
|
|
297
|
+
? Array.from(hybrid.pooled_colbert_48d)
|
|
298
|
+
: undefined, doc_token_ids: hybrid.token_ids });
|
|
291
299
|
});
|
|
292
300
|
onProgress === null || onProgress === void 0 ? void 0 : onProgress();
|
|
293
301
|
(0, logger_1.debug)("orch", `processFile done: ${input.path} ${vectors.length} vectors ${(performance.now() - fileStart).toFixed(0)}ms`);
|
package/package.json
CHANGED
|
@@ -42,6 +42,65 @@ function findMlxServerDir() {
|
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
// Inline fallback so SessionStart context is never empty if the installed
|
|
46
|
+
// gmax package can't be resolved (e.g. gmax not yet on PATH). The canonical
|
|
47
|
+
// copy lives in src/lib/help/agent-cheatsheet.ts; getSessionStartHint() prefers
|
|
48
|
+
// it and only uses this if the require fails. Keep the two in sync.
|
|
49
|
+
const FALLBACK_SESSION_START_HINT = `gmax ready. Add --agent to any command for compact output (~89% fewer tokens).
|
|
50
|
+
|
|
51
|
+
Find:
|
|
52
|
+
gmax "topic" semantic search
|
|
53
|
+
gmax similar <symbol> similar code
|
|
54
|
+
|
|
55
|
+
Understand:
|
|
56
|
+
gmax peek <symbol> signature + callers + callees + tests
|
|
57
|
+
gmax extract <symbol> full body + tests
|
|
58
|
+
gmax trace <symbol> call graph (--inbound = callers + snippets)
|
|
59
|
+
gmax test <symbol> tests for symbol
|
|
60
|
+
gmax impact <symbol> blast radius
|
|
61
|
+
gmax related <file> file deps + dependents
|
|
62
|
+
|
|
63
|
+
Survey:
|
|
64
|
+
gmax project codebase overview (langs, structure, key symbols)
|
|
65
|
+
gmax skeleton <file> file structure (file path, NOT a directory)
|
|
66
|
+
gmax context "topic-or-path" --budget 4000 topic summary or deterministic file/dir context
|
|
67
|
+
gmax log <path-or-symbol> git commits (replaces recent/diff)
|
|
68
|
+
gmax status indexed projects
|
|
69
|
+
|
|
70
|
+
Scope flags: --root <name|path>, --in <subpath>, --exclude <subpath>.
|
|
71
|
+
Roles in results: [DEFI] [ORCH] [IMPL] [DOCS].
|
|
72
|
+
Recovery: "not added yet" → gmax add; stale → gmax index; broken → gmax doctor --fix.`;
|
|
73
|
+
|
|
74
|
+
// Load the canonical cheatsheet from the installed gmax package (single source
|
|
75
|
+
// of truth shared with `gmax help-agent`). Tries the npm-resolved package root
|
|
76
|
+
// first, then the dev checkout, then the inline fallback above.
|
|
77
|
+
function getSessionStartHint() {
|
|
78
|
+
const roots = [];
|
|
79
|
+
try {
|
|
80
|
+
const gmaxPath = execFileSync("which", ["gmax"], {
|
|
81
|
+
encoding: "utf-8",
|
|
82
|
+
}).trim();
|
|
83
|
+
if (gmaxPath) {
|
|
84
|
+
const realPath = fs.realpathSync(gmaxPath);
|
|
85
|
+
roots.push(_path.resolve(_path.dirname(realPath), ".."));
|
|
86
|
+
}
|
|
87
|
+
} catch {}
|
|
88
|
+
// dev mode — plugin lives at <repo>/plugins/grepmax/hooks
|
|
89
|
+
roots.push(_path.resolve(__dirname, "../../.."));
|
|
90
|
+
|
|
91
|
+
for (const root of roots) {
|
|
92
|
+
try {
|
|
93
|
+
const mod = require(
|
|
94
|
+
_path.join(root, "dist", "lib", "help", "agent-cheatsheet.js"),
|
|
95
|
+
);
|
|
96
|
+
if (mod && typeof mod.SESSION_START_HINT === "string") {
|
|
97
|
+
return mod.SESSION_START_HINT;
|
|
98
|
+
}
|
|
99
|
+
} catch {}
|
|
100
|
+
}
|
|
101
|
+
return FALLBACK_SESSION_START_HINT;
|
|
102
|
+
}
|
|
103
|
+
|
|
45
104
|
function startPythonServer(serverDir, scriptName, logName, processName) {
|
|
46
105
|
if (!serverDir) return;
|
|
47
106
|
|
|
@@ -175,30 +234,7 @@ async function main() {
|
|
|
175
234
|
const response = {
|
|
176
235
|
hookSpecificOutput: {
|
|
177
236
|
hookEventName: "SessionStart",
|
|
178
|
-
additionalContext:
|
|
179
|
-
|
|
180
|
-
Find:
|
|
181
|
-
gmax "topic" semantic search
|
|
182
|
-
gmax similar <symbol> similar code
|
|
183
|
-
|
|
184
|
-
Understand:
|
|
185
|
-
gmax peek <symbol> signature + callers + callees + tests
|
|
186
|
-
gmax extract <symbol> full body + tests
|
|
187
|
-
gmax trace <symbol> call graph (--inbound = callers + snippets)
|
|
188
|
-
gmax test <symbol> tests for symbol
|
|
189
|
-
gmax impact <symbol> blast radius
|
|
190
|
-
gmax related <file> file deps + dependents
|
|
191
|
-
|
|
192
|
-
Survey:
|
|
193
|
-
gmax project codebase overview (langs, structure, key symbols)
|
|
194
|
-
gmax skeleton <file> file structure (file path, NOT a directory)
|
|
195
|
-
gmax context "topic-or-path" --budget 4000 topic summary or deterministic file/dir context
|
|
196
|
-
gmax log <path-or-symbol> git commits (replaces recent/diff)
|
|
197
|
-
gmax status indexed projects
|
|
198
|
-
|
|
199
|
-
Scope flags: --root <name|path>, --in <subpath>, --exclude <subpath>.
|
|
200
|
-
Roles in results: [DEFI] [ORCH] [IMPL] [DOCS].
|
|
201
|
-
Recovery: "not added yet" → gmax add; stale → gmax index; broken → gmax doctor --fix.`,
|
|
237
|
+
additionalContext: getSessionStartHint(),
|
|
202
238
|
},
|
|
203
239
|
};
|
|
204
240
|
process.stdout.write(JSON.stringify(response));
|