@gmickel/gno 0.7.0 → 0.8.2

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 +32 -25
  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
@@ -5,21 +5,14 @@
5
5
  * @module src/ingestion/sync
6
6
  */
7
7
 
8
- import type { Collection } from '../config/types';
9
- import { getDefaultMimeDetector, type MimeDetector } from '../converters/mime';
10
- import {
11
- type ConversionPipeline,
12
- getDefaultPipeline,
13
- } from '../converters/pipeline';
14
- import { DEFAULT_LIMITS } from '../converters/types';
8
+ import type { Collection } from "../config/types";
15
9
  import type {
16
10
  ChunkInput,
17
11
  DocumentRow,
18
12
  IngestErrorInput,
19
13
  StorePort,
20
14
  StoreResult,
21
- } from '../store/types';
22
- import { defaultChunker } from './chunker';
15
+ } from "../store/types";
23
16
  import type {
24
17
  ChunkerPort,
25
18
  CollectionSyncResult,
@@ -29,9 +22,17 @@ import type {
29
22
  SyncResult,
30
23
  WalkEntry,
31
24
  WalkerPort,
32
- } from './types';
33
- import { collectionToWalkConfig, DEFAULT_CHUNK_PARAMS } from './types';
34
- import { defaultWalker } from './walker';
25
+ } from "./types";
26
+
27
+ import { getDefaultMimeDetector, type MimeDetector } from "../converters/mime";
28
+ import {
29
+ type ConversionPipeline,
30
+ getDefaultPipeline,
31
+ } from "../converters/pipeline";
32
+ import { DEFAULT_LIMITS } from "../converters/types";
33
+ import { defaultChunker } from "./chunker";
34
+ import { collectionToWalkConfig, DEFAULT_CHUNK_PARAMS } from "./types";
35
+ import { defaultWalker } from "./walker";
35
36
 
36
37
  /** Default concurrency for file processing */
37
38
  const DEFAULT_CONCURRENCY = 1;
@@ -52,28 +53,28 @@ function decideAction(
52
53
  ): ProcessDecision {
53
54
  // No existing doc - must process
54
55
  if (!existing) {
55
- return { kind: 'process', reason: 'new file' };
56
+ return { kind: "process", reason: "new file" };
56
57
  }
57
58
 
58
59
  // Source hash changed - must process
59
60
  if (existing.sourceHash !== sourceHash) {
60
- return { kind: 'process', reason: 'content changed' };
61
+ return { kind: "process", reason: "content changed" };
61
62
  }
62
63
 
63
64
  // Source unchanged, but check for repair cases:
64
65
 
65
66
  // 1. Previous conversion failed (mirrorHash is null)
66
67
  if (!existing.mirrorHash) {
67
- return { kind: 'repair', reason: 'previous conversion failed' };
68
+ return { kind: "repair", reason: "previous conversion failed" };
68
69
  }
69
70
 
70
71
  // 2. Document has error recorded
71
72
  if (existing.lastErrorCode) {
72
- return { kind: 'repair', reason: 'previous error recorded' };
73
+ return { kind: "repair", reason: "previous error recorded" };
73
74
  }
74
75
 
75
76
  // All good - skip
76
- return { kind: 'skip', reason: 'unchanged' };
77
+ return { kind: "skip", reason: "unchanged" };
77
78
  }
78
79
 
79
80
  /**
@@ -188,7 +189,7 @@ export class SyncService {
188
189
  * Process a single file through the ingestion pipeline.
189
190
  * All store operations are checked and errors are propagated.
190
191
  */
