fix(memory): FTS5-safe search-term quoting — "TSK-0037"-style queries no longer crash (TSK-0043)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8b17baae96
commit
caf60ea939
@ -101,6 +101,8 @@ export class Index {
|
||||
}
|
||||
|
||||
search(query: string): Array<{ id: string; type: string; title: string }> {
|
||||
const ftsQuery = toFts5Phrase(query);
|
||||
if (!ftsQuery) return [];
|
||||
const stmt = this.db.prepare(`
|
||||
SELECT e.id, e.type, e.title
|
||||
FROM search s
|
||||
@ -108,7 +110,7 @@ export class Index {
|
||||
WHERE search MATCH @query
|
||||
ORDER BY rank
|
||||
`);
|
||||
return stmt.all({ query }) as Array<{ id: string; type: string; title: string }>;
|
||||
return stmt.all({ query: ftsQuery }) as Array<{ id: string; type: string; title: string }>;
|
||||
}
|
||||
|
||||
list(type?: string, filters?: { status?: string; role?: string; assignedTo?: string }): IndexEntry[] {
|
||||
@ -162,3 +164,9 @@ export class Index {
|
||||
this.db.close();
|
||||
}
|
||||
}
|
||||
|
||||
function toFts5Phrase(query: string): string {
|
||||
const trimmed = query.trim();
|
||||
if (!trimmed) return '';
|
||||
return `"${trimmed.replace(/"/g, '""')}"`;
|
||||
}
|
||||
|
||||
@ -18,6 +18,29 @@ describe('memoryService', () => {
|
||||
expect(listMemory(cwd)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('searches literal task IDs and other FTS5-special strings without throwing', () => {
|
||||
addMemory(cwd, {
|
||||
title: 'TSK-0037 result',
|
||||
category: 'implementation',
|
||||
content: 'Linked HOF-0030 and a:b plus foo-bar all belong to this note.',
|
||||
});
|
||||
|
||||
expect(searchMemory(cwd, 'TSK-0037')).toHaveLength(1);
|
||||
expect(searchMemory(cwd, 'HOF-0030')).toHaveLength(1);
|
||||
expect(searchMemory(cwd, 'a:b')).toHaveLength(1);
|
||||
expect(searchMemory(cwd, 'foo-bar')).toHaveLength(1);
|
||||
expect(searchMemory(cwd, 'TTL')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('keeps normal word search functional after FTS5 quoting', () => {
|
||||
addMemory(cwd, { title: 'DNS cache', category: 'technical', content: 'Use TTL' });
|
||||
addMemory(cwd, { title: 'Other note', category: 'technical', content: 'No cache keyword here' });
|
||||
|
||||
const results = searchMemory(cwd, 'TTL');
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0].title).toBe('DNS cache');
|
||||
});
|
||||
|
||||
it('stores relatedTasks in the memory object', () => {
|
||||
const m = addMemory(cwd, {
|
||||
title: 'TTL lesson',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user