embarsy-qdrant-mcp 0.1.2 → 0.1.3
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/chunker.js +14 -1
- package/dist/embeddings.js +8 -1
- package/package.json +1 -1
package/dist/chunker.js
CHANGED
|
@@ -39,13 +39,26 @@ export function chunkFile(content, cfg) {
|
|
|
39
39
|
if (nl > pos + Math.floor(maxChars / 2))
|
|
40
40
|
end = nl;
|
|
41
41
|
}
|
|
42
|
+
end = snapToCodePoint(content, end);
|
|
42
43
|
const text = content.slice(pos, end);
|
|
43
44
|
if (text.trim().length > 0) {
|
|
44
45
|
chunks.push({ startLine: lineAt(pos), endLine: lineAt(Math.max(pos, end - 1)), text });
|
|
45
46
|
}
|
|
46
47
|
if (end >= content.length)
|
|
47
48
|
break;
|
|
48
|
-
pos = Math.max(pos + 1, end - overlap);
|
|
49
|
+
pos = snapToCodePoint(content, Math.max(pos + 1, end - overlap));
|
|
49
50
|
}
|
|
50
51
|
return chunks;
|
|
51
52
|
}
|
|
53
|
+
/** A boundary that lands between the two halves of a surrogate pair would cut an emoji
|
|
54
|
+
* in half; the resulting lone surrogate is invalid Unicode that embedding backends
|
|
55
|
+
* reject (Python's UTF-8 encoder raises on it, turning the request into a 500).
|
|
56
|
+
* If the index points at a low surrogate, step back one unit to keep the pair whole. */
|
|
57
|
+
function snapToCodePoint(s, index) {
|
|
58
|
+
if (index > 0 && index < s.length) {
|
|
59
|
+
const code = s.charCodeAt(index);
|
|
60
|
+
if (code >= 0xdc00 && code <= 0xdfff)
|
|
61
|
+
return index - 1;
|
|
62
|
+
}
|
|
63
|
+
return index;
|
|
64
|
+
}
|
package/dist/embeddings.js
CHANGED
|
@@ -7,10 +7,17 @@ import { requestJSON } from "./http.js";
|
|
|
7
7
|
/** Absolute per-input cap (defense in depth on top of chunking) so no single text can overflow
|
|
8
8
|
* the model's context and crash the embedding backend, whatever produced it. */
|
|
9
9
|
const MAX_EMBED_CHARS = 8000;
|
|
10
|
+
/** Lone surrogates (an emoji cut in half by any UTF-16 slice) are invalid Unicode: the
|
|
11
|
+
* Embarsy API's UTF-8 re-encode for Ollama rejects them, failing the whole batch with
|
|
12
|
+
* a 500. Replace them with U+FFFD so one broken character can never sink an index run. */
|
|
13
|
+
const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
14
|
+
function wellFormed(text) {
|
|
15
|
+
return text.replace(LONE_SURROGATE, "�");
|
|
16
|
+
}
|
|
10
17
|
export async function embedBatch(texts, cfg) {
|
|
11
18
|
if (texts.length === 0)
|
|
12
19
|
return [];
|
|
13
|
-
const input = texts.map((t) => (t.length > MAX_EMBED_CHARS ? t.slice(0, MAX_EMBED_CHARS) : t));
|
|
20
|
+
const input = texts.map((t) => wellFormed(t.length > MAX_EMBED_CHARS ? t.slice(0, MAX_EMBED_CHARS) : t));
|
|
14
21
|
const json = await requestJSON(`${cfg.openaiBaseUrl}/embeddings`, {
|
|
15
22
|
method: "POST",
|
|
16
23
|
headers: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "embarsy-qdrant-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Codebase-indexing MCP server for Embarsy — semantic code search over a local Qdrant + OpenAI-compatible embeddings stack. Routes embeddings and Qdrant through Embarsy's proxy so auth and Monitoring counters just work.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|