@gmickel/gno 0.7.0 → 0.8.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.
Files changed (209) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -50
  3. package/THIRD_PARTY_NOTICES.md +22 -0
  4. package/assets/screenshots/webui-ask-answer.png +0 -0
  5. package/assets/screenshots/webui-collections.png +0 -0
  6. package/assets/screenshots/webui-editor.png +0 -0
  7. package/assets/screenshots/webui-home.png +0 -0
  8. package/assets/skill/SKILL.md +12 -12
  9. package/assets/skill/cli-reference.md +59 -57
  10. package/assets/skill/examples.md +8 -7
  11. package/assets/skill/mcp-reference.md +8 -4
  12. package/package.json +31 -24
  13. package/src/app/constants.ts +43 -42
  14. package/src/cli/colors.ts +1 -1
  15. package/src/cli/commands/ask.ts +44 -43
  16. package/src/cli/commands/cleanup.ts +9 -8
  17. package/src/cli/commands/collection/add.ts +12 -12
  18. package/src/cli/commands/collection/index.ts +4 -4
  19. package/src/cli/commands/collection/list.ts +26 -25
  20. package/src/cli/commands/collection/remove.ts +10 -10
  21. package/src/cli/commands/collection/rename.ts +10 -10
  22. package/src/cli/commands/context/add.ts +1 -1
  23. package/src/cli/commands/context/check.ts +17 -17
  24. package/src/cli/commands/context/index.ts +4 -4
  25. package/src/cli/commands/context/list.ts +11 -11
  26. package/src/cli/commands/context/rm.ts +1 -1
  27. package/src/cli/commands/doctor.ts +86 -84
  28. package/src/cli/commands/embed.ts +30 -28
  29. package/src/cli/commands/get.ts +27 -26
  30. package/src/cli/commands/index-cmd.ts +9 -9
  31. package/src/cli/commands/index.ts +16 -16
  32. package/src/cli/commands/init.ts +13 -12
  33. package/src/cli/commands/ls.ts +20 -19
  34. package/src/cli/commands/mcp/config.ts +30 -28
  35. package/src/cli/commands/mcp/index.ts +4 -4
  36. package/src/cli/commands/mcp/install.ts +17 -17
  37. package/src/cli/commands/mcp/paths.ts +133 -133
  38. package/src/cli/commands/mcp/status.ts +21 -21
  39. package/src/cli/commands/mcp/uninstall.ts +13 -13
  40. package/src/cli/commands/mcp.ts +2 -2
  41. package/src/cli/commands/models/clear.ts +12 -11
  42. package/src/cli/commands/models/index.ts +5 -5
  43. package/src/cli/commands/models/list.ts +31 -30
  44. package/src/cli/commands/models/path.ts +1 -1
  45. package/src/cli/commands/models/pull.ts +19 -18
  46. package/src/cli/commands/models/use.ts +4 -4
  47. package/src/cli/commands/multi-get.ts +38 -36
  48. package/src/cli/commands/query.ts +21 -20
  49. package/src/cli/commands/ref-parser.ts +10 -10
  50. package/src/cli/commands/reset.ts +40 -39
  51. package/src/cli/commands/search.ts +14 -13
  52. package/src/cli/commands/serve.ts +4 -4
  53. package/src/cli/commands/shared.ts +11 -10
  54. package/src/cli/commands/skill/index.ts +5 -5
  55. package/src/cli/commands/skill/install.ts +18 -17
  56. package/src/cli/commands/skill/paths-cmd.ts +11 -10
  57. package/src/cli/commands/skill/paths.ts +23 -23
  58. package/src/cli/commands/skill/show.ts +13 -12
  59. package/src/cli/commands/skill/uninstall.ts +16 -15
  60. package/src/cli/commands/status.ts +25 -24
  61. package/src/cli/commands/update.ts +3 -3
  62. package/src/cli/commands/vsearch.ts +17 -16
  63. package/src/cli/context.ts +5 -5
  64. package/src/cli/errors.ts +3 -3
  65. package/src/cli/format/search-results.ts +37 -37
  66. package/src/cli/options.ts +43 -43
  67. package/src/cli/program.ts +455 -459
  68. package/src/cli/progress.ts +1 -1
  69. package/src/cli/run.ts +24 -23
  70. package/src/collection/add.ts +9 -8
  71. package/src/collection/index.ts +3 -3
  72. package/src/collection/remove.ts +7 -6
  73. package/src/collection/types.ts +6 -6
  74. package/src/config/defaults.ts +1 -1
  75. package/src/config/index.ts +5 -5
  76. package/src/config/loader.ts +19 -18
  77. package/src/config/paths.ts +9 -8
  78. package/src/config/saver.ts +14 -13
  79. package/src/config/types.ts +53 -52
  80. package/src/converters/adapters/markitdownTs/adapter.ts +21 -19
  81. package/src/converters/adapters/officeparser/adapter.ts +18 -16
  82. package/src/converters/canonicalize.ts +12 -12
  83. package/src/converters/errors.ts +26 -22
  84. package/src/converters/index.ts +8 -8
  85. package/src/converters/mime.ts +25 -25
  86. package/src/converters/native/markdown.ts +10 -9
  87. package/src/converters/native/plaintext.ts +8 -7
  88. package/src/converters/path.ts +2 -2
  89. package/src/converters/pipeline.ts +11 -10
  90. package/src/converters/registry.ts +8 -8
  91. package/src/converters/types.ts +14 -14
  92. package/src/converters/versions.ts +4 -4
  93. package/src/index.ts +4 -4
  94. package/src/ingestion/chunker.ts +10 -9
  95. package/src/ingestion/index.ts +6 -6
  96. package/src/ingestion/language.ts +62 -62
  97. package/src/ingestion/sync.ts +50 -49
  98. package/src/ingestion/types.ts +10 -10
  99. package/src/ingestion/walker.ts +14 -13
  100. package/src/llm/cache.ts +51 -49
  101. package/src/llm/errors.ts +40 -36
  102. package/src/llm/index.ts +9 -9
  103. package/src/llm/lockfile.ts +6 -6
  104. package/src/llm/nodeLlamaCpp/adapter.ts +13 -12
  105. package/src/llm/nodeLlamaCpp/embedding.ts +9 -8
  106. package/src/llm/nodeLlamaCpp/generation.ts +7 -6
  107. package/src/llm/nodeLlamaCpp/lifecycle.ts +11 -10
  108. package/src/llm/nodeLlamaCpp/rerank.ts +6 -5
  109. package/src/llm/policy.ts +5 -5
  110. package/src/llm/registry.ts +6 -5
  111. package/src/llm/types.ts +2 -2
  112. package/src/mcp/resources/index.ts +15 -13
  113. package/src/mcp/server.ts +25 -23
  114. package/src/mcp/tools/get.ts +25 -23
  115. package/src/mcp/tools/index.ts +32 -29
  116. package/src/mcp/tools/multi-get.ts +34 -32
  117. package/src/mcp/tools/query.ts +29 -27
  118. package/src/mcp/tools/search.ts +14 -12
  119. package/src/mcp/tools/status.ts +12 -11
  120. package/src/mcp/tools/vsearch.ts +26 -24
  121. package/src/pipeline/answer.ts +9 -9
  122. package/src/pipeline/chunk-lookup.ts +1 -1
  123. package/src/pipeline/contextual.ts +4 -4
  124. package/src/pipeline/expansion.ts +23 -21
  125. package/src/pipeline/explain.ts +21 -21
  126. package/src/pipeline/fusion.ts +9 -9
  127. package/src/pipeline/hybrid.ts +41 -42
  128. package/src/pipeline/index.ts +10 -10
  129. package/src/pipeline/query-language.ts +39 -39
  130. package/src/pipeline/rerank.ts +8 -7
  131. package/src/pipeline/search.ts +22 -22
  132. package/src/pipeline/types.ts +8 -8
  133. package/src/pipeline/vsearch.ts +21 -24
  134. package/src/serve/CLAUDE.md +21 -15
  135. package/src/serve/config-sync.ts +9 -8
  136. package/src/serve/context.ts +19 -18
  137. package/src/serve/index.ts +1 -1
  138. package/src/serve/jobs.ts +7 -7
  139. package/src/serve/public/app.tsx +79 -25
  140. package/src/serve/public/components/AddCollectionDialog.tsx +382 -0
  141. package/src/serve/public/components/CaptureButton.tsx +60 -0
  142. package/src/serve/public/components/CaptureModal.tsx +365 -0
  143. package/src/serve/public/components/IndexingProgress.tsx +333 -0
  144. package/src/serve/public/components/ShortcutHelpModal.tsx +106 -0
  145. package/src/serve/public/components/ai-elements/code-block.tsx +42 -32
  146. package/src/serve/public/components/ai-elements/conversation.tsx +16 -14
  147. package/src/serve/public/components/ai-elements/inline-citation.tsx +33 -32
  148. package/src/serve/public/components/ai-elements/loader.tsx +5 -4
  149. package/src/serve/public/components/ai-elements/message.tsx +39 -37
  150. package/src/serve/public/components/ai-elements/prompt-input.tsx +97 -95
  151. package/src/serve/public/components/ai-elements/sources.tsx +12 -10
  152. package/src/serve/public/components/ai-elements/suggestion.tsx +10 -9
  153. package/src/serve/public/components/editor/CodeMirrorEditor.tsx +142 -0
  154. package/src/serve/public/components/editor/MarkdownPreview.tsx +311 -0
  155. package/src/serve/public/components/editor/index.ts +6 -0
  156. package/src/serve/public/components/preset-selector.tsx +29 -28
  157. package/src/serve/public/components/ui/badge.tsx +13 -12
  158. package/src/serve/public/components/ui/button-group.tsx +13 -12
  159. package/src/serve/public/components/ui/button.tsx +23 -22
  160. package/src/serve/public/components/ui/card.tsx +16 -16
  161. package/src/serve/public/components/ui/carousel.tsx +36 -35
  162. package/src/serve/public/components/ui/collapsible.tsx +1 -1
  163. package/src/serve/public/components/ui/command.tsx +17 -15
  164. package/src/serve/public/components/ui/dialog.tsx +13 -12
  165. package/src/serve/public/components/ui/dropdown-menu.tsx +13 -12
  166. package/src/serve/public/components/ui/hover-card.tsx +6 -5
  167. package/src/serve/public/components/ui/input-group.tsx +45 -43
  168. package/src/serve/public/components/ui/input.tsx +6 -6
  169. package/src/serve/public/components/ui/progress.tsx +5 -4
  170. package/src/serve/public/components/ui/scroll-area.tsx +11 -10
  171. package/src/serve/public/components/ui/select.tsx +19 -18
  172. package/src/serve/public/components/ui/separator.tsx +6 -5
  173. package/src/serve/public/components/ui/table.tsx +18 -18
  174. package/src/serve/public/components/ui/textarea.tsx +4 -4
  175. package/src/serve/public/components/ui/tooltip.tsx +5 -4
  176. package/src/serve/public/globals.css +27 -4
  177. package/src/serve/public/hooks/use-api.ts +8 -8
  178. package/src/serve/public/hooks/useCaptureModal.tsx +83 -0
  179. package/src/serve/public/hooks/useKeyboardShortcuts.ts +85 -0
  180. package/src/serve/public/index.html +4 -4
  181. package/src/serve/public/lib/utils.ts +6 -0
  182. package/src/serve/public/pages/Ask.tsx +27 -26
  183. package/src/serve/public/pages/Browse.tsx +28 -27
  184. package/src/serve/public/pages/Collections.tsx +439 -0
  185. package/src/serve/public/pages/Dashboard.tsx +166 -40
  186. package/src/serve/public/pages/DocView.tsx +258 -73
  187. package/src/serve/public/pages/DocumentEditor.tsx +510 -0
  188. package/src/serve/public/pages/Search.tsx +80 -58
  189. package/src/serve/routes/api.ts +272 -155
  190. package/src/serve/security.ts +4 -4
  191. package/src/serve/server.ts +66 -48
  192. package/src/store/index.ts +5 -5
  193. package/src/store/migrations/001-initial.ts +24 -23
  194. package/src/store/migrations/002-documents-fts.ts +7 -6
  195. package/src/store/migrations/index.ts +4 -4
  196. package/src/store/migrations/runner.ts +17 -15
  197. package/src/store/sqlite/adapter.ts +123 -121
  198. package/src/store/sqlite/fts5-snowball.ts +24 -23
  199. package/src/store/sqlite/index.ts +1 -1
  200. package/src/store/sqlite/setup.ts +12 -12
  201. package/src/store/sqlite/types.ts +4 -4
  202. package/src/store/types.ts +19 -19
  203. package/src/store/vector/index.ts +3 -3
  204. package/src/store/vector/sqlite-vec.ts +23 -20
  205. package/src/store/vector/stats.ts +10 -8
  206. package/src/store/vector/types.ts +2 -2
  207. package/vendor/fts5-snowball/README.md +6 -6
  208. package/assets/screenshots/webui-ask-answer.jpg +0 -0
  209. package/assets/screenshots/webui-home.jpg +0 -0
