mdcontext 0.1.0 → 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 (251) hide show
  1. package/.changeset/config.json +9 -9
  2. package/.claude/settings.local.json +25 -0
  3. package/.github/workflows/claude-code-review.yml +44 -0
  4. package/.github/workflows/claude.yml +85 -0
  5. package/CONTRIBUTING.md +186 -0
  6. package/NOTES/NOTES +44 -0
  7. package/README.md +206 -3
  8. package/biome.json +1 -1
  9. package/dist/chunk-23UPXDNL.js +3044 -0
  10. package/dist/chunk-2W7MO2DL.js +1366 -0
  11. package/dist/chunk-3NUAZGMA.js +1689 -0
  12. package/dist/chunk-7TOWB2XB.js +366 -0
  13. package/dist/chunk-7XOTOADQ.js +3065 -0
  14. package/dist/chunk-AH2PDM2K.js +3042 -0
  15. package/dist/chunk-BNXWSZ63.js +3742 -0
  16. package/dist/chunk-BTL5DJVU.js +3222 -0
  17. package/dist/chunk-HDHYG7E4.js +104 -0
  18. package/dist/chunk-HLR4KZBP.js +3234 -0
  19. package/dist/chunk-IP3FRFEB.js +1045 -0
  20. package/dist/chunk-KHU56VDO.js +3042 -0
  21. package/dist/chunk-KRYIFLQR.js +85 -89
  22. package/dist/chunk-LBSDNLEM.js +287 -0
  23. package/dist/chunk-MNTQ7HCP.js +2643 -0
  24. package/dist/chunk-MUJELQQ6.js +1387 -0
  25. package/dist/chunk-MXJGMSLV.js +2199 -0
  26. package/dist/chunk-N6QJGC3Z.js +2636 -0
  27. package/dist/chunk-OBELGBPM.js +1713 -0
  28. package/dist/chunk-OT7R5XTA.js +3192 -0
  29. package/dist/chunk-P7X4RA2T.js +106 -0
  30. package/dist/chunk-PIDUQNC2.js +3185 -0
  31. package/dist/chunk-POGCDIH4.js +3187 -0
  32. package/dist/chunk-PSIEOQGZ.js +3043 -0
  33. package/dist/chunk-PVRT3IHA.js +3238 -0
  34. package/dist/chunk-QNN4TT23.js +1430 -0
  35. package/dist/chunk-RE3R45RJ.js +3042 -0
  36. package/dist/chunk-S7E6TFX6.js +718 -657
  37. package/dist/chunk-SG6GLU4U.js +1378 -0
  38. package/dist/chunk-SJCDV2ST.js +274 -0
  39. package/dist/chunk-SYE5XLF3.js +104 -0
  40. package/dist/chunk-T5VLYBZD.js +103 -0
  41. package/dist/chunk-TOQB7VWU.js +3238 -0
  42. package/dist/chunk-VFNMZ4ZQ.js +3228 -0
  43. package/dist/chunk-VVTGZNBT.js +1533 -1423
  44. package/dist/chunk-W7Q4RFEV.js +104 -0
  45. package/dist/chunk-XTYYVRLO.js +3190 -0
  46. package/dist/chunk-Y6MDYVJD.js +3063 -0
  47. package/dist/cli/main.js +4072 -629
  48. package/dist/index.d.ts +420 -33
  49. package/dist/index.js +8 -15
  50. package/dist/mcp/server.js +103 -7
  51. package/dist/schema-BAWSG7KY.js +22 -0
  52. package/dist/schema-E3QUPL26.js +20 -0
  53. package/dist/schema-EHL7WUT6.js +20 -0
  54. package/docs/019-USAGE.md +44 -5
  55. package/docs/020-current-implementation.md +8 -8
  56. package/docs/021-DOGFOODING-FINDINGS.md +1 -1
  57. package/docs/CONFIG.md +1123 -0
  58. package/docs/ERRORS.md +383 -0
  59. package/docs/summarization.md +320 -0
  60. package/justfile +40 -0
  61. package/package.json +39 -33
  62. package/research/INDEX.md +315 -0
  63. package/research/code-review/README.md +90 -0
  64. package/research/code-review/cli-error-handling-review.md +979 -0
  65. package/research/code-review/code-review-validation-report.md +464 -0
  66. package/research/code-review/main-ts-review.md +1128 -0
  67. package/research/config-docs/SUMMARY.md +357 -0
  68. package/research/config-docs/TEST-RESULTS.md +776 -0
  69. package/research/config-docs/TODO.md +542 -0
  70. package/research/config-docs/analysis.md +744 -0
  71. package/research/config-docs/fix-validation.md +502 -0
  72. package/research/config-docs/help-audit.md +264 -0
  73. package/research/config-docs/help-system-analysis.md +890 -0
  74. package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
  75. package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
  76. package/research/issue-review.md +603 -0
  77. package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
  78. package/research/llm-summarization/alternative-providers-2026.md +1428 -0
  79. package/research/llm-summarization/anthropic-2026.md +367 -0
  80. package/research/llm-summarization/claude-cli-integration.md +1706 -0
  81. package/research/llm-summarization/cli-integration-patterns.md +3155 -0
  82. package/research/llm-summarization/openai-2026.md +473 -0
  83. package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
  84. package/research/llm-summarization/opencode-cli-integration.md +1552 -0
  85. package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
  86. package/research/llm-summarization/prototype-results.md +56 -0
  87. package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
  88. package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
  89. package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
  90. package/research/mdcontext-pudding/01-index-embed.md +956 -0
  91. package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
  92. package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
  93. package/research/mdcontext-pudding/02-search.md +970 -0
  94. package/research/mdcontext-pudding/03-context.md +779 -0
  95. package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
  96. package/research/mdcontext-pudding/04-tree.md +704 -0
  97. package/research/mdcontext-pudding/05-config.md +1038 -0
  98. package/research/mdcontext-pudding/06-links-summary.txt +87 -0
  99. package/research/mdcontext-pudding/06-links.md +679 -0
  100. package/research/mdcontext-pudding/07-stats.md +693 -0
  101. package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
  102. package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
  103. package/research/mdcontext-pudding/README.md +168 -0
  104. package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
  105. package/research/research-quality-review.md +834 -0
  106. package/research/semantic-search/embedding-text-analysis.md +156 -0
  107. package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
  108. package/research/semantic-search/query-processing-analysis.md +207 -0
  109. package/research/semantic-search/root-cause-and-solution.md +114 -0
  110. package/research/semantic-search/threshold-validation-report.md +69 -0
  111. package/research/semantic-search/vector-search-analysis.md +63 -0
  112. package/research/test-path-issues.md +276 -0
  113. package/review/ALP-76/1-error-type-design.md +962 -0
  114. package/review/ALP-76/2-error-handling-patterns.md +906 -0
  115. package/review/ALP-76/3-error-presentation.md +624 -0
  116. package/review/ALP-76/4-test-coverage.md +625 -0
  117. package/review/ALP-76/5-migration-completeness.md +440 -0
  118. package/review/ALP-76/6-effect-best-practices.md +755 -0
  119. package/scripts/apply-branch-protection.sh +47 -0
  120. package/scripts/branch-protection-templates.json +79 -0
  121. package/scripts/prototype-summarization.ts +346 -0
  122. package/scripts/rebuild-hnswlib.js +32 -37
  123. package/scripts/setup-branch-protection.sh +64 -0
  124. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
  125. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
  126. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
  127. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
  128. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  129. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  130. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
  131. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
  132. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
  133. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
  134. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
  135. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
  136. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
  137. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
  138. package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
  139. package/src/cli/argv-preprocessor.test.ts +2 -2
  140. package/src/cli/cli.test.ts +230 -33
  141. package/src/cli/commands/config-cmd.ts +642 -0
  142. package/src/cli/commands/context.ts +97 -9
  143. package/src/cli/commands/duplicates.ts +122 -0
  144. package/src/cli/commands/embeddings.ts +529 -0
  145. package/src/cli/commands/index-cmd.ts +210 -30
  146. package/src/cli/commands/index.ts +3 -0
  147. package/src/cli/commands/search.ts +894 -64
  148. package/src/cli/commands/stats.ts +3 -0
  149. package/src/cli/commands/tree.ts +26 -5
  150. package/src/cli/config-layer.ts +176 -0
  151. package/src/cli/error-handler.test.ts +235 -0
  152. package/src/cli/error-handler.ts +655 -0
  153. package/src/cli/flag-schemas.ts +66 -0
  154. package/src/cli/help.ts +209 -7
  155. package/src/cli/main.ts +348 -58
  156. package/src/cli/options.ts +10 -0
  157. package/src/cli/shared-error-handling.ts +199 -0
  158. package/src/cli/utils.ts +150 -17
  159. package/src/config/file-provider.test.ts +320 -0
  160. package/src/config/file-provider.ts +273 -0
  161. package/src/config/index.ts +72 -0
  162. package/src/config/integration.test.ts +667 -0
  163. package/src/config/precedence.test.ts +277 -0
  164. package/src/config/precedence.ts +451 -0
  165. package/src/config/schema.test.ts +414 -0
  166. package/src/config/schema.ts +603 -0
  167. package/src/config/service.test.ts +320 -0
  168. package/src/config/service.ts +243 -0
  169. package/src/config/testing.test.ts +264 -0
  170. package/src/config/testing.ts +110 -0
  171. package/src/core/types.ts +6 -33
  172. package/src/duplicates/detector.test.ts +183 -0
  173. package/src/duplicates/detector.ts +414 -0
  174. package/src/duplicates/index.ts +18 -0
  175. package/src/embeddings/embedding-namespace.test.ts +300 -0
  176. package/src/embeddings/embedding-namespace.ts +947 -0
  177. package/src/embeddings/heading-boost.test.ts +222 -0
  178. package/src/embeddings/hnsw-build-options.test.ts +198 -0
  179. package/src/embeddings/hyde.test.ts +272 -0
  180. package/src/embeddings/hyde.ts +264 -0
  181. package/src/embeddings/index.ts +2 -0
  182. package/src/embeddings/openai-provider.ts +332 -83
  183. package/src/embeddings/pricing.json +22 -0
  184. package/src/embeddings/provider-constants.ts +204 -0
  185. package/src/embeddings/provider-errors.test.ts +967 -0
  186. package/src/embeddings/provider-errors.ts +565 -0
  187. package/src/embeddings/provider-factory.test.ts +240 -0
  188. package/src/embeddings/provider-factory.ts +225 -0
  189. package/src/embeddings/provider-integration.test.ts +788 -0
  190. package/src/embeddings/query-preprocessing.test.ts +187 -0
  191. package/src/embeddings/semantic-search-threshold.test.ts +508 -0
  192. package/src/embeddings/semantic-search.ts +780 -93
  193. package/src/embeddings/types.ts +293 -16
  194. package/src/embeddings/vector-store.ts +486 -77
  195. package/src/embeddings/voyage-provider.ts +313 -0
  196. package/src/errors/errors.test.ts +845 -0
  197. package/src/errors/index.ts +533 -0
  198. package/src/index/ignore-patterns.test.ts +354 -0
  199. package/src/index/ignore-patterns.ts +305 -0
  200. package/src/index/indexer.ts +286 -48
  201. package/src/index/storage.ts +94 -30
  202. package/src/index/types.ts +40 -2
  203. package/src/index/watcher.ts +67 -9
  204. package/src/index.ts +22 -0
  205. package/src/integration/search-keyword.test.ts +678 -0
  206. package/src/mcp/server.ts +135 -6
  207. package/src/parser/parser.ts +18 -19
  208. package/src/parser/section-filter.test.ts +277 -0
  209. package/src/parser/section-filter.ts +125 -3
  210. package/src/search/__tests__/hybrid-search.test.ts +650 -0
  211. package/src/search/bm25-store.ts +366 -0
  212. package/src/search/cross-encoder.test.ts +253 -0
  213. package/src/search/cross-encoder.ts +406 -0
  214. package/src/search/fuzzy-search.test.ts +419 -0
  215. package/src/search/fuzzy-search.ts +273 -0
  216. package/src/search/hybrid-search.ts +448 -0
  217. package/src/search/path-matcher.test.ts +276 -0
  218. package/src/search/path-matcher.ts +33 -0
  219. package/src/search/searcher.test.ts +99 -1
  220. package/src/search/searcher.ts +189 -67
  221. package/src/search/wink-bm25.d.ts +30 -0
  222. package/src/summarization/cli-providers/claude.ts +202 -0
  223. package/src/summarization/cli-providers/detection.test.ts +273 -0
  224. package/src/summarization/cli-providers/detection.ts +118 -0
  225. package/src/summarization/cli-providers/index.ts +8 -0
  226. package/src/summarization/cost.test.ts +139 -0
  227. package/src/summarization/cost.ts +102 -0
  228. package/src/summarization/error-handler.test.ts +127 -0
  229. package/src/summarization/error-handler.ts +111 -0
  230. package/src/summarization/index.ts +102 -0
  231. package/src/summarization/pipeline.test.ts +498 -0
  232. package/src/summarization/pipeline.ts +231 -0
  233. package/src/summarization/prompts.test.ts +269 -0
  234. package/src/summarization/prompts.ts +133 -0
  235. package/src/summarization/provider-factory.test.ts +396 -0
  236. package/src/summarization/provider-factory.ts +178 -0
  237. package/src/summarization/types.ts +184 -0
  238. package/src/summarize/summarizer.ts +104 -35
  239. package/src/types/huggingface-transformers.d.ts +66 -0
  240. package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
  241. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
  242. package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
  243. package/tests/fixtures/cli/.mdcontext/indexes/documents.json +4 -4
  244. package/tests/fixtures/cli/.mdcontext/indexes/sections.json +14 -0
  245. package/tests/integration/embed-index.test.ts +712 -0
  246. package/tests/integration/search-context.test.ts +469 -0
  247. package/tests/integration/search-semantic.test.ts +522 -0
  248. package/vitest.config.ts +1 -6
  249. package/AGENTS.md +0 -46
  250. package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
  251. package/tests/fixtures/cli/.mdcontext/vectors.meta.json +0 -1264