191
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: file processing with multiple extraction and embedding paths
192
+ // oxlint-disable-next-line max-lines-per-function -- file processing with multiple extraction paths
192
193
  private async processFile(
193
194
  collection: Collection,
194
195
  entry: WalkEntry,
@@ -207,9 +208,9 @@ export class SyncService {
207
208
  const bytes = await Bun.file(entry.absPath).bytes();
208
209
 
209
210
  // 2. Compute sourceHash
210
- const hasher = new Bun.CryptoHasher('sha256');
211
+ const hasher = new Bun.CryptoHasher("sha256");
211
212
  hasher.update(bytes);
212
- const sourceHash = hasher.digest('hex');
213
+ const sourceHash = hasher.digest("hex");
213
214
 
214
215
  // 3. Check existing doc for skip/repair decision
215
216
  const existingResult = await store.getDocument(
@@ -219,8 +220,8 @@ export class SyncService {
219
220
  const existing = existingResult.ok ? existingResult.value : null;
220
221
  const decision = decideAction(existing, sourceHash);
221
222
 
222
- if (decision.kind === 'skip') {
223
- return { relPath: entry.relPath, status: 'unchanged' };
223
+ if (decision.kind === "skip") {
224
+ return { relPath: entry.relPath, status: "unchanged" };
224
225
  }
225
226
 
226
227
  // 4. Detect MIME (bytes is already Uint8Array from Bun.file().bytes())
@@ -268,15 +269,15 @@ export class SyncService {
268
269
  if (!upsertResult.ok) {
269
270
  return {
270
271
  relPath: entry.relPath,
271
- status: 'error',
272
- errorCode: 'STORE_ERROR',
272
+ status: "error",
273
+ errorCode: "STORE_ERROR",
273
274
  errorMessage: upsertResult.error.message,
274
275
  };
275
276
  }
276
277
 
277
278
  return {
278
279
  relPath: entry.relPath,
279
- status: 'error',
280
+ status: "error",
280
281
  errorCode: convertResult.error.code,
281
282
  errorMessage: convertResult.error.message,
282
283
  };
@@ -303,7 +304,7 @@ export class SyncService {
303
304
  lastErrorMessage: undefined,
304
305
  });
305
306
 
306
- const docid = mustOk(docidResult, 'upsertDocument', {
307
+ const docid = mustOk(docidResult, "upsertDocument", {
307
308
  collection: collection.name,
308
309
  relPath: entry.relPath,
309
310
  });
@@ -313,7 +314,7 @@ export class SyncService {
313
314
  artifact.mirrorHash,
314
315
  artifact.markdown
315
316
  );
316
- mustOk(contentResult, 'upsertContent', {
317
+ mustOk(contentResult, "upsertContent", {
317
318
  mirrorHash: artifact.mirrorHash,
318
319
  });
319
320
 
@@ -340,18 +341,18 @@ export class SyncService {
340
341
  artifact.mirrorHash,
341
342
  chunkInputs
342
343
  );
343
- mustOk(chunksResult, 'upsertChunks', {
344
+ mustOk(chunksResult, "upsertChunks", {
344
345
  mirrorHash: artifact.mirrorHash,
345
346
  chunkCount: chunkInputs.length,
346
347
  });
347
348
 
348
349
  // 11. Rebuild FTS for this hash - CHECKED
349
350
  const ftsResult = await store.rebuildFtsForHash(artifact.mirrorHash);
350
- mustOk(ftsResult, 'rebuildFtsForHash', {
351
+ mustOk(ftsResult, "rebuildFtsForHash", {
351
352
  mirrorHash: artifact.mirrorHash,
352
353
  });
353
354
 
354
- const status = existing ? 'updated' : 'added';
355
+ const status = existing ? "updated" : "added";
355
356
  return {
356
357
  relPath: entry.relPath,
357
358
  status,
@@ -359,13 +360,13 @@ export class SyncService {
359
360
  mirrorHash: artifact.mirrorHash,
360
361
  };
361
362
  } catch (error) {
362
- const message = error instanceof Error ? error.message : 'Unknown error';
363
+ const message = error instanceof Error ? error.message : "Unknown error";
363
364
  // Distinguish store errors from other internal errors
364
365
  const isStoreError =
365
- message.startsWith('Store operation failed:') ||
366
+ message.startsWith("Store operation failed:") ||
366
367
  (error instanceof Error &&
367
368
  (error as Error & { context?: unknown }).context !== undefined);
368
- const code = isStoreError ? 'STORE_ERROR' : 'INTERNAL';
369
+ const code = isStoreError ? "STORE_ERROR" : "INTERNAL";
369
370
 
370
371
  // Record internal error to store (best-effort)
371
372
  try {
@@ -403,7 +404,7 @@ export class SyncService {
403
404
 
404
405
  return {
405
406
  relPath: entry.relPath,
406
- status: 'error',
407
+ status: "error",
407
408
  errorCode: code,
408
409
  errorMessage: message,
409
410
  };
@@ -413,7 +414,7 @@ export class SyncService {
413
414
  /**
414
415
  * Sync a single collection.
415
416
  */
416
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: sync orchestration with git integration and progress tracking
417
+ // oxlint-disable-next-line max-lines-per-function -- sync orchestration with git and progress
417
418
  async syncCollection(
418
419
  collection: Collection,
419
420
  store: StorePort,
@@ -443,31 +444,31 @@ export class SyncService {
443
444
  // a previously-included file, that doc SHOULD be marked inactive
444
445
  const seenPaths = new Set<string>();
445
446
  for (const skip of skipped) {
446
- if (skip.reason === 'TOO_LARGE') {
447
+ if (skip.reason === "TOO_LARGE") {
447
448
  seenPaths.add(skip.relPath);
448
449
  }
449
450
  }
450
451
 
451
452
  // 3. Record TOO_LARGE errors and track in seenPaths
452
453
  for (const skip of skipped) {
453
- if (skip.reason === 'TOO_LARGE') {
454
+ if (skip.reason === "TOO_LARGE") {
454
455
  const recordResult = await store.recordError({
455
456
  collection: collection.name,
456
457
  relPath: skip.relPath,
457
- code: 'TOO_LARGE',
458
+ code: "TOO_LARGE",
458
459
  message: `File size ${skip.size} exceeds limit ${maxBytes}`,
459
460
  });
460
461
  // Log failure but continue
461
462
  if (!recordResult.ok) {
462
463
  errors.push({
463
464
  relPath: skip.relPath,
464
- code: 'STORE_ERROR',
465
+ code: "STORE_ERROR",
465
466
  message: `Failed to record error: ${recordResult.error.message}`,
466
467
  });
467
468
  }
468
469
  errors.push({
469
470
  relPath: skip.relPath,
470
- code: 'TOO_LARGE',
471
+ code: "TOO_LARGE",
471
472
  message: `File size ${skip.size} exceeds limit ${maxBytes}`,
472
473
  });
473
474
  }
@@ -499,16 +500,16 @@ export class SyncService {
499
500
  options
500
501
  );
501
502
  switch (result.status) {
502
- case 'added':
503
+ case "added":
503
504
  added += 1;
504
505
  break;
505
- case 'updated':
506
+ case "updated":
506
507
  updated += 1;
507
508
  break;
508
- case 'unchanged':
509
+ case "unchanged":
509
510
  unchanged += 1;
510
511
  break;
511
- case 'error':
512
+ case "error":
512
513
  errored += 1;
513
514
  if (result.errorCode && result.errorMessage) {
514
515
  errors.push({
@@ -530,7 +531,7 @@ export class SyncService {
530
531
  const txResult = await store.withTransaction(runBatch);
531
532
  if (!txResult.ok) {
532
533
  errors.push({
533
- relPath: '(transaction batch)',
534
+ relPath: "(transaction batch)",
534
535
  code: txResult.error.code,
535
536
  message: txResult.error.message,
536
537
  });
@@ -566,16 +567,16 @@ export class SyncService {
566
567
  // Aggregate results
567
568
  for (const result of results) {
568
569
  switch (result.status) {
569
- case 'added':
570
+ case "added":
570
571
  added += 1;
571
572
  break;
572
- case 'updated':
573
+ case "updated":
573
574
  updated += 1;
574
575
  break;
575
- case 'unchanged':
576
+ case "unchanged":
576
577
  unchanged += 1;
577
578
  break;
578
- case 'error':
579
+ case "error":
579
580
  errored += 1;
580
581
  if (result.errorCode && result.errorMessage) {
581
582
  errors.push({
@@ -5,7 +5,7 @@
5
5
  * @module src/ingestion/types
6
6
  */
7
7
 
8
- import type { Collection } from '../config/types';
8
+ import type { Collection } from "../config/types";
9
9
 
10
10
  // ─────────────────────────────────────────────────────────────────────────────
11
11
  // Walker Types
@@ -41,7 +41,7 @@ export interface WalkConfig {
41
41
  export interface SkippedEntry {
42
42
  absPath: string;
43
43
  relPath: string;
44
- reason: 'TOO_LARGE' | 'EXCLUDED';
44
+ reason: "TOO_LARGE" | "EXCLUDED";
45
45
  size?: number;
46
46
  }
47
47
 
@@ -133,11 +133,11 @@ export interface SyncOptions {
133
133
 
134
134
  /** Per-file sync status */
135
135
  export type FileSyncStatus =
136
- | 'added'
137
- | 'updated'
138
- | 'unchanged'
139
- | 'error'
140
- | 'skipped';
136
+ | "added"
137
+ | "updated"
138
+ | "unchanged"
139
+ | "error"
140
+ | "skipped";
141
141
 
142
142
  /** Per-file sync result */
143
143
  export interface FileSyncResult {
@@ -180,9 +180,9 @@ export interface SyncResult {
180
180
 
181
181
  /** Decision for whether to process a file */
182
182
  export type ProcessDecision =
183
- | { kind: 'skip'; reason: string }
184
- | { kind: 'process'; reason: string }
185
- | { kind: 'repair'; reason: string };
183
+ | { kind: "skip"; reason: string }
184
+ | { kind: "process"; reason: string }
185
+ | { kind: "repair"; reason: string };
186
186
 
187
187
  // ─────────────────────────────────────────────────────────────────────────────
188
188
  // Language Detection Types
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  // node:fs/promises - Bun has no realpath equivalent
9
- import { realpath } from 'node:fs/promises';
9
+ import { realpath } from "node:fs/promises";
10
10
  // node:path - Bun has no path manipulation module
11
11
  import {
12
12
  extname,
@@ -15,8 +15,9 @@ import {
15
15
  relative,
16
16
  resolve,
17
17
  sep,
18
- } from 'node:path';
19
- import type { SkippedEntry, WalkConfig, WalkEntry, WalkerPort } from './types';
18
+ } from "node:path";
19
+
20
+ import type { SkippedEntry, WalkConfig, WalkEntry, WalkerPort } from "./types";
20
21
 
21
22
  /**
22
23
  * Regex to detect dangerous patterns with parent directory traversal.
@@ -28,10 +29,10 @@ const DANGEROUS_PATTERN_REGEX = /(?:^|[\\/])\.\./;
28
29
  * Normalize path to POSIX format (forward slashes).
29
30
  */
30
31
  function toPosixPath(path: string): string {
31
- if (sep === '/') {
32
+ if (sep === "/") {
32
33
  return path;
33
34
  }
34
- return path.replaceAll(sep, '/');
35
+ return path.replaceAll(sep, "/");
35
36
  }
36
37
 
37
38
  /**
@@ -40,10 +41,10 @@ function toPosixPath(path: string): string {
40
41
  */
41
42
  function validatePattern(pattern: string): string | null {
42
43
  if (isAbsolute(pattern)) {
43
- return 'Pattern must be relative, not absolute';
44
+ return "Pattern must be relative, not absolute";
44
45
  }
45
46
  if (DANGEROUS_PATTERN_REGEX.test(pattern)) {
46
- return 'Pattern contains dangerous parent directory reference (..)';
47
+ return "Pattern contains dangerous parent directory reference (..)";
47
48
  }
48
49
  return null;
49
50
  }
@@ -63,7 +64,7 @@ async function safeRelPath(
63
64
 
64
65
  // Reject if relative path escapes root
65
66
  // Check for ".." at start followed by separator or end (not just ".." prefix)
66
- if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
67
+ if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
67
68
  return null;
68
69
  }
69
70
 
@@ -88,7 +89,7 @@ async function safeRelPath(
88
89
  * - exclude: ["dist"] matches "dist/bundle.js" and "src/dist/output.js"
89
90
  */
90
91
  function matchesExclude(relPath: string, excludes: string[]): boolean {
91
- const parts = relPath.split('/');
92
+ const parts = relPath.split("/");
92
93
 
93
94
  for (const pattern of excludes) {
94
95
  // Check if any path component matches exactly
@@ -119,7 +120,7 @@ function matchesInclude(relPath: string, include: string[]): boolean {
119
120
  }
120
121
 
121
122
  return include.some((inc) => {
122
- const normalizedInc = inc.startsWith('.')
123
+ const normalizedInc = inc.startsWith(".")
123
124
  ? inc.toLowerCase()
124
125
  : `.${inc.toLowerCase()}`;
125
126
  return ext === normalizedInc;
@@ -178,7 +179,7 @@ export class FileWalker implements WalkerPort {
178
179
  skipped.push({
179
180
  absPath,
180
181
  relPath,
181
- reason: 'EXCLUDED',
182
+ reason: "EXCLUDED",
182
183
  });
183
184
  continue;
184
185
  }
@@ -188,7 +189,7 @@ export class FileWalker implements WalkerPort {
188
189
  skipped.push({
189
190
  absPath,
190
191
  relPath,
191
- reason: 'EXCLUDED',
192
+ reason: "EXCLUDED",
192
193
  });
193
194
  continue;
194
195
  }
@@ -208,7 +209,7 @@ export class FileWalker implements WalkerPort {
208
209
  skipped.push({
209
210
  absPath,
210
211
  relPath,
211
- reason: 'TOO_LARGE',
212
+ reason: "TOO_LARGE",
212
213
  size: stat.size,
213
214
  });
214
215
  continue;