@@ -8,11 +8,10 @@
8
8
  */
9
9
 
10
10
  // CRITICAL: Import setup FIRST to configure custom SQLite before any Database use
11
- import './setup';
12
- import { Database } from 'bun:sqlite';
13
- import { buildUri, deriveDocid } from '../../app/constants';
14
- import type { Collection, Context, FtsTokenizer } from '../../config/types';
15
- import { migrations, runMigrations } from '../migrations';
11
+ import "./setup";
12
+ import { Database } from "bun:sqlite";
13
+
14
+ import type { Collection, Context, FtsTokenizer } from "../../config/types";
16
15
  import type {
17
16
  ChunkInput,
18
17
  ChunkRow,
@@ -29,10 +28,13 @@ import type {
29
28
  MigrationResult,
30
29
  StorePort,
31
30
  StoreResult,
32
- } from '../types';
33
- import { err, ok } from '../types';
34
- import { loadFts5Snowball } from './fts5-snowball';
35
- import type { SqliteDbProvider } from './types';
31
+ } from "../types";
32
+ import type { SqliteDbProvider } from "./types";
33
+
34
+ import { buildUri, deriveDocid } from "../../app/constants";
35
+ import { migrations, runMigrations } from "../migrations";
36
+ import { err, ok } from "../types";
37
+ import { loadFts5Snowball } from "./fts5-snowball";
36
38
 
