@voidwire/lore 2.0.0 → 2.1.0

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/lib/search.ts CHANGED
@@ -5,9 +5,7 @@
5
5
  * Uses Bun's built-in SQLite for zero external dependencies.
6
6
  */
7
7
 
8
- import { Database } from "bun:sqlite";
9
- import { existsSync } from "fs";
10
- import { getDatabasePath } from "./db.js";
8
+ import { openDatabaseBasic } from "./db.js";
11
9
 
12
10
  export interface SearchResult {
13
11
  rowid: number;
@@ -53,13 +51,7 @@ export function search(
53
51
  query: string,
54
52
  options: SearchOptions = {},
55
53
  ): SearchResult[] {
56
- const dbPath = getDatabasePath();
57
-
58
- if (!existsSync(dbPath)) {
59
- throw new Error(`Database not found: ${dbPath}. Run lore-db-init first.`);
60
- }
61
-
62
- const db = new Database(dbPath, { readonly: true });
54
+ const db = openDatabaseBasic(true);
63
55
 
64
56
  try {
65
57
  const limit = options.limit ?? 20;
@@ -117,18 +109,73 @@ export function search(
117
109
  }
118
110
 
119
111
  /**
120
- * List all available sources in the database
112
+ * Raw content result from FTS5 query (no snippet formatting).
113
+ * Used by contradiction detection where clean content is needed for LLM comparison.
114
+ */
115
+ export interface RawSearchResult {
116
+ rowid: number;
117
+ source: string;
118
+ title: string;
119
+ content: string;
120
+ metadata: string;
121
+ topic: string;
122
+ type: string;
123
+ timestamp: string;
124
+ }
125
+
126
+ /**
127
+ * Search the FTS5 database returning raw content (no snippet markers).
121
128
  *
122
- * @returns Array of source names with entry counts
129
+ * Unlike search(), this returns the raw content column without FTS5 snippet()
130
+ * formatting. Used by contradiction detection where snippet markers (arrows)
131
+ * would corrupt LLM text comparison.
132
+ *
133
+ * @param query - Text to match against FTS5 index
134
+ * @param options - Optional source filter and result limit
135
+ * @returns Array of raw search results ranked by relevance
136
+ * @throws Error if database doesn't exist or query fails
123
137
  */
124
- export function listSources(): { source: string; count: number }[] {
125
- const dbPath = getDatabasePath();
138
+ export function rawSearch(
139
+ query: string,
140
+ options: { source?: string; limit?: number } = {},
141
+ ): RawSearchResult[] {
142
+ const db = openDatabaseBasic(true);
143
+
144
+ try {
145
+ const limit = options.limit ?? 5;
146
+
147
+ const conditions: string[] = ["search MATCH ?"];
148
+ const params: (string | number)[] = [escapeFts5Query(query)];
149
+
150
+ if (options.source) {
151
+ conditions.push("source = ?");
152
+ params.push(options.source);
153
+ }
154
+
155
+ params.push(limit);
156
+
157
+ const sql = `
158
+ SELECT rowid, source, title, content, metadata, topic, type, timestamp
159
+ FROM search
160
+ WHERE ${conditions.join(" AND ")}
161
+ ORDER BY rank
162
+ LIMIT ?
163
+ `;
126
164
 
127
- if (!existsSync(dbPath)) {
128
- throw new Error(`Database not found: ${dbPath}. Run lore-db-init first.`);
165
+ const stmt = db.prepare(sql);
166
+ return stmt.all(...params) as RawSearchResult[];
167
+ } finally {
168
+ db.close();
129
169
  }
170
+ }
130
171
 
131
- const db = new Database(dbPath, { readonly: true });
172
+ /**
173
+ * List all available sources in the database
174
+ *
175
+ * @returns Array of source names with entry counts
176
+ */
177
+ export function listSources(): { source: string; count: number }[] {
178
+ const db = openDatabaseBasic(true);
132
179
 
133
180
  try {
134
181
  const stmt = db.prepare(`
package/lib/semantic.ts CHANGED
@@ -35,7 +35,13 @@ export interface SemanticSearchOptions {
35
35
  since?: string;
36
36
  }
37
37
 
38
- const { model: MODEL_NAME, dimensions: EMBEDDING_DIM } = getConfig().embedding;
38
+ // Lazy avoids getConfig() at import time so `lore init` works on clean machines
39
+ function MODEL_NAME(): string {
40
+ return getConfig().embedding.model;
41
+ }
42
+ function EMBEDDING_DIM(): number {
43
+ return getConfig().embedding.dimensions;
44
+ }
39
45
 
40
46
  /**
41
47
  * Embed a query string via the embed server
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voidwire/lore",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Unified knowledge CLI - Search, list, and capture your indexed knowledge",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -21,6 +21,7 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "build": "tsc --noEmit false --outDir dist --declaration",
24
+ "tsc": "tsc",
24
25
  "typecheck": "tsc --noEmit",
25
26
  "test": "bun test"
26
27
  },
@@ -48,7 +49,8 @@
48
49
  },
49
50
  "dependencies": {
50
51
  "@iarna/toml": "^2.2.5",
51
- "@voidwire/llm-core": "^0.4.0"
52
+ "@voidwire/llm-core": "^0.4.0",
53
+ "sqlite-vec": "^0.1.9"
52
54
  },
53
55
  "devDependencies": {
54
56
  "bun-types": "1.3.5"