mdcontext 0.0.1 → 0.2.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.
Files changed (337) hide show
  1. package/.changeset/README.md +28 -0
  2. package/.changeset/config.json +11 -0
  3. package/.claude/settings.local.json +25 -0
  4. package/.github/workflows/ci.yml +83 -0
  5. package/.github/workflows/claude-code-review.yml +44 -0
  6. package/.github/workflows/claude.yml +85 -0
  7. package/.github/workflows/release.yml +113 -0
  8. package/.tldrignore +112 -0
  9. package/BACKLOG.md +338 -0
  10. package/CONTRIBUTING.md +186 -0
  11. package/NOTES/NOTES +44 -0
  12. package/README.md +434 -11
  13. package/biome.json +36 -0
  14. package/cspell.config.yaml +14 -0
  15. package/dist/chunk-23UPXDNL.js +3044 -0
  16. package/dist/chunk-2W7MO2DL.js +1366 -0
  17. package/dist/chunk-3NUAZGMA.js +1689 -0
  18. package/dist/chunk-7TOWB2XB.js +366 -0
  19. package/dist/chunk-7XOTOADQ.js +3065 -0
  20. package/dist/chunk-AH2PDM2K.js +3042 -0
  21. package/dist/chunk-BNXWSZ63.js +3742 -0
  22. package/dist/chunk-BTL5DJVU.js +3222 -0
  23. package/dist/chunk-HDHYG7E4.js +104 -0
  24. package/dist/chunk-HLR4KZBP.js +3234 -0
  25. package/dist/chunk-IP3FRFEB.js +1045 -0
  26. package/dist/chunk-KHU56VDO.js +3042 -0
  27. package/dist/chunk-KRYIFLQR.js +88 -0
  28. package/dist/chunk-LBSDNLEM.js +287 -0
  29. package/dist/chunk-MNTQ7HCP.js +2643 -0
  30. package/dist/chunk-MUJELQQ6.js +1387 -0
  31. package/dist/chunk-MXJGMSLV.js +2199 -0
  32. package/dist/chunk-N6QJGC3Z.js +2636 -0
  33. package/dist/chunk-OBELGBPM.js +1713 -0
  34. package/dist/chunk-OT7R5XTA.js +3192 -0
  35. package/dist/chunk-P7X4RA2T.js +106 -0
  36. package/dist/chunk-PIDUQNC2.js +3185 -0
  37. package/dist/chunk-POGCDIH4.js +3187 -0
  38. package/dist/chunk-PSIEOQGZ.js +3043 -0
  39. package/dist/chunk-PVRT3IHA.js +3238 -0
  40. package/dist/chunk-QNN4TT23.js +1430 -0
  41. package/dist/chunk-RE3R45RJ.js +3042 -0
  42. package/dist/chunk-S7E6TFX6.js +803 -0
  43. package/dist/chunk-SG6GLU4U.js +1378 -0
  44. package/dist/chunk-SJCDV2ST.js +274 -0
  45. package/dist/chunk-SYE5XLF3.js +104 -0
  46. package/dist/chunk-T5VLYBZD.js +103 -0
  47. package/dist/chunk-TOQB7VWU.js +3238 -0
  48. package/dist/chunk-VFNMZ4ZQ.js +3228 -0
  49. package/dist/chunk-VVTGZNBT.js +1629 -0
  50. package/dist/chunk-W7Q4RFEV.js +104 -0
  51. package/dist/chunk-XTYYVRLO.js +3190 -0
  52. package/dist/chunk-Y6MDYVJD.js +3063 -0
  53. package/dist/cli/main.d.ts +1 -0
  54. package/dist/cli/main.js +5458 -0
  55. package/dist/index.d.ts +653 -0
  56. package/dist/index.js +79 -0
  57. package/dist/mcp/server.d.ts +1 -0
  58. package/dist/mcp/server.js +472 -0
  59. package/dist/schema-BAWSG7KY.js +22 -0
  60. package/dist/schema-E3QUPL26.js +20 -0
  61. package/dist/schema-EHL7WUT6.js +20 -0
  62. package/docs/019-USAGE.md +625 -0
  63. package/docs/020-current-implementation.md +364 -0
  64. package/docs/021-DOGFOODING-FINDINGS.md +175 -0
  65. package/docs/BACKLOG.md +80 -0
  66. package/docs/CONFIG.md +1123 -0
  67. package/docs/DESIGN.md +439 -0
  68. package/docs/ERRORS.md +383 -0
  69. package/docs/PROJECT.md +88 -0
  70. package/docs/ROADMAP.md +407 -0
  71. package/docs/summarization.md +320 -0
  72. package/docs/test-links.md +9 -0
  73. package/justfile +40 -0
  74. package/package.json +74 -9
  75. package/pnpm-workspace.yaml +5 -0
  76. package/research/INDEX.md +315 -0
  77. package/research/code-review/README.md +90 -0
  78. package/research/code-review/cli-error-handling-review.md +979 -0
  79. package/research/code-review/code-review-validation-report.md +464 -0
  80. package/research/code-review/main-ts-review.md +1128 -0
  81. package/research/config-analysis/01-current-implementation.md +470 -0
  82. package/research/config-analysis/02-strategy-recommendation.md +428 -0
  83. package/research/config-analysis/03-task-candidates.md +715 -0
  84. package/research/config-analysis/033-research-configuration-management.md +828 -0
  85. package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
  86. package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
  87. package/research/config-docs/SUMMARY.md +357 -0
  88. package/research/config-docs/TEST-RESULTS.md +776 -0
  89. package/research/config-docs/TODO.md +542 -0
  90. package/research/config-docs/analysis.md +744 -0
  91. package/research/config-docs/fix-validation.md +502 -0
  92. package/research/config-docs/help-audit.md +264 -0
  93. package/research/config-docs/help-system-analysis.md +890 -0
  94. package/research/dogfood/consolidated-tool-evaluation.md +373 -0
  95. package/research/dogfood/strategy-a/a-synthesis.md +184 -0
  96. package/research/dogfood/strategy-a/a1-docs.md +226 -0
  97. package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
  98. package/research/dogfood/strategy-a/a3-llm.md +164 -0
  99. package/research/dogfood/strategy-b/b-synthesis.md +228 -0
  100. package/research/dogfood/strategy-b/b1-architecture.md +207 -0
  101. package/research/dogfood/strategy-b/b2-gaps.md +258 -0
  102. package/research/dogfood/strategy-b/b3-workflows.md +250 -0
  103. package/research/dogfood/strategy-c/c-synthesis.md +451 -0
  104. package/research/dogfood/strategy-c/c1-explorer.md +192 -0
  105. package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
  106. package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
  107. package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
  108. package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
  109. package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
  110. package/research/effect-cli-error-handling.md +845 -0
  111. package/research/effect-errors-as-values.md +943 -0
  112. package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
  113. package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
  114. package/research/errors-task-analysis/embeddings-analysis.md +709 -0
  115. package/research/errors-task-analysis/index-search-analysis.md +812 -0
  116. package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
  117. package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
  118. package/research/issue-review.md +603 -0
  119. package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
  120. package/research/llm-summarization/alternative-providers-2026.md +1428 -0
  121. package/research/llm-summarization/anthropic-2026.md +367 -0
  122. package/research/llm-summarization/claude-cli-integration.md +1706 -0
  123. package/research/llm-summarization/cli-integration-patterns.md +3155 -0
  124. package/research/llm-summarization/openai-2026.md +473 -0
  125. package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
  126. package/research/llm-summarization/opencode-cli-integration.md +1552 -0
  127. package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
  128. package/research/llm-summarization/prototype-results.md +56 -0
  129. package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
  130. package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
  131. package/research/mdcontext-error-analysis.md +521 -0
  132. package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
  133. package/research/mdcontext-pudding/01-index-embed.md +956 -0
  134. package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
  135. package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
  136. package/research/mdcontext-pudding/02-search.md +970 -0
  137. package/research/mdcontext-pudding/03-context.md +779 -0
  138. package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
  139. package/research/mdcontext-pudding/04-tree.md +704 -0
  140. package/research/mdcontext-pudding/05-config.md +1038 -0
  141. package/research/mdcontext-pudding/06-links-summary.txt +87 -0
  142. package/research/mdcontext-pudding/06-links.md +679 -0
  143. package/research/mdcontext-pudding/07-stats.md +693 -0
  144. package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
  145. package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
  146. package/research/mdcontext-pudding/README.md +168 -0
  147. package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
  148. package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
  149. package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
  150. package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
  151. package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
  152. package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
  153. package/research/research-quality-review.md +834 -0
  154. package/research/semantic-search/002-research-embedding-models.md +490 -0
  155. package/research/semantic-search/003-research-rag-alternatives.md +523 -0
  156. package/research/semantic-search/004-research-vector-search.md +841 -0
  157. package/research/semantic-search/032-research-semantic-search.md +427 -0
  158. package/research/semantic-search/embedding-text-analysis.md +156 -0
  159. package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
  160. package/research/semantic-search/query-processing-analysis.md +207 -0
  161. package/research/semantic-search/root-cause-and-solution.md +114 -0
  162. package/research/semantic-search/threshold-validation-report.md +69 -0
  163. package/research/semantic-search/vector-search-analysis.md +63 -0
  164. package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
  165. package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
  166. package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
  167. package/research/task-management-2026/03-lightweight-file-based.md +567 -0
  168. package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
  169. package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
  170. package/research/task-management-2026/linear/02-api-integrations.md +930 -0
  171. package/research/task-management-2026/linear/03-ai-features.md +368 -0
  172. package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
  173. package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
  174. package/research/test-path-issues.md +276 -0
  175. package/review/ALP-76/1-error-type-design.md +962 -0
  176. package/review/ALP-76/2-error-handling-patterns.md +906 -0
  177. package/review/ALP-76/3-error-presentation.md +624 -0
  178. package/review/ALP-76/4-test-coverage.md +625 -0
  179. package/review/ALP-76/5-migration-completeness.md +440 -0
  180. package/review/ALP-76/6-effect-best-practices.md +755 -0
  181. package/scripts/apply-branch-protection.sh +47 -0
  182. package/scripts/branch-protection-templates.json +79 -0
  183. package/scripts/prototype-summarization.ts +346 -0
  184. package/scripts/rebuild-hnswlib.js +58 -0
  185. package/scripts/setup-branch-protection.sh +64 -0
  186. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
  187. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
  188. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
  189. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
  190. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  191. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  192. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
  193. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
  194. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
  195. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
  196. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
  197. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
  198. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
  199. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
  200. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
  201. package/src/cli/argv-preprocessor.test.ts +210 -0
  202. package/src/cli/argv-preprocessor.ts +202 -0
  203. package/src/cli/cli.test.ts +627 -0
  204. package/src/cli/commands/backlinks.ts +54 -0
  205. package/src/cli/commands/config-cmd.ts +642 -0
  206. package/src/cli/commands/context.ts +285 -0
  207. package/src/cli/commands/duplicates.ts +122 -0
  208. package/src/cli/commands/embeddings.ts +529 -0
  209. package/src/cli/commands/index-cmd.ts +480 -0
  210. package/src/cli/commands/index.ts +16 -0
  211. package/src/cli/commands/links.ts +52 -0
  212. package/src/cli/commands/search.ts +1281 -0
  213. package/src/cli/commands/stats.ts +149 -0
  214. package/src/cli/commands/tree.ts +128 -0
  215. package/src/cli/config-layer.ts +176 -0
  216. package/src/cli/error-handler.test.ts +235 -0
  217. package/src/cli/error-handler.ts +655 -0
  218. package/src/cli/flag-schemas.ts +341 -0
  219. package/src/cli/help.ts +588 -0
  220. package/src/cli/index.ts +9 -0
  221. package/src/cli/main.ts +435 -0
  222. package/src/cli/options.ts +41 -0
  223. package/src/cli/shared-error-handling.ts +199 -0
  224. package/src/cli/typo-suggester.test.ts +105 -0
  225. package/src/cli/typo-suggester.ts +130 -0
  226. package/src/cli/utils.ts +259 -0
  227. package/src/config/file-provider.test.ts +320 -0
  228. package/src/config/file-provider.ts +273 -0
  229. package/src/config/index.ts +72 -0
  230. package/src/config/integration.test.ts +667 -0
  231. package/src/config/precedence.test.ts +277 -0
  232. package/src/config/precedence.ts +451 -0
  233. package/src/config/schema.test.ts +414 -0
  234. package/src/config/schema.ts +603 -0
  235. package/src/config/service.test.ts +320 -0
  236. package/src/config/service.ts +243 -0
  237. package/src/config/testing.test.ts +264 -0
  238. package/src/config/testing.ts +110 -0
  239. package/src/core/index.ts +1 -0
  240. package/src/core/types.ts +113 -0
  241. package/src/duplicates/detector.test.ts +183 -0
  242. package/src/duplicates/detector.ts +414 -0
  243. package/src/duplicates/index.ts +18 -0
  244. package/src/embeddings/embedding-namespace.test.ts +300 -0
  245. package/src/embeddings/embedding-namespace.ts +947 -0
  246. package/src/embeddings/heading-boost.test.ts +222 -0
  247. package/src/embeddings/hnsw-build-options.test.ts +198 -0
  248. package/src/embeddings/hyde.test.ts +272 -0
  249. package/src/embeddings/hyde.ts +264 -0
  250. package/src/embeddings/index.ts +10 -0
  251. package/src/embeddings/openai-provider.ts +414 -0
  252. package/src/embeddings/pricing.json +22 -0
  253. package/src/embeddings/provider-constants.ts +204 -0
  254. package/src/embeddings/provider-errors.test.ts +967 -0
  255. package/src/embeddings/provider-errors.ts +565 -0
  256. package/src/embeddings/provider-factory.test.ts +240 -0
  257. package/src/embeddings/provider-factory.ts +225 -0
  258. package/src/embeddings/provider-integration.test.ts +788 -0
  259. package/src/embeddings/query-preprocessing.test.ts +187 -0
  260. package/src/embeddings/semantic-search-threshold.test.ts +508 -0
  261. package/src/embeddings/semantic-search.ts +1270 -0
  262. package/src/embeddings/types.ts +359 -0
  263. package/src/embeddings/vector-store.ts +708 -0
  264. package/src/embeddings/voyage-provider.ts +313 -0
  265. package/src/errors/errors.test.ts +845 -0
  266. package/src/errors/index.ts +533 -0
  267. package/src/index/ignore-patterns.test.ts +354 -0
  268. package/src/index/ignore-patterns.ts +305 -0
  269. package/src/index/index.ts +4 -0
  270. package/src/index/indexer.ts +684 -0
  271. package/src/index/storage.ts +260 -0
  272. package/src/index/types.ts +147 -0
  273. package/src/index/watcher.ts +189 -0
  274. package/src/index.ts +30 -0
  275. package/src/integration/search-keyword.test.ts +678 -0
  276. package/src/mcp/server.ts +612 -0
  277. package/src/parser/index.ts +1 -0
  278. package/src/parser/parser.test.ts +291 -0
  279. package/src/parser/parser.ts +394 -0
  280. package/src/parser/section-filter.test.ts +277 -0
  281. package/src/parser/section-filter.ts +392 -0
  282. package/src/search/__tests__/hybrid-search.test.ts +650 -0
  283. package/src/search/bm25-store.ts +366 -0
  284. package/src/search/cross-encoder.test.ts +253 -0
  285. package/src/search/cross-encoder.ts +406 -0
  286. package/src/search/fuzzy-search.test.ts +419 -0
  287. package/src/search/fuzzy-search.ts +273 -0
  288. package/src/search/hybrid-search.ts +448 -0
  289. package/src/search/path-matcher.test.ts +276 -0
  290. package/src/search/path-matcher.ts +33 -0
  291. package/src/search/query-parser.test.ts +260 -0
  292. package/src/search/query-parser.ts +319 -0
  293. package/src/search/searcher.test.ts +280 -0
  294. package/src/search/searcher.ts +724 -0
  295. package/src/search/wink-bm25.d.ts +30 -0
  296. package/src/summarization/cli-providers/claude.ts +202 -0
  297. package/src/summarization/cli-providers/detection.test.ts +273 -0
  298. package/src/summarization/cli-providers/detection.ts +118 -0
  299. package/src/summarization/cli-providers/index.ts +8 -0
  300. package/src/summarization/cost.test.ts +139 -0
  301. package/src/summarization/cost.ts +102 -0
  302. package/src/summarization/error-handler.test.ts +127 -0
  303. package/src/summarization/error-handler.ts +111 -0
  304. package/src/summarization/index.ts +102 -0
  305. package/src/summarization/pipeline.test.ts +498 -0
  306. package/src/summarization/pipeline.ts +231 -0
  307. package/src/summarization/prompts.test.ts +269 -0
  308. package/src/summarization/prompts.ts +133 -0
  309. package/src/summarization/provider-factory.test.ts +396 -0
  310. package/src/summarization/provider-factory.ts +178 -0
  311. package/src/summarization/types.ts +184 -0
  312. package/src/summarize/budget-bugs.test.ts +620 -0
  313. package/src/summarize/formatters.ts +419 -0
  314. package/src/summarize/index.ts +20 -0
  315. package/src/summarize/summarizer.test.ts +275 -0
  316. package/src/summarize/summarizer.ts +597 -0
  317. package/src/summarize/verify-bugs.test.ts +238 -0
  318. package/src/types/huggingface-transformers.d.ts +66 -0
  319. package/src/utils/index.ts +1 -0
  320. package/src/utils/tokens.test.ts +142 -0
  321. package/src/utils/tokens.ts +186 -0
  322. package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
  323. package/tests/fixtures/cli/.mdcontext/config.json +8 -0
  324. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  325. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  326. package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
  327. package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
  328. package/tests/fixtures/cli/.mdcontext/indexes/sections.json +247 -0
  329. package/tests/fixtures/cli/README.md +9 -0
  330. package/tests/fixtures/cli/api-reference.md +11 -0
  331. package/tests/fixtures/cli/getting-started.md +11 -0
  332. package/tests/integration/embed-index.test.ts +712 -0
  333. package/tests/integration/search-context.test.ts +469 -0
  334. package/tests/integration/search-semantic.test.ts +522 -0
  335. package/tsconfig.json +26 -0
  336. package/vitest.config.ts +16 -0
  337. package/vitest.setup.ts +12 -0
