@levnikolaevich/hex-line-mcp 1.8.0 → 1.9.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/dist/server.mjs +65 -5
- package/package.json +1 -1
package/dist/server.mjs
CHANGED
|
@@ -281,7 +281,7 @@ function validateWritePath(filePath) {
|
|
|
281
281
|
import { existsSync as existsSync2 } from "node:fs";
|
|
282
282
|
import { join as join3, dirname as dirname2, relative } from "node:path";
|
|
283
283
|
import { createRequire } from "node:module";
|
|
284
|
-
var HEX_LINE_CONTRACT_VERSION =
|
|
284
|
+
var HEX_LINE_CONTRACT_VERSION = 2;
|
|
285
285
|
var _dbs = /* @__PURE__ */ new Map();
|
|
286
286
|
var _driverUnavailable = false;
|
|
287
287
|
function getGraphDB(filePath) {
|
|
@@ -311,7 +311,7 @@ function validateHexLineContract(db) {
|
|
|
311
311
|
const contract = db.prepare("SELECT contract_version FROM hex_line_contract LIMIT 1").get();
|
|
312
312
|
if (!contract || contract.contract_version !== HEX_LINE_CONTRACT_VERSION) return false;
|
|
313
313
|
db.prepare("SELECT node_id, file, line_start, line_end, display_name, kind, callees, callers FROM hex_line_symbol_annotations LIMIT 1").all();
|
|
314
|
-
db.prepare("SELECT source_id, target_id, source_file, source_line, source_display_name, target_file, target_line, target_display_name FROM hex_line_call_edges LIMIT 1").all();
|
|
314
|
+
db.prepare("SELECT source_id, target_id, source_file, source_line, source_display_name, target_file, target_line, target_display_name, confidence FROM hex_line_call_edges LIMIT 1").all();
|
|
315
315
|
return true;
|
|
316
316
|
} catch {
|
|
317
317
|
return false;
|
|
@@ -363,7 +363,8 @@ function callImpact(db, file, startLine, endLine) {
|
|
|
363
363
|
const dependents = db.prepare(
|
|
364
364
|
`SELECT source_display_name AS name, source_file AS file, source_line AS line
|
|
365
365
|
FROM hex_line_call_edges
|
|
366
|
-
WHERE target_id =
|
|
366
|
+
WHERE target_id = ?
|
|
367
|
+
AND confidence IN ('exact', 'precise')`
|
|
367
368
|
).all(node.node_id);
|
|
368
369
|
for (const dep of dependents) {
|
|
369
370
|
const key = `${dep.file}:${dep.name}`;
|
|
@@ -378,6 +379,38 @@ function callImpact(db, file, startLine, endLine) {
|
|
|
378
379
|
return [];
|
|
379
380
|
}
|
|
380
381
|
}
|
|
382
|
+
function cloneWarning(db, file, startLine, endLine) {
|
|
383
|
+
try {
|
|
384
|
+
const modified = db.prepare(
|
|
385
|
+
`SELECT node_id
|
|
386
|
+
FROM hex_line_symbol_annotations
|
|
387
|
+
WHERE file = ?
|
|
388
|
+
AND line_start <= ?
|
|
389
|
+
AND line_end >= ?`
|
|
390
|
+
).all(file, endLine, startLine);
|
|
391
|
+
if (modified.length === 0) return [];
|
|
392
|
+
const clones = [];
|
|
393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
394
|
+
for (const node of modified) {
|
|
395
|
+
const siblings = db.prepare(
|
|
396
|
+
`SELECT s2.file, s2.line_start, s2.display_name
|
|
397
|
+
FROM hex_line_clone_siblings s1
|
|
398
|
+
JOIN hex_line_clone_siblings s2 ON s2.norm_hash = s1.norm_hash AND s2.node_id != s1.node_id
|
|
399
|
+
WHERE s1.node_id = ?`
|
|
400
|
+
).all(node.node_id);
|
|
401
|
+
for (const sib of siblings) {
|
|
402
|
+
const key = `${sib.file}:${sib.display_name}`;
|
|
403
|
+
if (!seen.has(key)) {
|
|
404
|
+
seen.add(key);
|
|
405
|
+
clones.push({ name: sib.display_name, file: sib.file, line: sib.line_start });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return clones.slice(0, 10);
|
|
410
|
+
} catch {
|
|
411
|
+
return [];
|
|
412
|
+
}
|
|
413
|
+
}
|
|
381
414
|
function matchAnnotation(db, file, line) {
|
|
382
415
|
try {
|
|
383
416
|
const node = db.prepare(
|
|
@@ -1569,6 +1602,13 @@ ${serializeReadBlock(block)}`;
|
|
|
1569
1602
|
\u26A0 Call impact: ${affected.length} callers in other files
|
|
1570
1603
|
${list}`;
|
|
1571
1604
|
}
|
|
1605
|
+
const clones = cloneWarning(db, relFile, minLine, maxLine);
|
|
1606
|
+
if (clones.length > 0) {
|
|
1607
|
+
const list = clones.map((c) => `${c.file}:${c.line}`).join(", ");
|
|
1608
|
+
msg += `
|
|
1609
|
+
|
|
1610
|
+
\u26A0 ${clones.length} clone(s): ${list}`;
|
|
1611
|
+
}
|
|
1572
1612
|
}
|
|
1573
1613
|
} catch {
|
|
1574
1614
|
}
|
|
@@ -1594,6 +1634,7 @@ try {
|
|
|
1594
1634
|
var DEFAULT_LIMIT2 = 100;
|
|
1595
1635
|
var MAX_OUTPUT = 10 * 1024 * 1024;
|
|
1596
1636
|
var TIMEOUT2 = 3e4;
|
|
1637
|
+
var MAX_SEARCH_OUTPUT_CHARS = 8e4;
|
|
1597
1638
|
function spawnRg(args) {
|
|
1598
1639
|
return new Promise((resolve_, reject) => {
|
|
1599
1640
|
let stdout = "";
|
|
@@ -1790,7 +1831,26 @@ async function contentMode(pattern, target, opts, plain, totalLimit) {
|
|
|
1790
1831
|
}
|
|
1791
1832
|
flushGroup();
|
|
1792
1833
|
if (db) blocks.sort((a, b) => (b.meta.graphScore || 0) - (a.meta.graphScore || 0));
|
|
1793
|
-
|
|
1834
|
+
const parts = [];
|
|
1835
|
+
let budget = MAX_SEARCH_OUTPUT_CHARS;
|
|
1836
|
+
let capped = false;
|
|
1837
|
+
for (const block of blocks) {
|
|
1838
|
+
const serialized = block.type === "edit_ready_block" ? serializeSearchBlock(block, { plain }) : serializeDiagnosticBlock(block);
|
|
1839
|
+
if (parts.length > 0 && budget - serialized.length < 0) {
|
|
1840
|
+
capped = true;
|
|
1841
|
+
break;
|
|
1842
|
+
}
|
|
1843
|
+
parts.push(serialized);
|
|
1844
|
+
budget -= serialized.length;
|
|
1845
|
+
}
|
|
1846
|
+
if (capped) {
|
|
1847
|
+
const remaining = blocks.length - parts.length;
|
|
1848
|
+
parts.push(serializeDiagnosticBlock(buildDiagnosticBlock({
|
|
1849
|
+
kind: "output_capped",
|
|
1850
|
+
message: `OUTPUT_CAPPED: ${remaining} more search block(s) omitted (${MAX_SEARCH_OUTPUT_CHARS} char limit). Narrow with path= or glob= filters.`
|
|
1851
|
+
})));
|
|
1852
|
+
}
|
|
1853
|
+
return parts.join("\n\n");
|
|
1794
1854
|
}
|
|
1795
1855
|
|
|
1796
1856
|
// lib/outline.mjs
|
|
@@ -2786,7 +2846,7 @@ OUTPUT_CAPPED: Output exceeded ${MAX_BULK_OUTPUT_CHARS} chars.`;
|
|
|
2786
2846
|
}
|
|
2787
2847
|
|
|
2788
2848
|
// server.mjs
|
|
2789
|
-
var version = true ? "1.
|
|
2849
|
+
var version = true ? "1.9.0" : (await null).createRequire(import.meta.url)("./package.json").version;
|
|
2790
2850
|
var { server, StdioServerTransport } = await createServerRuntime({
|
|
2791
2851
|
name: "hex-line-mcp",
|
|
2792
2852
|
version
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@levnikolaevich/hex-line-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"mcpName": "io.github.levnikolaevich/hex-line-mcp",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Hash-verified file editing MCP + token efficiency hook for AI coding agents. 10 tools: read, edit, write, grep, outline, verify, directory_tree, file_info, changes, bulk_replace.",
|