37
39
  // ─────────────────────────────────────────────────────────────────────────────
38
40
  // FTS5 Query Escaping
@@ -56,7 +58,7 @@ function escapeFts5Query(query: string): string {
56
58
  const escaped = token.replace(/"/g, '""');
57
59
  return `"${escaped}"`;
58
60
  })
59
- .join(' ');
61
+ .join(" ");
60
62
  }
61
63
 
62
64
  // ─────────────────────────────────────────────────────────────────────────────
@@ -71,9 +73,9 @@ const INDEX_PREFIX_REGEX = /^index-/;
71
73
 
72
74
  export class SqliteAdapter implements StorePort, SqliteDbProvider {
73
75
  private db: Database | null = null;
74
- private dbPath = '';
75
- private ftsTokenizer: FtsTokenizer = 'unicode61';
76
- private configPath = ''; // Set by CLI layer for status output
76
+ private dbPath = "";
77
+ private ftsTokenizer: FtsTokenizer = "unicode61";
78
+ private configPath = ""; // Set by CLI layer for status output
77
79
  private txDepth = 0; // Transaction nesting depth
78
80
  private txCounter = 0; // Savepoint counter for unique names
79
81
 
@@ -91,27 +93,27 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
91
93
  this.ftsTokenizer = ftsTokenizer;
92
94
 
93
95
  // Enable pragmas for performance and safety
94
- this.db.exec('PRAGMA foreign_keys = ON');
95
- this.db.exec('PRAGMA busy_timeout = 5000');
96
+ this.db.exec("PRAGMA foreign_keys = ON");
97
+ this.db.exec("PRAGMA busy_timeout = 5000");
96
98
 
97
99
  // CI mode: trade durability for speed (no fsync, memory journal)
98
100
  // Safe for tests since we don't need crash recovery
99
101
  if (process.env.CI) {
100
- this.db.exec('PRAGMA journal_mode = MEMORY');
101
- this.db.exec('PRAGMA synchronous = OFF');
102
- this.db.exec('PRAGMA temp_store = MEMORY');
102
+ this.db.exec("PRAGMA journal_mode = MEMORY");
103
+ this.db.exec("PRAGMA synchronous = OFF");
104
+ this.db.exec("PRAGMA temp_store = MEMORY");
103
105
  } else {
104
- this.db.exec('PRAGMA journal_mode = WAL');
106
+ this.db.exec("PRAGMA journal_mode = WAL");
105
107
  }
106
108
 
107
109
  // Load fts5-snowball extension if using snowball tokenizer
108
- if (ftsTokenizer.startsWith('snowball')) {
110
+ if (ftsTokenizer.startsWith("snowball")) {
109
111
  const snowballResult = loadFts5Snowball(this.db);
110
112
  if (!snowballResult.loaded) {
111
113
  this.db.close();
112
114
  this.db = null;
113
115
  return err(
114
- 'EXTENSION_LOAD_FAILED',
116
+ "EXTENSION_LOAD_FAILED",
115
117
  `Failed to load fts5-snowball: ${snowballResult.error}`
116
118
  );
117
119
  }
@@ -128,8 +130,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
128
130
  return result;
129
131
  } catch (cause) {
130
132
  const message =
131
- cause instanceof Error ? cause.message : 'Failed to open database';
132
- return err('CONNECTION_FAILED', message, cause);
133
+ cause instanceof Error ? cause.message : "Failed to open database";
134
+ return err("CONNECTION_FAILED", message, cause);
133
135
  }
134
136
  }
135
137
 
@@ -160,7 +162,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
160
162
  try {
161
163
  if (isOuter) {
162
164
  // IMMEDIATE reduces lock churn for bulk writes
163
- db.exec('BEGIN IMMEDIATE');
165
+ db.exec("BEGIN IMMEDIATE");
164
166
  } else {
165
167
  db.exec(`SAVEPOINT ${savepoint}`);
166
168
  }
@@ -170,7 +172,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
170
172
  this.txDepth -= 1;
171
173
 
172
174
  if (isOuter) {
173
- db.exec('COMMIT');
175
+ db.exec("COMMIT");
174
176
  } else {
175
177
  db.exec(`RELEASE ${savepoint}`);
176
178
  }
@@ -181,7 +183,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
181
183
 
182
184
  try {
183
185
  if (isOuter) {
184
- db.exec('ROLLBACK');
186
+ db.exec("ROLLBACK");
185
187
  } else {
186
188
  db.exec(`ROLLBACK TO ${savepoint}`);
187
189
  db.exec(`RELEASE ${savepoint}`);
@@ -191,8 +193,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
191
193
  }
192
194
 
193
195
  const message =
194
- cause instanceof Error ? cause.message : 'Transaction failed';
195
- return err('TRANSACTION_FAILED', message, cause);
196
+ cause instanceof Error ? cause.message : "Transaction failed";
197
+ return err("TRANSACTION_FAILED", message, cause);
196
198
  }
197
199
  }
198
200
 
@@ -213,7 +215,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
213
215
 
214
216
  private ensureOpen(): Database {
215
217
  if (!this.db) {
216
- throw new Error('Database not open');
218
+ throw new Error("Database not open");
217
219
  }
218
220
  return this.db;
219
221
  }
@@ -230,7 +232,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
230
232
  // Get existing collection names
231
233
  const existing = new Set(
232
234
  db
233
- .query<{ name: string }, []>('SELECT name FROM collections')
235
+ .query<{ name: string }, []>("SELECT name FROM collections")
234
236
  .all()
235
237
  .map((r) => r.name)
236
238
  );
@@ -240,7 +242,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
240
242
  // Delete removed collections
241
243
  for (const name of existing) {
242
244
  if (!incoming.has(name)) {
243
- db.run('DELETE FROM collections WHERE name = ?', [name]);
245
+ db.run("DELETE FROM collections WHERE name = ?", [name]);
244
246
  }
245
247
  }
246
248
 
@@ -275,8 +277,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
275
277
  return ok(undefined);
276
278
  } catch (cause) {
277
279
  return err(
278
- 'QUERY_FAILED',
279
- cause instanceof Error ? cause.message : 'Failed to sync collections',
280
+ "QUERY_FAILED",
281
+ cause instanceof Error ? cause.message : "Failed to sync collections",
280
282
  cause
281
283
  );
282
284
  }
