notex-companion 0.4.0 → 0.4.1
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/cli.js +20 -0
- package/dist/client.js +20 -0
- package/dist/index.js +20 -0
- package/dist/ops.d.ts +1 -1
- package/dist/scoring.d.ts +2 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -6727,11 +6727,13 @@ function shatter(text) {
|
|
|
6727
6727
|
function terms(question) {
|
|
6728
6728
|
return [...new Set(shatter(question).filter((t) => t.length >= 3 && !STOPWORDS.has(t)))];
|
|
6729
6729
|
}
|
|
6730
|
+
var FUZZY_MATCH_EXACT_MIN_COUNT = 2;
|
|
6730
6731
|
function scoreNodes(index, queryTerms) {
|
|
6731
6732
|
const scored = [];
|
|
6732
6733
|
for (const entry of index) {
|
|
6733
6734
|
let score = 0;
|
|
6734
6735
|
let exact = false;
|
|
6736
|
+
let fuzzyMatchesByToken;
|
|
6735
6737
|
for (const term of queryTerms) {
|
|
6736
6738
|
let best = 0;
|
|
6737
6739
|
if (entry.labelLower === term) {
|
|
@@ -6744,6 +6746,16 @@ function scoreNodes(index, queryTerms) {
|
|
|
6744
6746
|
for (const tok of entry.labelTokens) {
|
|
6745
6747
|
if (tok.length >= 4 && (tok.startsWith(term) || term.startsWith(tok))) {
|
|
6746
6748
|
best = Math.max(best, 1.5);
|
|
6749
|
+
if (term.length >= 4) {
|
|
6750
|
+
if (!fuzzyMatchesByToken)
|
|
6751
|
+
fuzzyMatchesByToken = new Map;
|
|
6752
|
+
let matchedTerms = fuzzyMatchesByToken.get(tok);
|
|
6753
|
+
if (!matchedTerms) {
|
|
6754
|
+
matchedTerms = new Set;
|
|
6755
|
+
fuzzyMatchesByToken.set(tok, matchedTerms);
|
|
6756
|
+
}
|
|
6757
|
+
matchedTerms.add(term);
|
|
6758
|
+
}
|
|
6747
6759
|
} else if (term.length >= 4 && tok.includes(term)) {
|
|
6748
6760
|
best = Math.max(best, 1);
|
|
6749
6761
|
}
|
|
@@ -6761,6 +6773,14 @@ function scoreNodes(index, queryTerms) {
|
|
|
6761
6773
|
}
|
|
6762
6774
|
score += best;
|
|
6763
6775
|
}
|
|
6776
|
+
if (fuzzyMatchesByToken) {
|
|
6777
|
+
for (const matchedTerms of fuzzyMatchesByToken.values()) {
|
|
6778
|
+
if (matchedTerms.size >= FUZZY_MATCH_EXACT_MIN_COUNT) {
|
|
6779
|
+
exact = true;
|
|
6780
|
+
break;
|
|
6781
|
+
}
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6764
6784
|
if (score > 0)
|
|
6765
6785
|
scored.push({ id: entry.id, score: Math.round(score * 100) / 100, exact });
|
|
6766
6786
|
}
|
package/dist/client.js
CHANGED
|
@@ -98,11 +98,13 @@ function shatter(text) {
|
|
|
98
98
|
function terms(question) {
|
|
99
99
|
return [...new Set(shatter(question).filter((t) => t.length >= 3 && !STOPWORDS.has(t)))];
|
|
100
100
|
}
|
|
101
|
+
var FUZZY_MATCH_EXACT_MIN_COUNT = 2;
|
|
101
102
|
function scoreNodes(index, queryTerms) {
|
|
102
103
|
const scored = [];
|
|
103
104
|
for (const entry of index) {
|
|
104
105
|
let score = 0;
|
|
105
106
|
let exact = false;
|
|
107
|
+
let fuzzyMatchesByToken;
|
|
106
108
|
for (const term of queryTerms) {
|
|
107
109
|
let best = 0;
|
|
108
110
|
if (entry.labelLower === term) {
|
|
@@ -115,6 +117,16 @@ function scoreNodes(index, queryTerms) {
|
|
|
115
117
|
for (const tok of entry.labelTokens) {
|
|
116
118
|
if (tok.length >= 4 && (tok.startsWith(term) || term.startsWith(tok))) {
|
|
117
119
|
best = Math.max(best, 1.5);
|
|
120
|
+
if (term.length >= 4) {
|
|
121
|
+
if (!fuzzyMatchesByToken)
|
|
122
|
+
fuzzyMatchesByToken = new Map;
|
|
123
|
+
let matchedTerms = fuzzyMatchesByToken.get(tok);
|
|
124
|
+
if (!matchedTerms) {
|
|
125
|
+
matchedTerms = new Set;
|
|
126
|
+
fuzzyMatchesByToken.set(tok, matchedTerms);
|
|
127
|
+
}
|
|
128
|
+
matchedTerms.add(term);
|
|
129
|
+
}
|
|
118
130
|
} else if (term.length >= 4 && tok.includes(term)) {
|
|
119
131
|
best = Math.max(best, 1);
|
|
120
132
|
}
|
|
@@ -132,6 +144,14 @@ function scoreNodes(index, queryTerms) {
|
|
|
132
144
|
}
|
|
133
145
|
score += best;
|
|
134
146
|
}
|
|
147
|
+
if (fuzzyMatchesByToken) {
|
|
148
|
+
for (const matchedTerms of fuzzyMatchesByToken.values()) {
|
|
149
|
+
if (matchedTerms.size >= FUZZY_MATCH_EXACT_MIN_COUNT) {
|
|
150
|
+
exact = true;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
135
155
|
if (score > 0)
|
|
136
156
|
scored.push({ id: entry.id, score: Math.round(score * 100) / 100, exact });
|
|
137
157
|
}
|
package/dist/index.js
CHANGED
|
@@ -98,11 +98,13 @@ function shatter(text) {
|
|
|
98
98
|
function terms(question) {
|
|
99
99
|
return [...new Set(shatter(question).filter((t) => t.length >= 3 && !STOPWORDS.has(t)))];
|
|
100
100
|
}
|
|
101
|
+
var FUZZY_MATCH_EXACT_MIN_COUNT = 2;
|
|
101
102
|
function scoreNodes(index, queryTerms) {
|
|
102
103
|
const scored = [];
|
|
103
104
|
for (const entry of index) {
|
|
104
105
|
let score = 0;
|
|
105
106
|
let exact = false;
|
|
107
|
+
let fuzzyMatchesByToken;
|
|
106
108
|
for (const term of queryTerms) {
|
|
107
109
|
let best = 0;
|
|
108
110
|
if (entry.labelLower === term) {
|
|
@@ -115,6 +117,16 @@ function scoreNodes(index, queryTerms) {
|
|
|
115
117
|
for (const tok of entry.labelTokens) {
|
|
116
118
|
if (tok.length >= 4 && (tok.startsWith(term) || term.startsWith(tok))) {
|
|
117
119
|
best = Math.max(best, 1.5);
|
|
120
|
+
if (term.length >= 4) {
|
|
121
|
+
if (!fuzzyMatchesByToken)
|
|
122
|
+
fuzzyMatchesByToken = new Map;
|
|
123
|
+
let matchedTerms = fuzzyMatchesByToken.get(tok);
|
|
124
|
+
if (!matchedTerms) {
|
|
125
|
+
matchedTerms = new Set;
|
|
126
|
+
fuzzyMatchesByToken.set(tok, matchedTerms);
|
|
127
|
+
}
|
|
128
|
+
matchedTerms.add(term);
|
|
129
|
+
}
|
|
118
130
|
} else if (term.length >= 4 && tok.includes(term)) {
|
|
119
131
|
best = Math.max(best, 1);
|
|
120
132
|
}
|
|
@@ -132,6 +144,14 @@ function scoreNodes(index, queryTerms) {
|
|
|
132
144
|
}
|
|
133
145
|
score += best;
|
|
134
146
|
}
|
|
147
|
+
if (fuzzyMatchesByToken) {
|
|
148
|
+
for (const matchedTerms of fuzzyMatchesByToken.values()) {
|
|
149
|
+
if (matchedTerms.size >= FUZZY_MATCH_EXACT_MIN_COUNT) {
|
|
150
|
+
exact = true;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
135
155
|
if (score > 0)
|
|
136
156
|
scored.push({ id: entry.id, score: Math.round(score * 100) / 100, exact });
|
|
137
157
|
}
|
package/dist/ops.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export type QueryResult = {
|
|
|
73
73
|
};
|
|
74
74
|
/** See companion-api.md §4.8 / notex-mcp-server.md §5 — same buildFooter as the write paths. */
|
|
75
75
|
footer?: string;
|
|
76
|
-
/** Set when no seed cleared the seed-score floor —
|
|
76
|
+
/** Set when no seed cleared the seed-score floor — see ScoredNode's `exact` (scoring.ts). */
|
|
77
77
|
lowConfidence?: {
|
|
78
78
|
topScore: number;
|
|
79
79
|
};
|
package/dist/scoring.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ export type ScoreIndexEntry = {
|
|
|
10
10
|
export type ScoredNode = {
|
|
11
11
|
id: string;
|
|
12
12
|
score: number;
|
|
13
|
-
/** Cleared the seed-score floor: at least one term matched a whole label or a whole label
|
|
13
|
+
/** Cleared the seed-score floor: at least one term matched a whole label or a whole label
|
|
14
|
+
* token, or (TBR-130) at least two independent terms each fuzzy-prefix the same label token. */
|
|
14
15
|
exact: boolean;
|
|
15
16
|
};
|
|
16
17
|
/** label tokens weigh full; path tokens weigh less — a path match is weaker evidence. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "notex-companion",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Local retrieval companion for Notex — reads a checkout's graphify-out/graph.json and serves deterministic search/query/path/node lookups over loopback HTTP and MCP stdio. No LLM, no graph building, no network beyond 127.0.0.1.",
|
|
5
5
|
"keywords": ["notex", "graphify", "mcp", "code-graph"],
|
|
6
6
|
"license": "MIT",
|