ralph-hero-knowledge-index 0.1.18 → 0.1.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/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/dist/search.d.ts +1 -0
- package/dist/search.js +7 -1
- package/dist/search.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/search.test.ts +34 -1
- package/src/search.ts +7 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ralph-knowledge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Knowledge graph for ralph-hero: semantic search, relationship traversal, and document indexing across thoughts/ documents. Optional companion to ralph-hero.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Chad Dubiel",
|
package/.mcp.json
CHANGED
package/dist/search.d.ts
CHANGED
package/dist/search.js
CHANGED
|
@@ -60,10 +60,16 @@ export class FtsSearch {
|
|
|
60
60
|
SELECT rowid, title, path, content FROM documents
|
|
61
61
|
`);
|
|
62
62
|
}
|
|
63
|
+
escapeFts5Query(raw) {
|
|
64
|
+
const tokens = raw.split(/\s+/).filter(Boolean);
|
|
65
|
+
if (tokens.length === 0)
|
|
66
|
+
return '""';
|
|
67
|
+
return tokens.map(t => '"' + t.replace(/"/g, '""') + '"').join(" ");
|
|
68
|
+
}
|
|
63
69
|
search(query, options = {}) {
|
|
64
70
|
const { type, tags, includeSuperseded = false, limit = 20 } = options;
|
|
65
71
|
const conditions = ["documents_fts MATCH @query"];
|
|
66
|
-
const params = { query, limit };
|
|
72
|
+
const params = { query: this.escapeFts5Query(query), limit };
|
|
67
73
|
if (!includeSuperseded) {
|
|
68
74
|
conditions.push("d.status IS NOT 'superseded'");
|
|
69
75
|
}
|
package/dist/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,SAAS;IACH,EAAE,CAAc;IAEjC,YAAY,EAAe;QACzB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,KAAa;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAC5B,gEAAgE,CACjE,CAAC,GAAG,CAAC,KAAK,CAAgF,CAAC;QAC5F,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAChB,oGAAoG,CACrG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,KAAa;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAC5B,gEAAgE,CACjE,CAAC,GAAG,CAAC,KAAK,CAAgF,CAAC;QAC5F,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAChB,2EAA2E,CAC5E,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,4DAA4D;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAC/B,4EAA4E,CAC7E,CAAC,GAAG,EAAE,CAAC;QACR,IAAI,MAAM;YAAE,OAAO;QACnB,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;KAQf,CAAC,CAAC;IACL,CAAC;IAED,YAAY;QACV,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACtD,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;KAQf,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;;;KAGf,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,UAAyB,EAAE;QAC/C,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,iBAAiB,GAAG,KAAK,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;QAEtE,MAAM,UAAU,GAAa,CAAC,4BAA4B,CAAC,CAAC;QAC5D,MAAM,MAAM,GAA4B,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -68,7 +68,7 @@ describe("FtsSearch", () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it("filters by tags", () => {
|
|
71
|
-
const results = fts.search("
|
|
71
|
+
const results = fts.search("auth", { tags: ["security"] });
|
|
72
72
|
expect(results).toHaveLength(1);
|
|
73
73
|
expect(results[0].id).toBe("auth-doc");
|
|
74
74
|
});
|
|
@@ -172,6 +172,39 @@ describe("FtsSearch", () => {
|
|
|
172
172
|
});
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
+
describe("FTS5 query escaping", () => {
|
|
176
|
+
it("handles hyphenated tokens like GH-42", () => {
|
|
177
|
+
const results = fts.search("GH-42");
|
|
178
|
+
expect(Array.isArray(results)).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it("handles hyphenated path segments like cache-strategies", () => {
|
|
182
|
+
const results = fts.search("cache-strategies");
|
|
183
|
+
expect(Array.isArray(results)).toBe(true);
|
|
184
|
+
expect(results.some(r => r.id === "cache-doc")).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it("handles colon (FTS5 column filter) without crashing", () => {
|
|
188
|
+
const results = fts.search("column:injection");
|
|
189
|
+
expect(Array.isArray(results)).toBe(true);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("handles asterisk (FTS5 prefix wildcard) without crashing", () => {
|
|
193
|
+
const results = fts.search("test*");
|
|
194
|
+
expect(Array.isArray(results)).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("handles parentheses (FTS5 grouping) without crashing", () => {
|
|
198
|
+
const results = fts.search("(grouped)");
|
|
199
|
+
expect(Array.isArray(results)).toBe(true);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("handles multi-word query with special chars", () => {
|
|
203
|
+
const results = fts.search("implementation plan GH-730 playwright-aware");
|
|
204
|
+
expect(Array.isArray(results)).toBe(true);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
175
208
|
describe("ensureTable", () => {
|
|
176
209
|
it("creates FTS table if it does not exist", () => {
|
|
177
210
|
// Create a fresh DB without FTS table
|
package/src/search.ts
CHANGED
|
@@ -93,11 +93,17 @@ export class FtsSearch {
|
|
|
93
93
|
`);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
private escapeFts5Query(raw: string): string {
|
|
97
|
+
const tokens = raw.split(/\s+/).filter(Boolean);
|
|
98
|
+
if (tokens.length === 0) return '""';
|
|
99
|
+
return tokens.map(t => '"' + t.replace(/"/g, '""') + '"').join(" ");
|
|
100
|
+
}
|
|
101
|
+
|
|
96
102
|
search(query: string, options: SearchOptions = {}): SearchResult[] {
|
|
97
103
|
const { type, tags, includeSuperseded = false, limit = 20 } = options;
|
|
98
104
|
|
|
99
105
|
const conditions: string[] = ["documents_fts MATCH @query"];
|
|
100
|
-
const params: Record<string, unknown> = { query, limit };
|
|
106
|
+
const params: Record<string, unknown> = { query: this.escapeFts5Query(query), limit };
|
|
101
107
|
|
|
102
108
|
if (!includeSuperseded) {
|
|
103
109
|
conditions.push("d.status IS NOT 'superseded'");
|