@@ -288,7 +290,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
288
290
 
289
291
  const transaction = db.transaction(() => {
290
292
  // Delete all and re-insert (contexts are small)
291
- db.run('DELETE FROM contexts');
293
+ db.run("DELETE FROM contexts");
292
294
 
293
295
  const stmt = db.prepare(`
294
296
  INSERT INTO contexts (scope_type, scope_key, text, synced_at)
@@ -304,8 +306,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
304
306
  return ok(undefined);
305
307
  } catch (cause) {
306
308
  return err(
307
- 'QUERY_FAILED',
308
- cause instanceof Error ? cause.message : 'Failed to sync contexts',
309
+ "QUERY_FAILED",
310
+ cause instanceof Error ? cause.message : "Failed to sync contexts",
309
311
  cause
310
312
  );
311
313
  }
@@ -315,14 +317,14 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
315
317
  try {
316
318
  const db = this.ensureOpen();
317
319
  const rows = db
318
- .query<DbCollectionRow, []>('SELECT * FROM collections')
320
+ .query<DbCollectionRow, []>("SELECT * FROM collections")
319
321
  .all();
320
322
 
321
323
  return ok(rows.map(mapCollectionRow));
322
324
  } catch (cause) {
323
325
  return err(
324
- 'QUERY_FAILED',
325
- cause instanceof Error ? cause.message : 'Failed to get collections',
326
+ "QUERY_FAILED",
327
+ cause instanceof Error ? cause.message : "Failed to get collections",
326
328
  cause
327
329
  );
328
330
  }
@@ -331,13 +333,13 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
331
333
  async getContexts(): Promise<StoreResult<ContextRow[]>> {
332
334
  try {
333
335
  const db = this.ensureOpen();
334
- const rows = db.query<DbContextRow, []>('SELECT * FROM contexts').all();
336
+ const rows = db.query<DbContextRow, []>("SELECT * FROM contexts").all();
335
337
 
336
338
  return ok(rows.map(mapContextRow));
337
339
  } catch (cause) {
338
340
  return err(
339
- 'QUERY_FAILED',
340
- cause instanceof Error ? cause.message : 'Failed to get contexts',
341
+ "QUERY_FAILED",
342
+ cause instanceof Error ? cause.message : "Failed to get contexts",
341
343
  cause
342
344
  );
343
345
  }
@@ -404,8 +406,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
404
406
  return ok(docid);
405
407
  } catch (cause) {
406
408
  return err(
407
- 'QUERY_FAILED',
408
- cause instanceof Error ? cause.message : 'Failed to upsert document',
409
+ "QUERY_FAILED",
410
+ cause instanceof Error ? cause.message : "Failed to upsert document",
409
411
  cause
410
412
  );
411
413
  }
@@ -419,15 +421,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
419
421
  const db = this.ensureOpen();
420
422
  const row = db
421
423
  .query<DbDocumentRow, [string, string]>(
422
- 'SELECT * FROM documents WHERE collection = ? AND rel_path = ?'
424
+ "SELECT * FROM documents WHERE collection = ? AND rel_path = ?"
423
425
  )
424
426
  .get(collection, relPath);
425
427
 
426
428
  return ok(row ? mapDocumentRow(row) : null);
427
429
  } catch (cause) {
428
430
  return err(
429
- 'QUERY_FAILED',
430
- cause instanceof Error ? cause.message : 'Failed to get document',
431
+ "QUERY_FAILED",
432
+ cause instanceof Error ? cause.message : "Failed to get document",
431
433
  cause
432
434
  );
433
435
  }
@@ -440,17 +442,17 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
440
442
  const db = this.ensureOpen();
441
443
  const row = db
442
444
  .query<DbDocumentRow, [string]>(
443
- 'SELECT * FROM documents WHERE docid = ?'
445
+ "SELECT * FROM documents WHERE docid = ?"
444
446
  )
445
447
  .get(docid);
446
448
 
447
449
  return ok(row ? mapDocumentRow(row) : null);
448
450
  } catch (cause) {
449
451
  return err(
450
- 'QUERY_FAILED',
452
+ "QUERY_FAILED",
451
453
  cause instanceof Error
452
454
  ? cause.message
453
- : 'Failed to get document by docid',
455
+ : "Failed to get document by docid",
454
456
  cause
455
457
  );
456
458
  }
@@ -462,16 +464,16 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
462
464
  try {
463
465
  const db = this.ensureOpen();
464
466
  const row = db
465
- .query<DbDocumentRow, [string]>('SELECT * FROM documents WHERE uri = ?')
467
+ .query<DbDocumentRow, [string]>("SELECT * FROM documents WHERE uri = ?")
466
468
  .get(uri);
467
469
 
468
470
  return ok(row ? mapDocumentRow(row) : null);
469
471
  } catch (cause) {
470
472
  return err(
471
- 'QUERY_FAILED',
473
+ "QUERY_FAILED",
472
474
  cause instanceof Error
473
475
  ? cause.message
474
- : 'Failed to get document by uri',
476
+ : "Failed to get document by uri",
475
477
  cause
476
478
  );
477
479
  }
@@ -486,16 +488,16 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
486
488
  const rows = collection
487
489
  ? db
488
490
  .query<DbDocumentRow, [string]>(
489
- 'SELECT * FROM documents WHERE collection = ?'
491
+ "SELECT * FROM documents WHERE collection = ?"
490
492
  )
491
493
  .all(collection)
492
- : db.query<DbDocumentRow, []>('SELECT * FROM documents').all();
494
+ : db.query<DbDocumentRow, []>("SELECT * FROM documents").all();
493
495
 
494
496
  return ok(rows.map(mapDocumentRow));
495
497
  } catch (cause) {
496
498
  return err(
497
- 'QUERY_FAILED',
498
- cause instanceof Error ? cause.message : 'Failed to list documents',
499
+ "QUERY_FAILED",
500
+ cause instanceof Error ? cause.message : "Failed to list documents",
499
501
  cause
500
502
  );
501
503
  }
@@ -514,12 +516,12 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
514
516
  const countRow = collection
515
517
  ? db
516
518
  .query<{ count: number }, [string]>(
517
- 'SELECT COUNT(*) as count FROM documents WHERE collection = ?'
519
+ "SELECT COUNT(*) as count FROM documents WHERE collection = ?"
518
520
  )
519
521
  .get(collection)
520
522
  : db
521
523
  .query<{ count: number }, []>(
522
- 'SELECT COUNT(*) as count FROM documents'
524
+ "SELECT COUNT(*) as count FROM documents"
523
525
  )
524
526
  .get();
525
527
 
@@ -529,20 +531,20 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
529
531
  const rows = collection
530
532
  ? db
531
533
  .query<DbDocumentRow, [string, number, number]>(
532
- 'SELECT * FROM documents WHERE collection = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?'
534
+ "SELECT * FROM documents WHERE collection = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?"
533
535
  )
534
536
  .all(collection, limit, offset)
535
537
  : db
536
538
  .query<DbDocumentRow, [number, number]>(
537
- 'SELECT * FROM documents ORDER BY updated_at DESC LIMIT ? OFFSET ?'
539
+ "SELECT * FROM documents ORDER BY updated_at DESC LIMIT ? OFFSET ?"
538
540
  )
539
541
  .all(limit, offset);
540
542
 
541
543
  return ok({ documents: rows.map(mapDocumentRow), total });
542
544
  } catch (cause) {
543
545
  return err(
544
- 'QUERY_FAILED',
545
- cause instanceof Error ? cause.message : 'Failed to list documents',
546
+ "QUERY_FAILED",
547
+ cause instanceof Error ? cause.message : "Failed to list documents",
546
548
  cause
547
549
  );
548
550
  }
@@ -559,7 +561,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
559
561
  return ok(0);
560
562
  }
561
563
 
562
- const placeholders = relPaths.map(() => '?').join(',');
564
+ const placeholders = relPaths.map(() => "?").join(",");
563
565
  const result = db.run(
564
566
  `UPDATE documents SET active = 0, updated_at = datetime('now')
565
567
  WHERE collection = ? AND rel_path IN (${placeholders})`,
@@ -569,10 +571,10 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
569
571
  return ok(result.changes);
570
572
  } catch (cause) {
571
573
  return err(
572
- 'QUERY_FAILED',
574
+ "QUERY_FAILED",
573
575
  cause instanceof Error
574
576
  ? cause.message
575
- : 'Failed to mark documents inactive',
577
+ : "Failed to mark documents inactive",
576
578
  cause
577
579
  );
578
580
  }
@@ -599,8 +601,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
599
601
  return ok(undefined);
600
602
  } catch (cause) {
601
603
  return err(
602
- 'QUERY_FAILED',
603
- cause instanceof Error ? cause.message : 'Failed to upsert content',
604
+ "QUERY_FAILED",
605
+ cause instanceof Error ? cause.message : "Failed to upsert content",
604
606
  cause
605
607
  );
606
608
  }
@@ -612,15 +614,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
612
614
 
613
615
  const row = db
614
616
  .query<{ markdown: string }, [string]>(
615
- 'SELECT markdown FROM content WHERE mirror_hash = ?'
617
+ "SELECT markdown FROM content WHERE mirror_hash = ?"
616
618
  )
617
619
  .get(mirrorHash);
618
620
 
619
621
  return ok(row?.markdown ?? null);
620
622
  } catch (cause) {
621
623
  return err(
622
- 'QUERY_FAILED',
623
- cause instanceof Error ? cause.message : 'Failed to get content',
624
+ "QUERY_FAILED",
625
+ cause instanceof Error ? cause.message : "Failed to get content",
624
626
  cause
625
627
  );
626
628
  }
@@ -639,7 +641,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
639
641
 
640
642
  const transaction = db.transaction(() => {
641
643
  // Delete existing chunks for this hash
642
- db.run('DELETE FROM content_chunks WHERE mirror_hash = ?', [
644
+ db.run("DELETE FROM content_chunks WHERE mirror_hash = ?", [
643
645
  mirrorHash,
644
646
  ]);
645
647
 
@@ -667,8 +669,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
667
669
  return ok(undefined);
668
670
  } catch (cause) {
669
671
  return err(
670
- 'QUERY_FAILED',
671
- cause instanceof Error ? cause.message : 'Failed to upsert chunks',
672
+ "QUERY_FAILED",
673
+ cause instanceof Error ? cause.message : "Failed to upsert chunks",
672
674
  cause
673
675
  );
674
676
  }
@@ -680,15 +682,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
680
682
 
681
683
  const rows = db
682
684
  .query<DbChunkRow, [string]>(
683
- 'SELECT * FROM content_chunks WHERE mirror_hash = ? ORDER BY seq'
685
+ "SELECT * FROM content_chunks WHERE mirror_hash = ? ORDER BY seq"
684
686
  )
685
687
  .all(mirrorHash);
686
688
 
687
689
  return ok(rows.map(mapChunkRow));
688
690
  } catch (cause) {
689
691
  return err(
690
- 'QUERY_FAILED',
691
- cause instanceof Error ? cause.message : 'Failed to get chunks',
692
+ "QUERY_FAILED",
693
+ cause instanceof Error ? cause.message : "Failed to get chunks",
692
694
  cause
693
695
  );
694
696
  }
@@ -721,7 +723,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
721
723
  // Batch queries to respect SQLite parameter limit
722
724
  for (let i = 0; i < uniqueHashes.length; i += SQLITE_MAX_PARAMS) {
723
725
  const batch = uniqueHashes.slice(i, i + SQLITE_MAX_PARAMS);
724
- const placeholders = batch.map(() => '?').join(',');
726
+ const placeholders = batch.map(() => "?").join(",");
725
727
  const sql = `SELECT * FROM content_chunks
726
728
  WHERE mirror_hash IN (${placeholders})
727
729
  ORDER BY mirror_hash, seq`;
@@ -739,8 +741,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
739
741
  return ok(result);
740
742
  } catch (cause) {
741
743
  return err(
742
- 'QUERY_FAILED',
743
- cause instanceof Error ? cause.message : 'Failed to get chunks batch',
744
+ "QUERY_FAILED",
745
+ cause instanceof Error ? cause.message : "Failed to get chunks batch",
744
746
  cause
745
747
  );
746
748
  }
@@ -766,7 +768,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
766
768
  d.mirror_hash,
767
769
  0 as seq,
768
770
  bm25(documents_fts) as score,
769
- ${options.snippet ? "snippet(documents_fts, 2, '<mark>', '</mark>', '...', 32) as snippet," : ''}
771
+ ${options.snippet ? "snippet(documents_fts, 2, '<mark>', '</mark>', '...', 32) as snippet," : ""}
770
772
  d.docid,
771
773
  d.uri,
772
774
  d.title,
@@ -780,7 +782,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
780
782
  FROM documents_fts fts
781
783
  JOIN documents d ON d.id = fts.rowid AND d.active = 1
782
784
  WHERE documents_fts MATCH ?
783
- ${options.collection ? 'AND d.collection = ?' : ''}
785
+ ${options.collection ? "AND d.collection = ?" : ""}
784
786
  ORDER BY bm25(documents_fts)
785
787
  LIMIT ?
786
788
  `;
@@ -829,15 +831,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
829
831
  }))
