@jefuriiij/synthra 0.1.19 → 0.1.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/CHANGELOG.md +28 -0
- package/dist/cli/index.js +39 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/index.js +1 -1
- package/dist/dashboard/index.js.map +1 -1
- package/dist/server/index.js +38 -5
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/server/index.js
CHANGED
|
@@ -1965,10 +1965,12 @@ function scoreFiles(inputs) {
|
|
|
1965
1965
|
}
|
|
1966
1966
|
const symbols = symbolsByFile.get(file.path) ?? [];
|
|
1967
1967
|
let symHits = 0;
|
|
1968
|
+
let exactSym = 0;
|
|
1968
1969
|
for (const sym of symbols) {
|
|
1969
1970
|
const name = sym.name.toLowerCase();
|
|
1970
1971
|
if (qTokens.has(name)) {
|
|
1971
1972
|
symHits += 3;
|
|
1973
|
+
exactSym += 1;
|
|
1972
1974
|
} else {
|
|
1973
1975
|
for (const t of qTokens) {
|
|
1974
1976
|
if (name.includes(t) || t.includes(name)) {
|
|
@@ -1993,7 +1995,7 @@ function scoreFiles(inputs) {
|
|
|
1993
1995
|
score2 += 5;
|
|
1994
1996
|
reasons.push("seed");
|
|
1995
1997
|
}
|
|
1996
|
-
scored.push({ file, score: score2, reasons });
|
|
1998
|
+
scored.push({ file, score: score2, reasons, symHits, exactSym });
|
|
1997
1999
|
}
|
|
1998
2000
|
const positivePaths = new Set(scored.filter((s) => s.score > 0).map((s) => s.file.path));
|
|
1999
2001
|
if (positivePaths.size > 0) {
|
|
@@ -2028,7 +2030,8 @@ async function retrieve(graph, query, options = {}) {
|
|
|
2028
2030
|
return {
|
|
2029
2031
|
files: [],
|
|
2030
2032
|
confidence: "low",
|
|
2031
|
-
reason: qTokens.length === 0 ? "empty query" : "empty graph"
|
|
2033
|
+
reason: qTokens.length === 0 ? "empty query" : "empty graph",
|
|
2034
|
+
symbolMatched: false
|
|
2032
2035
|
};
|
|
2033
2036
|
}
|
|
2034
2037
|
const rankInputs = {
|
|
@@ -2044,10 +2047,13 @@ async function retrieve(graph, query, options = {}) {
|
|
|
2044
2047
|
return {
|
|
2045
2048
|
files: [],
|
|
2046
2049
|
confidence: "low",
|
|
2047
|
-
reason: `no matches for ${JSON.stringify(qTokens)}
|
|
2050
|
+
reason: `no matches for ${JSON.stringify(qTokens)}`,
|
|
2051
|
+
symbolMatched: false
|
|
2048
2052
|
};
|
|
2049
2053
|
}
|
|
2050
|
-
const
|
|
2054
|
+
const topScored = positive.slice(0, topK);
|
|
2055
|
+
const top = topScored.map((s) => s.file);
|
|
2056
|
+
const symbolMatched = topScored.some((s) => s.exactSym > 0);
|
|
2051
2057
|
const topScore = positive[0]?.score ?? 0;
|
|
2052
2058
|
const secondScore = positive[1]?.score ?? 0;
|
|
2053
2059
|
let confidence;
|
|
@@ -2059,7 +2065,8 @@ async function retrieve(graph, query, options = {}) {
|
|
|
2059
2065
|
return {
|
|
2060
2066
|
files: top,
|
|
2061
2067
|
confidence,
|
|
2062
|
-
reason: `top: ${reasons}
|
|
2068
|
+
reason: `top: ${reasons}`,
|
|
2069
|
+
symbolMatched
|
|
2063
2070
|
};
|
|
2064
2071
|
}
|
|
2065
2072
|
|
|
@@ -2913,6 +2920,16 @@ function extractQuery(toolName, input) {
|
|
|
2913
2920
|
}
|
|
2914
2921
|
return null;
|
|
2915
2922
|
}
|
|
2923
|
+
function looksLikeNonSymbolQuery(pattern) {
|
|
2924
|
+
if (/<\/?[a-zA-Z]/.test(pattern)) return true;
|
|
2925
|
+
if (/[a-zA-Z][\w-]*-[\w-]*\s*=/.test(pattern)) return true;
|
|
2926
|
+
if (/\{/.test(pattern)) return true;
|
|
2927
|
+
if (/\\\.[a-zA-Z]/.test(pattern)) return true;
|
|
2928
|
+
if (/:\s*\d/.test(pattern) || /\d(?:px|rem|em|vh|vw)\b/.test(pattern) || /\d%/.test(pattern)) {
|
|
2929
|
+
return true;
|
|
2930
|
+
}
|
|
2931
|
+
return false;
|
|
2932
|
+
}
|
|
2916
2933
|
function recentlyTouchedMatchesQuery(recentPaths, queryTokens) {
|
|
2917
2934
|
const matches = [];
|
|
2918
2935
|
for (const path of recentPaths) {
|
|
@@ -2954,6 +2971,14 @@ async function handleGate(req, ctx) {
|
|
|
2954
2971
|
await logDecision(ctx, req.tool_name, null, res2.decision, res2.reason);
|
|
2955
2972
|
return res2;
|
|
2956
2973
|
}
|
|
2974
|
+
if (req.tool_name === "Grep" && looksLikeNonSymbolQuery(query)) {
|
|
2975
|
+
const res2 = {
|
|
2976
|
+
decision: "allow",
|
|
2977
|
+
reason: `"${query}" targets markup/CSS/attributes, not code symbols \u2014 letting Grep through (the graph indexes symbols).`
|
|
2978
|
+
};
|
|
2979
|
+
await logDecision(ctx, req.tool_name, query, res2.decision, res2.reason);
|
|
2980
|
+
return res2;
|
|
2981
|
+
}
|
|
2957
2982
|
const retrieval = await retrieve(ctx.graph, query);
|
|
2958
2983
|
if (retrieval.confidence === "low") {
|
|
2959
2984
|
const res2 = {
|
|
@@ -2974,6 +2999,14 @@ async function handleGate(req, ctx) {
|
|
|
2974
2999
|
await logDecision(ctx, req.tool_name, query, res2.decision, res2.reason);
|
|
2975
3000
|
return res2;
|
|
2976
3001
|
}
|
|
3002
|
+
if (!retrieval.symbolMatched) {
|
|
3003
|
+
const res2 = {
|
|
3004
|
+
decision: "allow",
|
|
3005
|
+
reason: `confidence=${retrieval.confidence} but only keyword/path matched (no symbol the query names) \u2014 graph_read can't slice it, letting ${req.tool_name} through.`
|
|
3006
|
+
};
|
|
3007
|
+
await logDecision(ctx, req.tool_name, query, res2.decision, res2.reason);
|
|
3008
|
+
return res2;
|
|
3009
|
+
}
|
|
2977
3010
|
const top = retrieval.files.slice(0, 3).map((f) => f.path).join(", ");
|
|
2978
3011
|
const res = {
|
|
2979
3012
|
decision: "block",
|