@@ -0,0 +1,533 @@
1
+ /**
2
+ * Centralized error types for mdcontext
3
+ *
4
+ * This module defines all domain errors using Effect's Data.TaggedError pattern.
5
+ * Each error has a unique `_tag` discriminant that enables:
6
+ * - Exhaustive error handling with `catchTag` / `catchTags`
7
+ * - Type-safe error composition in Effect pipelines
8
+ * - Pattern matching for user-friendly error messages at CLI boundary
9
+ *
10
+ * ## Error Message Convention
11
+ *
12
+ * The `message` field in errors should contain **technical details** from the
13
+ * underlying operation, NOT user-facing formatted messages.
14
+ *
15
+ * **Good (technical):**
16
+ * ```typescript
17
+ * new FileReadError({
18
+ * path: '/path/to/file',
19
+ * message: e.message, // e.g., "ENOENT: no such file or directory"
20
+ * cause: e,
21
+ * })
22
+ * ```
23
+ *
24
+ * **Bad (user-facing):**
25
+ * ```typescript
26
+ * new FileReadError({
27
+ * path: '/path/to/file',
28
+ * message: 'Cannot read file. Please check permissions.', // NO!
29
+ * })
30
+ * ```
31
+ *
32
+ * User-friendly messages are generated at the CLI boundary by the error handler
33
+ * in `src/cli/error-handler.ts`. This separation enables:
34
+ * - i18n/localization in the future
35
+ * - Testing error data without string matching
36
+ * - Consistent formatting in one place
37
+ *
38
+ * ## Error Taxonomy
39
+ *
40
+ * - File System: FileReadError, FileWriteError, DirectoryCreateError, DirectoryWalkError
41
+ * - Parsing: ParseError (for markdown parsing failures)
42
+ * - API: ApiKeyMissingError, ApiKeyInvalidError
43
+ * - Embeddings: EmbeddingError (rate limits, quota, network failures)
44
+ * - Index: IndexNotFoundError, IndexCorruptedError, IndexBuildError
45
+ * - Search: DocumentNotFoundError, EmbeddingsNotFoundError
46
+ * - Vector Store: VectorStoreError
47
+ * - Config: ConfigError
48
+ * - CLI: CliValidationError
49
+ *
50
+ * ## Usage
51
+ *
52
+ * ```typescript
53
+ * import { FileReadError, ApiKeyMissingError } from './errors/index.js'
54
+ * import { Effect } from 'effect'
55
+ *
56
+ * const program = Effect.gen(function* () {
57
+ * // ... operations that may fail
58
+ * }).pipe(
59
+ * Effect.catchTag('FileReadError', (e) => ...),
60
+ * Effect.catchTag('ApiKeyMissingError', (e) => ...)
61
+ * )
62
+ * ```
63
+ */
64
+
65
+ import { Data } from 'effect'
66
+
67
+ // ============================================================================
68
+ // Error Codes
69
+ // ============================================================================
70
+
71
+ /**
72
+ * Standardized error codes for programmatic handling.
73
+ *
74
+ * Error codes enable:
75
+ * - Scripting and automation (check error codes in CI/CD)
76
+ * - Machine-readable error handling without parsing messages
77
+ * - Stable identifiers that don't change when messages are updated
78
+ *
79
+ * Naming convention: E{category}{number}
80
+ * - E1xx: File system errors
81
+ * - E2xx: Parse errors
82
+ * - E3xx: API/authentication errors
83
+ * - E4xx: Index errors
84
+ * - E5xx: Search errors
85
+ * - E6xx: Vector store errors
86
+ * - E7xx: Config errors
87
+ * - E8xx: Watch errors
88
+ * - E9xx: CLI errors
89
+ */
90
+ export const ErrorCode = {
91
+ // File system errors (E1xx)
92
+ FILE_READ: 'E100',
93
+ FILE_WRITE: 'E101',
94
+ DIRECTORY_CREATE: 'E102',
95
+ DIRECTORY_WALK: 'E103',
96
+
97
+ // Parse errors (E2xx)
98
+ PARSE: 'E200',
99
+
100
+ // API/authentication errors (E3xx)
101
+ API_KEY_MISSING: 'E300',
102
+ API_KEY_INVALID: 'E301',
103
+ EMBEDDING_RATE_LIMIT: 'E310',
104
+ EMBEDDING_QUOTA: 'E311',
105
+ EMBEDDING_NETWORK: 'E312',
106
+ EMBEDDING_MODEL: 'E313',
107
+ EMBEDDING_UNKNOWN: 'E319',
108
+
109
+ // Index errors (E4xx)
110
+ INDEX_NOT_FOUND: 'E400',
111
+ INDEX_CORRUPTED: 'E401',
112
+ INDEX_BUILD: 'E402',
113
+
114
+ // Search errors (E5xx)
115
+ DOCUMENT_NOT_FOUND: 'E500',
116
+ EMBEDDINGS_NOT_FOUND: 'E501',
117
+
118
+ // Vector store errors (E6xx)
119
+ VECTOR_STORE: 'E600',
120
+ DIMENSION_MISMATCH: 'E601',
121
+
122
+ // Config errors (E7xx)
123
+ CONFIG: 'E700',
124
+
125
+ // Watch errors (E8xx)
126
+ WATCH: 'E800',
127
+
128
+ // CLI errors (E9xx)
129
+ CLI_VALIDATION: 'E900',
130
+ } as const
131
+
132
+ export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode]
133
+
134
+ // ============================================================================
135
+ // File System Errors
136
+ // ============================================================================
137
+
138
+ /**
139
+ * Error reading a file from the filesystem
140
+ */
141
+ export class FileReadError extends Data.TaggedError('FileReadError')<{
142
+ readonly path: string
143
+ readonly message: string
144
+ readonly cause?: unknown
145
+ }> {
146
+ get code(): typeof ErrorCode.FILE_READ {
147
+ return ErrorCode.FILE_READ
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Error writing a file to the filesystem
153
+ */
154
+ export class FileWriteError extends Data.TaggedError('FileWriteError')<{
155
+ readonly path: string
156
+ readonly message: string
157
+ readonly cause?: unknown
158
+ }> {
159
+ get code(): typeof ErrorCode.FILE_WRITE {
160
+ return ErrorCode.FILE_WRITE
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Error creating a directory
166
+ */
167
+ export class DirectoryCreateError extends Data.TaggedError(
168
+ 'DirectoryCreateError',
169
+ )<{
170
+ readonly path: string
171
+ readonly message: string
172
+ readonly cause?: unknown
173
+ }> {
174
+ get code(): typeof ErrorCode.DIRECTORY_CREATE {
175
+ return ErrorCode.DIRECTORY_CREATE
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Error walking/traversing a directory tree
181
+ */
182
+ export class DirectoryWalkError extends Data.TaggedError('DirectoryWalkError')<{
183
+ readonly path: string
184
+ readonly message: string
185
+ readonly cause?: unknown
186
+ }> {
187
+ get code(): typeof ErrorCode.DIRECTORY_WALK {
188
+ return ErrorCode.DIRECTORY_WALK
189
+ }
190
+ }
191
+
192
+ // ============================================================================
193
+ // Parse Errors
194
+ // ============================================================================
195
+
196
+ /**
197
+ * Error parsing a markdown document
198
+ */
199
+ export class ParseError extends Data.TaggedError('ParseError')<{
200
+ readonly message: string
201
+ readonly path?: string
202
+ readonly line?: number
203
+ readonly column?: number
204
+ readonly cause?: unknown
205
+ }> {
206
+ get code(): typeof ErrorCode.PARSE {
207
+ return ErrorCode.PARSE
208
+ }
209
+ }
210
+
211
+ // ============================================================================
212
+ // API Key Errors
213
+ // ============================================================================
214
+
215
+ /**
216
+ * API key is not set in environment
217
+ */
218
+ export class ApiKeyMissingError extends Data.TaggedError('ApiKeyMissingError')<{
219
+ readonly provider: string
220
+ readonly envVar: string
221
+ }> {
222
+ get code(): typeof ErrorCode.API_KEY_MISSING {
223
+ return ErrorCode.API_KEY_MISSING
224
+ }
225
+ get message(): string {
226
+ return `${this.envVar} not set`
227
+ }
228
+ }
229
+
230
+ /**
231
+ * API key was rejected by the provider
232
+ */
233
+ export class ApiKeyInvalidError extends Data.TaggedError('ApiKeyInvalidError')<{
234
+ readonly provider: string
235
+ readonly details?: string
236
+ }> {
237
+ get code(): typeof ErrorCode.API_KEY_INVALID {
238
+ return ErrorCode.API_KEY_INVALID
239
+ }
240
+ get message(): string {
241
+ return this.details ?? `Invalid API key for ${this.provider}`
242
+ }
243
+ }
244
+
245
+ // ============================================================================
246
+ // Embedding Errors
247
+ // ============================================================================
248
+
249
+ /**
250
+ * Embedding operation failure causes
251
+ */
252
+ export type EmbeddingErrorCause =
253
+ | 'RateLimit'
254
+ | 'QuotaExceeded'
255
+ | 'Network'
256
+ | 'ModelError'
257
+ | 'Unknown'
258
+
259
+ /**
260
+ * Error generating embeddings
261
+ */
262
+ export class EmbeddingError extends Data.TaggedError('EmbeddingError')<{
263
+ readonly reason: EmbeddingErrorCause
264
+ readonly message: string
265
+ readonly provider?: string
266
+ readonly cause?: unknown
267
+ }> {
268
+ get code(): ErrorCodeValue {
269
+ switch (this.reason) {
270
+ case 'RateLimit':
271
+ return ErrorCode.EMBEDDING_RATE_LIMIT
272
+ case 'QuotaExceeded':
273
+ return ErrorCode.EMBEDDING_QUOTA
274
+ case 'Network':
275
+ return ErrorCode.EMBEDDING_NETWORK
276
+ case 'ModelError':
277
+ return ErrorCode.EMBEDDING_MODEL
278
+ default:
279
+ // 'Unknown' and any future unknown reasons
280
+ return ErrorCode.EMBEDDING_UNKNOWN
281
+ }
282
+ }
283
+ }
284
+
285
+ // ============================================================================
286
+ // Index Errors
287
+ // ============================================================================
288
+
289
+ /**
290
+ * Index does not exist at the expected location
291
+ */
292
+ export class IndexNotFoundError extends Data.TaggedError('IndexNotFoundError')<{
293
+ readonly path: string
294
+ }> {
295
+ get code(): typeof ErrorCode.INDEX_NOT_FOUND {
296
+ return ErrorCode.INDEX_NOT_FOUND
297
+ }
298
+ get message(): string {
299
+ return `Index not found at ${this.path}`
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Index exists but is corrupted or invalid
305
+ */
306
+ export class IndexCorruptedError extends Data.TaggedError(
307
+ 'IndexCorruptedError',
308
+ )<{
309
+ readonly path: string
310
+ readonly reason: 'InvalidJson' | 'VersionMismatch' | 'MissingData' | 'Unknown'
311
+ readonly details?: string
312
+ }> {
313
+ get code(): typeof ErrorCode.INDEX_CORRUPTED {
314
+ return ErrorCode.INDEX_CORRUPTED
315
+ }
316
+ get message(): string {
317
+ return `Index corrupted at ${this.path}: ${this.reason}`
318
+ }
319
+ }
320
+
321
+ /**
322
+ * Error building/updating the index
323
+ */
324
+ export class IndexBuildError extends Data.TaggedError('IndexBuildError')<{
325
+ readonly path: string
326
+ readonly message: string
327
+ readonly cause?: unknown
328
+ }> {
329
+ get code(): typeof ErrorCode.INDEX_BUILD {
330
+ return ErrorCode.INDEX_BUILD
331
+ }
332
+ }
333
+
334
+ // ============================================================================
335
+ // Search Errors
336
+ // ============================================================================
337
+
338
+ /**
339
+ * Document not found in the index
340
+ */
341
+ export class DocumentNotFoundError extends Data.TaggedError(
342
+ 'DocumentNotFoundError',
343
+ )<{
344
+ readonly path: string
345
+ readonly indexPath?: string
346
+ }> {
347
+ get code(): typeof ErrorCode.DOCUMENT_NOT_FOUND {
348
+ return ErrorCode.DOCUMENT_NOT_FOUND
349
+ }
350
+ get message(): string {
351
+ return `Document not found in index: ${this.path}`
352
+ }
353
+ }
354
+
355
+ // ============================================================================
356
+ // Config Errors
357
+ // ============================================================================
358
+
359
+ /**
360
+ * Configuration error with rich context for user-friendly formatting.
361
+ *
362
+ * Fields:
363
+ * - `field`: The config field name (e.g., "index.maxDepth")
364
+ * - `message`: Technical error message
365
+ * - `sourceFile`: Path to the config file where the error occurred
366
+ * - `expectedType`: Expected type (e.g., "number", "boolean")
367
+ * - `actualValue`: The actual invalid value
368
+ * - `validValues`: List of valid values for enum-like fields
369
+ */
370
+ export class ConfigError extends Data.TaggedError('ConfigError')<{
371
+ readonly field?: string
372
+ readonly message: string
373
+ readonly cause?: unknown
374
+ readonly sourceFile?: string
375
+ readonly expectedType?: string
376
+ readonly actualValue?: unknown
377
+ readonly validValues?: readonly string[]
378
+ }> {
379
+ get code(): typeof ErrorCode.CONFIG {
380
+ return ErrorCode.CONFIG
381
+ }
382
+ }
383
+
384
+ // ============================================================================
385
+ // Vector Store Errors
386
+ // ============================================================================
387
+
388
+ /**
389
+ * Error with vector store operations (HNSW index)
390
+ */
391
+ export class VectorStoreError extends Data.TaggedError('VectorStoreError')<{
392
+ readonly operation: 'init' | 'add' | 'search' | 'save' | 'load'
393
+ readonly message: string
394
+ readonly cause?: unknown
395
+ }> {
396
+ get code(): typeof ErrorCode.VECTOR_STORE {
397
+ return ErrorCode.VECTOR_STORE
398
+ }
399
+ }
400
+
401
+ /**
402
+ * Embeddings not found for semantic search
403
+ */
404
+ export class EmbeddingsNotFoundError extends Data.TaggedError(
405
+ 'EmbeddingsNotFoundError',
406
+ )<{
407
+ readonly path: string
408
+ }> {
409
+ get code(): typeof ErrorCode.EMBEDDINGS_NOT_FOUND {
410
+ return ErrorCode.EMBEDDINGS_NOT_FOUND
411
+ }
412
+ get message(): string {
413
+ return `Embeddings not found at ${this.path}. Run 'mdcontext index --embed' first.`
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Embedding dimension mismatch between corpus and current provider.
419
+ *
420
+ * This happens when trying to search a corpus that was created with a different
421
+ * embedding configuration (different dimensions or provider).
422
+ */
423
+ export class DimensionMismatchError extends Data.TaggedError(
424
+ 'DimensionMismatchError',
425
+ )<{
426
+ /** Dimensions stored in the corpus */
427
+ readonly corpusDimensions: number
428
+ /** Dimensions expected by the current provider */
429
+ readonly providerDimensions: number
430
+ /** Provider that created the corpus (e.g., "openai:text-embedding-3-small") */
431
+ readonly corpusProvider?: string
432
+ /** Current provider being used */
433
+ readonly currentProvider?: string
434
+ /** Path to the corpus */
435
+ readonly path: string
436
+ }> {
437
+ get code(): typeof ErrorCode.DIMENSION_MISMATCH {
438
+ return ErrorCode.DIMENSION_MISMATCH
439
+ }
440
+ get message(): string {
441
+ const corpusInfo = this.corpusProvider
442
+ ? `${this.corpusDimensions} (${this.corpusProvider})`
443
+ : `${this.corpusDimensions}`
444
+ const currentInfo = this.currentProvider
445
+ ? `${this.providerDimensions} (${this.currentProvider})`
446
+ : `${this.providerDimensions}`
447
+ return `Embedding dimension mismatch: corpus has ${corpusInfo}, current provider expects ${currentInfo}`
448
+ }
449
+ }
450
+
451
+ // ============================================================================
452
+ // Watch Errors
453
+ // ============================================================================
454
+
455
+ /**
456
+ * File watcher error
457
+ */
458
+ export class WatchError extends Data.TaggedError('WatchError')<{
459
+ readonly path: string
460
+ readonly message: string
461
+ readonly cause?: unknown
462
+ }> {
463
+ get code(): typeof ErrorCode.WATCH {
464
+ return ErrorCode.WATCH
465
+ }
466
+ }
467
+
468
+ // ============================================================================
469
+ // CLI Errors
470
+ // ============================================================================
471
+
472
+ /**
473
+ * CLI validation error (invalid arguments, missing options, etc.)
474
+ */
475
+ export class CliValidationError extends Data.TaggedError('CliValidationError')<{
476
+ readonly message: string
477
+ readonly argument?: string
478
+ readonly expected?: string
479
+ readonly received?: string
480
+ }> {
481
+ get code(): typeof ErrorCode.CLI_VALIDATION {
482
+ return ErrorCode.CLI_VALIDATION
483
+ }
484
+ }
485
+
486
+ // ============================================================================
487
+ // Union Types
488
+ // ============================================================================
489
+
490
+ /**
491
+ * All file system related errors
492
+ */
493
+ export type FileSystemError =
494
+ | FileReadError
495
+ | FileWriteError
496
+ | DirectoryCreateError
497
+ | DirectoryWalkError
498
+
499
+ /**
500
+ * All API-related errors
501
+ */
502
+ export type ApiError = ApiKeyMissingError | ApiKeyInvalidError | EmbeddingError
503
+
504
+ /**
505
+ * All index-related errors
506
+ */
507
+ export type IndexError =
508
+ | IndexNotFoundError
509
+ | IndexCorruptedError
510
+ | IndexBuildError
511
+
512
+ /**
513
+ * All search-related errors
514
+ */
515
+ export type SearchError =
516
+ | DocumentNotFoundError
517
+ | EmbeddingsNotFoundError
518
+ | DimensionMismatchError
519
+
520
+ /**
521
+ * Union of all mdcontext errors
522
+ * Use this for exhaustive error handling at the CLI boundary
523
+ */
524
+ export type MdContextError =
525
+ | FileSystemError
526
+ | ParseError
527
+ | ApiError
528
+ | IndexError
529
+ | SearchError
530
+ | VectorStoreError
531
+ | ConfigError
532
+ | WatchError
533
+ | CliValidationError