830
832
  );
831
833
  } catch (cause) {
832
- const message = cause instanceof Error ? cause.message : '';
834
+ const message = cause instanceof Error ? cause.message : "";
833
835
  // Detect FTS5 syntax errors and return INVALID_INPUT for consistent handling
834
836
  const isSyntaxError =
835
- message.includes('malformed MATCH') ||
836
- message.includes('fts5: syntax error') ||
837
- message.includes('fts5:');
837
+ message.includes("malformed MATCH") ||
838
+ message.includes("fts5: syntax error") ||
839
+ message.includes("fts5:");
838
840
  return err(
839
- isSyntaxError ? 'INVALID_INPUT' : 'QUERY_FAILED',
840
- message || 'Failed to search FTS',
841
+ isSyntaxError ? "INVALID_INPUT" : "QUERY_FAILED",
842
+ message || "Failed to search FTS",
841
843
  cause
842
844
  );
843
845
  }
@@ -878,13 +880,13 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
878
880
  }
879
881
 
880
882
  // Delete existing FTS entry for this doc
881
- db.run('DELETE FROM documents_fts WHERE rowid = ?', [doc.id]);
883
+ db.run("DELETE FROM documents_fts WHERE rowid = ?", [doc.id]);
882
884
 
883
885
  // Insert new FTS entry if we have content