@@ -0,0 +1,274 @@
1
+ // src/config/schema.ts
2
+ import { Config, Option } from "effect";
3
+
4
+ var IndexConfig = Config.all({
5
+ /**
6
+ * Maximum directory depth to traverse when indexing
7
+ * Default: 10
8
+ */
9
+ maxDepth: Config.number("maxDepth").pipe(Config.withDefault(10)),
10
+ /**
11
+ * Glob patterns to exclude from indexing (comma-separated)
12
+ * Default: ['node_modules', '.git', 'dist', 'build']
13
+ */
14
+ excludePatterns: Config.array(Config.string(), "excludePatterns").pipe(
15
+ Config.withDefault(["node_modules", ".git", "dist", "build"]),
16
+ ),
17
+ /**
18
+ * File extensions to index (comma-separated)
19
+ * Default: ['.md', '.mdx']
20
+ */
21
+ fileExtensions: Config.array(Config.string(), "fileExtensions").pipe(
22
+ Config.withDefault([".md", ".mdx"]),
23
+ ),
24
+ /**
25
+ * Whether to follow symlinks when traversing directories
26
+ * Default: false
27
+ */
28
+ followSymlinks: Config.boolean("followSymlinks").pipe(
29
+ Config.withDefault(false),
30
+ ),
31
+ /**
32
+ * Directory where index files are stored (relative to project root)
33
+ * Default: '.mdcontext'
34
+ */
35
+ indexDir: Config.string("indexDir").pipe(Config.withDefault(".mdcontext")),
36
+ });
37
+ var SearchConfig = Config.all({
38
+ /**
39
+ * Default number of search results to return
40
+ * Default: 10
41
+ */
42
+ defaultLimit: Config.number("defaultLimit").pipe(Config.withDefault(10)),
43
+ /**
44
+ * Maximum number of search results allowed
45
+ * Default: 100
46
+ */
47
+ maxLimit: Config.number("maxLimit").pipe(Config.withDefault(100)),
48
+ /**
49
+ * Minimum similarity score for semantic search results (0-1)
50
+ * Default: 0.5
51
+ */
52
+ minSimilarity: Config.number("minSimilarity").pipe(Config.withDefault(0.5)),
53
+ /**
54
+ * Whether to include content snippets in search results
55
+ * Default: true
56
+ */
57
+ includeSnippets: Config.boolean("includeSnippets").pipe(
58
+ Config.withDefault(true),
59
+ ),
60
+ /**
61
+ * Maximum length of content snippets in characters
62
+ * Default: 200
63
+ */
64
+ snippetLength: Config.number("snippetLength").pipe(Config.withDefault(200)),
65
+ /**
66
+ * Auto-create semantic index if estimated time is under this threshold (seconds)
67
+ * Default: 10
68
+ */
69
+ autoIndexThreshold: Config.number("autoIndexThreshold").pipe(
70
+ Config.withDefault(10),
71
+ ),
72
+ });
73
+ var EmbeddingsConfig = Config.all({
74
+ /**
75
+ * Embedding provider to use
76
+ * Default: 'openai'
77
+ */
78
+ provider: Config.literal("openai")("provider").pipe(
79
+ Config.withDefault("openai"),
80
+ ),
81
+ /**
82
+ * OpenAI embedding model to use
83
+ * Default: 'text-embedding-3-small'
84
+ */
85
+ model: Config.string("model").pipe(
86
+ Config.withDefault("text-embedding-3-small"),
87
+ ),
88
+ /**
89
+ * Number of dimensions for embeddings
90
+ * Lower dimensions = faster search, higher = more accuracy
91
+ * Default: 512
92
+ */
93
+ dimensions: Config.number("dimensions").pipe(Config.withDefault(512)),
94
+ /**
95
+ * Batch size for embedding API calls
96
+ * Default: 100
97
+ */
98
+ batchSize: Config.number("batchSize").pipe(Config.withDefault(100)),
99
+ /**
100
+ * Maximum retries for failed API calls
101
+ * Default: 3
102
+ */
103
+ maxRetries: Config.number("maxRetries").pipe(Config.withDefault(3)),
104
+ /**
105
+ * Delay between retries in milliseconds
106
+ * Default: 1000
107
+ */
108
+ retryDelayMs: Config.number("retryDelayMs").pipe(Config.withDefault(1e3)),
109
+ /**
110
+ * Request timeout in milliseconds
111
+ * Default: 30000 (30 seconds)
112
+ */
113
+ timeoutMs: Config.number("timeoutMs").pipe(Config.withDefault(3e4)),
114
+ /**
115
+ * OpenAI API key (usually from environment variable)
116
+ * No default - must be provided
117
+ */
118
+ apiKey: Config.option(Config.string("apiKey")),
119
+ });
120
+ var OutputConfig = Config.all({
121
+ /**
122
+ * Default output format
123
+ * Default: 'text'
124
+ */
125
+ format: Config.literal(
126
+ "text",
127
+ "json",
128
+ )("format").pipe(Config.withDefault("text")),
129
+ /**
130
+ * Whether to use colors in terminal output
131
+ * Default: true
132
+ */
133
+ color: Config.boolean("color").pipe(Config.withDefault(true)),
134
+ /**
135
+ * Whether to pretty-print JSON output
136
+ * Default: true
137
+ */
138
+ prettyJson: Config.boolean("prettyJson").pipe(Config.withDefault(true)),
139
+ /**
140
+ * Whether to show verbose output
141
+ * Default: false
142
+ */
143
+ verbose: Config.boolean("verbose").pipe(Config.withDefault(false)),
144
+ /**
145
+ * Whether to show debug information
146
+ * Default: false
147
+ */
148
+ debug: Config.boolean("debug").pipe(Config.withDefault(false)),
149
+ });
150
+ var SummarizationConfig = Config.all({
151
+ /**
152
+ * Token budget for 'brief' compression level
153
+ * Default: 100
154
+ */
155
+ briefTokenBudget: Config.number("briefTokenBudget").pipe(
156
+ Config.withDefault(100),
157
+ ),
158
+ /**
159
+ * Token budget for 'summary' compression level
160
+ * Default: 500
161
+ */
162
+ summaryTokenBudget: Config.number("summaryTokenBudget").pipe(
163
+ Config.withDefault(500),
164
+ ),
165
+ /**
166
+ * Target compression ratio for summaries (0-1)
167
+ * Default: 0.3 (30% of original)
168
+ */
169
+ compressionRatio: Config.number("compressionRatio").pipe(
170
+ Config.withDefault(0.3),
171
+ ),
172
+ /**
173
+ * Minimum tokens for any section summary
174
+ * Default: 20
175
+ */
176
+ minSectionTokens: Config.number("minSectionTokens").pipe(
177
+ Config.withDefault(20),
178
+ ),
179
+ /**
180
+ * Maximum topics to extract from a document
181
+ * Default: 10
182
+ */
183
+ maxTopics: Config.number("maxTopics").pipe(Config.withDefault(10)),
184
+ /**
185
+ * Minimum remaining budget to include partial content
186
+ * Default: 50
187
+ */
188
+ minPartialBudget: Config.number("minPartialBudget").pipe(
189
+ Config.withDefault(50),
190
+ ),
191
+ });
192
+ var PathsConfig = Config.all({
193
+ /**
194
+ * Root directory for markdown files (default: current working directory)
195
+ */
196
+ root: Config.option(Config.string("root")),
197
+ /**
198
+ * Custom config file path (default: auto-detected)
199
+ */
200
+ configFile: Config.option(Config.string("configFile")),
201
+ /**
202
+ * Cache directory for temporary files
203
+ * Default: '.mdcontext/cache'
204
+ */
205
+ cacheDir: Config.string("cacheDir").pipe(
206
+ Config.withDefault(".mdcontext/cache"),
207
+ ),
208
+ });
209
+ var MdContextConfig = Config.all({
210
+ index: Config.nested(IndexConfig, "index"),
211
+ search: Config.nested(SearchConfig, "search"),
212
+ embeddings: Config.nested(EmbeddingsConfig, "embeddings"),
213
+ summarization: Config.nested(SummarizationConfig, "summarization"),
214
+ output: Config.nested(OutputConfig, "output"),
215
+ paths: Config.nested(PathsConfig, "paths"),
216
+ });
217
+ var defaultConfig = {
218
+ index: {
219
+ maxDepth: 10,
220
+ excludePatterns: ["node_modules", ".git", "dist", "build"],
221
+ fileExtensions: [".md", ".mdx"],
222
+ followSymlinks: false,
223
+ indexDir: ".mdcontext",
224
+ },
225
+ search: {
226
+ defaultLimit: 10,
227
+ maxLimit: 100,
228
+ minSimilarity: 0.5,
229
+ includeSnippets: true,
230
+ snippetLength: 200,
231
+ autoIndexThreshold: 10,
232
+ },
233
+ embeddings: {
234
+ provider: "openai",
235
+ model: "text-embedding-3-small",
236
+ dimensions: 512,
237
+ batchSize: 100,
238
+ maxRetries: 3,
239
+ retryDelayMs: 1e3,
240
+ timeoutMs: 3e4,
241
+ apiKey: Option.none(),
242
+ },
243
+ summarization: {
244
+ briefTokenBudget: 100,
245
+ summaryTokenBudget: 500,
246
+ compressionRatio: 0.3,
247
+ minSectionTokens: 20,
248
+ maxTopics: 10,
249
+ minPartialBudget: 50,
250
+ },
251
+ output: {
252
+ format: "text",
253
+ color: true,
254
+ prettyJson: true,
255
+ verbose: false,
256
+ debug: false,
257
+ },
258
+ paths: {
259
+ root: Option.none(),
260
+ configFile: Option.none(),
261
+ cacheDir: ".mdcontext/cache",
262
+ },
263
+ };
264
+
265
+ export {
266
+ IndexConfig,
267
+ SearchConfig,
268
+ EmbeddingsConfig,
269
+ OutputConfig,
270
+ SummarizationConfig,
271
+ PathsConfig,
272
+ MdContextConfig,
273
+ defaultConfig,
274
+ };
@@ -0,0 +1,104 @@
1
+ import {
2
+ WatchError,
3
+ buildIndex,
4
+ createStorage,
5
+ getChokidarIgnorePatterns,
6
+ indexExists
7
+ } from "./chunk-MUJELQQ6.js";
8
+
9
+ // src/index/watcher.ts
10
+ import * as path from "path";
11
+ import { watch } from "chokidar";
12
+ import { Effect } from "effect";
13
+ var isMarkdownFile = (filePath) => filePath.endsWith(".md") || filePath.endsWith(".mdx");
14
+ var watchDirectory = (rootPath, options = {}) => Effect.gen(function* () {
15
+ const resolvedRoot = path.resolve(rootPath);
16
+ const storage = createStorage(resolvedRoot);
17
+ const debounceMs = options.debounceMs ?? 300;
18
+ const exists = yield* indexExists(storage);
19
+ if (!exists) {
20
+ const result = yield* buildIndex(resolvedRoot, options);
21
+ options.onIndex?.({
22
+ documentsIndexed: result.documentsIndexed,
23
+ duration: result.duration
24
+ });
25
+ }
26
+ const pendingPaths = /* @__PURE__ */ new Set();
27
+ let debounceTimer = null;
28
+ const scheduleReindex = () => {
29
+ if (debounceTimer) {
30
+ clearTimeout(debounceTimer);
31
+ }
32
+ debounceTimer = setTimeout(async () => {
33
+ if (pendingPaths.size === 0) return;
34
+ pendingPaths.clear();
35
+ try {
36
+ const result = await Effect.runPromise(
37
+ buildIndex(resolvedRoot, options)
38
+ );
39
+ options.onIndex?.({
40
+ documentsIndexed: result.documentsIndexed,
41
+ duration: result.duration
42
+ });
43
+ } catch (error) {
44
+ options.onError?.(
45
+ new WatchError({
46
+ path: resolvedRoot,
47
+ message: error instanceof Error ? error.message : "Index rebuild failed",
48
+ cause: error
49
+ })
50
+ );
51
+ }
52
+ }, debounceMs);
53
+ };
54
+ const ignorePatterns = yield* getChokidarIgnorePatterns({
55
+ rootPath: resolvedRoot,
56
+ cliPatterns: options.exclude,
57
+ honorGitignore: options.honorGitignore ?? true,
58
+ honorMdcontextignore: options.honorMdcontextignore ?? true
59
+ });
60
+ const watcher = watch(resolvedRoot, {
61
+ ignored: ignorePatterns,
62
+ persistent: true,
63
+ ignoreInitial: true
64
+ });
65
+ watcher.on("add", (filePath) => {
66
+ if (isMarkdownFile(filePath)) {
67
+ pendingPaths.add(filePath);
68
+ scheduleReindex();
69
+ }
70
+ });
71
+ watcher.on("change", (filePath) => {
72
+ if (isMarkdownFile(filePath)) {
73
+ pendingPaths.add(filePath);
74
+ scheduleReindex();
75
+ }
76
+ });
77
+ watcher.on("unlink", (filePath) => {
78
+ if (isMarkdownFile(filePath)) {
79
+ pendingPaths.add(filePath);
80
+ scheduleReindex();
81
+ }
82
+ });
83
+ watcher.on("error", (error) => {
84
+ options.onError?.(
85
+ new WatchError({
86
+ path: resolvedRoot,
87
+ message: error instanceof Error ? error.message : "File watcher error",
88
+ cause: error
89
+ })
90
+ );
91
+ });
92
+ return {
93
+ stop: () => {
94
+ if (debounceTimer) {
95
+ clearTimeout(debounceTimer);
96
+ }
97
+ watcher.close();
98
+ }
99
+ };
100
+ });
101
+
102
+ export {
103
+ watchDirectory
104
+ };
@@ -0,0 +1,103 @@
1
+ import { watch } from "chokidar";
2
+ import { Effect } from "effect";
3
+ // src/index/watcher.ts
4
+ import * as path from "path";
5
+ import {
6
+ buildIndex,
7
+ createStorage,
8
+ indexExists,
9
+ WatchError,
10
+ } from "./chunk-IP3FRFEB.js";
11
+
12
+ var isMarkdownFile = (filePath) =>
13
+ filePath.endsWith(".md") || filePath.endsWith(".mdx");
14
+ var watchDirectory = (rootPath, options = {}) =>
15
+ Effect.gen(function* () {
16
+ const resolvedRoot = path.resolve(rootPath);
17
+ const storage = createStorage(resolvedRoot);
18
+ const debounceMs = options.debounceMs ?? 300;
19
+ const exists = yield* indexExists(storage);
20
+ if (!exists) {
21
+ const result = yield* buildIndex(resolvedRoot, options);
22
+ options.onIndex?.({
23
+ documentsIndexed: result.documentsIndexed,
24
+ duration: result.duration,
25
+ });
26
+ }
27
+ const pendingPaths = /* @__PURE__ */ new Set();
28
+ let debounceTimer = null;
29
+ const scheduleReindex = () => {
30
+ if (debounceTimer) {
31
+ clearTimeout(debounceTimer);
32
+ }
33
+ debounceTimer = setTimeout(async () => {
34
+ if (pendingPaths.size === 0) return;
35
+ pendingPaths.clear();
36
+ try {
37
+ const result = await Effect.runPromise(
38
+ buildIndex(resolvedRoot, options),
39
+ );
40
+ options.onIndex?.({
41
+ documentsIndexed: result.documentsIndexed,
42
+ duration: result.duration,
43
+ });
44
+ } catch (error) {
45
+ options.onError?.(
46
+ new WatchError({
47
+ path: resolvedRoot,
48
+ message:
49
+ error instanceof Error ? error.message : "Index rebuild failed",
50
+ cause: error,
51
+ }),
52
+ );
53
+ }
54
+ }, debounceMs);
55
+ };
56
+ const watcher = watch(resolvedRoot, {
57
+ ignored: [
58
+ /(^|[/\\])\../,
59
+ // Ignore dotfiles
60
+ "**/node_modules/**",
61
+ ],
62
+ persistent: true,
63
+ ignoreInitial: true,
64
+ });
65
+ watcher.on("add", (filePath) => {
66
+ if (isMarkdownFile(filePath)) {
67
+ pendingPaths.add(filePath);
68
+ scheduleReindex();
69
+ }
70
+ });
71
+ watcher.on("change", (filePath) => {
72
+ if (isMarkdownFile(filePath)) {
73
+ pendingPaths.add(filePath);
74
+ scheduleReindex();
75
+ }
76
+ });
77
+ watcher.on("unlink", (filePath) => {
78
+ if (isMarkdownFile(filePath)) {
79
+ pendingPaths.add(filePath);
80
+ scheduleReindex();
81
+ }
82
+ });
83
+ watcher.on("error", (error) => {
84
+ options.onError?.(
85
+ new WatchError({
86
+ path: resolvedRoot,
87
+ message:
88
+ error instanceof Error ? error.message : "File watcher error",
89
+ cause: error,
90
+ }),
91
+ );
92
+ });
93
+ return {
94
+ stop: () => {
95
+ if (debounceTimer) {
96
+ clearTimeout(debounceTimer);
97
+ }
98
+ watcher.close();
99
+ },
100
+ };
101
+ });
102
+
103
+ export { watchDirectory };