884
886
  if (doc.markdown) {
885
887
  db.run(
886
- 'INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)',
887
- [doc.id, doc.rel_path, doc.title ?? '', doc.markdown]
888
+ "INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)",
889
+ [doc.id, doc.rel_path, doc.title ?? "", doc.markdown]
888
890
  );
889
891
  }
890
892
  });
@@ -893,8 +895,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
893
895
  return ok(undefined);
894
896
  } catch (cause) {
895
897
  return err(
896
- 'QUERY_FAILED',
897
- cause instanceof Error ? cause.message : 'Failed to sync document FTS',
898
+ "QUERY_FAILED",
899
+ cause instanceof Error ? cause.message : "Failed to sync document FTS",
898
900
  cause
899
901
  );
900
902
  }
@@ -911,7 +913,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
911
913
 
912
914
  const transaction = db.transaction(() => {
913
915
  // Clear FTS table
914
- db.run('DELETE FROM documents_fts');
916
+ db.run("DELETE FROM documents_fts");
915
917
 
916
918
  // Get all active documents with content
917
919
  interface DocWithContent {
@@ -932,11 +934,11 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
932
934
 
933
935
  // Insert FTS entries
934
936
  const stmt = db.prepare(
935
- 'INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)'
937
+ "INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)"
936
938
  );
937
939
 
938
940
  for (const doc of docs) {
939
- stmt.run(doc.id, doc.rel_path, doc.title ?? '', doc.markdown);
941
+ stmt.run(doc.id, doc.rel_path, doc.title ?? "", doc.markdown);
940
942
  count++;
941
943
  }
942
944
  });
@@ -945,10 +947,10 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
945
947
  return ok(count);
946
948
  } catch (cause) {
947
949
  return err(
948
- 'QUERY_FAILED',
950
+ "QUERY_FAILED",
949
951
  cause instanceof Error
950
952
  ? cause.message
951
- : 'Failed to rebuild documents FTS',
953
+ : "Failed to rebuild documents FTS",
952
954
  cause
953
955
  );
954
956
  }
@@ -972,14 +974,14 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
972
974
 
973
975
  const docs = db
974
976
  .query<DocInfo, [string]>(
975
- 'SELECT id, rel_path, title FROM documents WHERE mirror_hash = ? AND active = 1'
977
+ "SELECT id, rel_path, title FROM documents WHERE mirror_hash = ? AND active = 1"
976
978
  )
977
979
  .all(mirrorHash);
978
980
 
979
981
  // Get content
980
982
  const content = db
981
983
  .query<{ markdown: string }, [string]>(
982
- 'SELECT markdown FROM content WHERE mirror_hash = ?'
984
+ "SELECT markdown FROM content WHERE mirror_hash = ?"
983
985
  )
984
986
  .get(mirrorHash);
985
987
 
@@ -989,10 +991,10 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
989
991
 
990
992
  // Update FTS for each document using this hash
991
993
  for (const doc of docs) {
992
- db.run('DELETE FROM documents_fts WHERE rowid = ?', [doc.id]);
994
+ db.run("DELETE FROM documents_fts WHERE rowid = ?", [doc.id]);
993
995
  db.run(
994
- 'INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)',
995
- [doc.id, doc.rel_path, doc.title ?? '', content.markdown]
996
+ "INSERT INTO documents_fts (rowid, filepath, title, body) VALUES (?, ?, ?, ?)",
997
+ [doc.id, doc.rel_path, doc.title ?? "", content.markdown]
996
998
  );
997
999
  }
998
1000
  });
@@ -1001,8 +1003,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1001
1003
  return ok(undefined);
1002
1004
  } catch (cause) {
1003
1005
  return err(
1004
- 'QUERY_FAILED',
1005
- cause instanceof Error ? cause.message : 'Failed to rebuild FTS',
1006
+ "QUERY_FAILED",
1007
+ cause instanceof Error ? cause.message : "Failed to rebuild FTS",
1006
1008
  cause
1007
1009
  );
1008
1010
  }
@@ -1022,15 +1024,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1022
1024
  "SELECT value FROM schema_meta WHERE key = 'version'"
1023
1025
  )
1024
1026
  .get();
1025
- const version = versionRow?.value ?? '0';
1027
+ const version = versionRow?.value ?? "0";
1026
1028
 
1027
1029
  // Derive indexName from dbPath (basename without extension)
1028
1030
  const indexName =
1029
1031
  this.dbPath
1030
- .split('/')
1032
+ .split("/")
1031
1033
  .pop()
1032
- ?.replace(SQLITE_EXT_REGEX, '')
1033
- ?.replace(INDEX_PREFIX_REGEX, '') || 'default';
1034
+ ?.replace(SQLITE_EXT_REGEX, "")
1035
+ ?.replace(INDEX_PREFIX_REGEX, "") || "default";
1034
1036
 
1035
1037
  // Get collection stats with chunk counts
1036
1038
  interface CollectionStat {
@@ -1082,7 +1084,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1082
1084
  const chunkCount =
1083
1085
  db
1084
1086
  .query<{ count: number }, []>(
1085
- 'SELECT COUNT(*) as count FROM content_chunks'
1087
+ "SELECT COUNT(*) as count FROM content_chunks"
1086
1088
  )
1087
1089
  .get()?.count ?? 0;
1088
1090
 
@@ -1117,7 +1119,7 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1117
1119
  // Last updated (max updated_at from documents)
1118
1120
  const lastUpdatedRow = db
1119
1121
  .query<{ last_updated: string | null }, []>(
1120
- 'SELECT MAX(updated_at) as last_updated FROM documents'
1122
+ "SELECT MAX(updated_at) as last_updated FROM documents"
1121
1123
  )
1122
1124
  .get();
1123
1125
 
@@ -1151,8 +1153,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1151
1153
  });
1152
1154
  } catch (cause) {
1153
1155
  return err(
1154
- 'QUERY_FAILED',
1155
- cause instanceof Error ? cause.message : 'Failed to get status',
1156
+ "QUERY_FAILED",
1157
+ cause instanceof Error ? cause.message : "Failed to get status",
1156
1158
  cause
1157
1159
  );
1158
1160
  }
@@ -1181,8 +1183,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1181
1183
  return ok(undefined);
1182
1184
  } catch (cause) {
1183
1185
  return err(
1184
- 'QUERY_FAILED',
1185
- cause instanceof Error ? cause.message : 'Failed to record error',
1186
+ "QUERY_FAILED",
1187
+ cause instanceof Error ? cause.message : "Failed to record error",
1186
1188
  cause
1187
1189
  );
1188
1190
  }
@@ -1194,15 +1196,15 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1194
1196
 
1195
1197
  const rows = db
1196
1198
  .query<DbIngestErrorRow, [number]>(
1197
- 'SELECT * FROM ingest_errors ORDER BY occurred_at DESC LIMIT ?'
1199
+ "SELECT * FROM ingest_errors ORDER BY occurred_at DESC LIMIT ?"
1198
1200
  )
1199
1201
  .all(limit);
1200
1202
 
1201
1203
  return ok(rows.map(mapIngestErrorRow));
1202
1204
  } catch (cause) {
1203
1205
  return err(
1204
- 'QUERY_FAILED',
1205
- cause instanceof Error ? cause.message : 'Failed to get recent errors',
1206
+ "QUERY_FAILED",
1207
+ cause instanceof Error ? cause.message : "Failed to get recent errors",
1206
1208
  cause
1207
1209
  );
1208
1210
  }
@@ -1270,8 +1272,8 @@ export class SqliteAdapter implements StorePort, SqliteDbProvider {
1270
1272
  });
1271
1273
  } catch (cause) {
1272
1274
  return err(
1273
- 'QUERY_FAILED',
1274
- cause instanceof Error ? cause.message : 'Failed to cleanup orphans',
1275
+ "QUERY_FAILED",
1276
+ cause instanceof Error ? cause.message : "Failed to cleanup orphans",
1275
1277
  cause
1276
1278
  );
1277
1279
  }
@@ -1294,7 +1296,7 @@ interface DbCollectionRow {
1294
1296
  }
1295
1297
 
1296
1298
  interface DbContextRow {
1297
- scope_type: 'global' | 'collection' | 'prefix';
1299
+ scope_type: "global" | "collection" | "prefix";
1298
1300
  scope_key: string;
1299
1301
  text: string;
1300
1302
  synced_at: string;