mdcontext 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/.changeset/README.md +28 -0
  2. package/.changeset/config.json +11 -0
  3. package/.github/workflows/ci.yml +83 -0
  4. package/.github/workflows/release.yml +113 -0
  5. package/.tldrignore +112 -0
  6. package/AGENTS.md +46 -0
  7. package/BACKLOG.md +338 -0
  8. package/README.md +231 -11
  9. package/biome.json +36 -0
  10. package/cspell.config.yaml +14 -0
  11. package/dist/chunk-KRYIFLQR.js +92 -0
  12. package/dist/chunk-S7E6TFX6.js +742 -0
  13. package/dist/chunk-VVTGZNBT.js +1519 -0
  14. package/dist/cli/main.d.ts +1 -0
  15. package/dist/cli/main.js +2015 -0
  16. package/dist/index.d.ts +266 -0
  17. package/dist/index.js +86 -0
  18. package/dist/mcp/server.d.ts +1 -0
  19. package/dist/mcp/server.js +376 -0
  20. package/docs/019-USAGE.md +586 -0
  21. package/docs/020-current-implementation.md +364 -0
  22. package/docs/021-DOGFOODING-FINDINGS.md +175 -0
  23. package/docs/BACKLOG.md +80 -0
  24. package/docs/DESIGN.md +439 -0
  25. package/docs/PROJECT.md +88 -0
  26. package/docs/ROADMAP.md +407 -0
  27. package/docs/test-links.md +9 -0
  28. package/package.json +69 -10
  29. package/pnpm-workspace.yaml +5 -0
  30. package/research/config-analysis/01-current-implementation.md +470 -0
  31. package/research/config-analysis/02-strategy-recommendation.md +428 -0
  32. package/research/config-analysis/03-task-candidates.md +715 -0
  33. package/research/config-analysis/033-research-configuration-management.md +828 -0
  34. package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
  35. package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
  36. package/research/dogfood/consolidated-tool-evaluation.md +373 -0
  37. package/research/dogfood/strategy-a/a-synthesis.md +184 -0
  38. package/research/dogfood/strategy-a/a1-docs.md +226 -0
  39. package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
  40. package/research/dogfood/strategy-a/a3-llm.md +164 -0
  41. package/research/dogfood/strategy-b/b-synthesis.md +228 -0
  42. package/research/dogfood/strategy-b/b1-architecture.md +207 -0
  43. package/research/dogfood/strategy-b/b2-gaps.md +258 -0
  44. package/research/dogfood/strategy-b/b3-workflows.md +250 -0
  45. package/research/dogfood/strategy-c/c-synthesis.md +451 -0
  46. package/research/dogfood/strategy-c/c1-explorer.md +192 -0
  47. package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
  48. package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
  49. package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
  50. package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
  51. package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
  52. package/research/effect-cli-error-handling.md +845 -0
  53. package/research/effect-errors-as-values.md +943 -0
  54. package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
  55. package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
  56. package/research/errors-task-analysis/embeddings-analysis.md +709 -0
  57. package/research/errors-task-analysis/index-search-analysis.md +812 -0
  58. package/research/mdcontext-error-analysis.md +521 -0
  59. package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
  60. package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
  61. package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
  62. package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
  63. package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
  64. package/research/semantic-search/002-research-embedding-models.md +490 -0
  65. package/research/semantic-search/003-research-rag-alternatives.md +523 -0
  66. package/research/semantic-search/004-research-vector-search.md +841 -0
  67. package/research/semantic-search/032-research-semantic-search.md +427 -0
  68. package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
  69. package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
  70. package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
  71. package/research/task-management-2026/03-lightweight-file-based.md +567 -0
  72. package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
  73. package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
  74. package/research/task-management-2026/linear/02-api-integrations.md +930 -0
  75. package/research/task-management-2026/linear/03-ai-features.md +368 -0
  76. package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
  77. package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
  78. package/scripts/rebuild-hnswlib.js +63 -0
  79. package/src/cli/argv-preprocessor.test.ts +210 -0
  80. package/src/cli/argv-preprocessor.ts +202 -0
  81. package/src/cli/cli.test.ts +430 -0
  82. package/src/cli/commands/backlinks.ts +54 -0
  83. package/src/cli/commands/context.ts +197 -0
  84. package/src/cli/commands/index-cmd.ts +300 -0
  85. package/src/cli/commands/index.ts +13 -0
  86. package/src/cli/commands/links.ts +52 -0
  87. package/src/cli/commands/search.ts +451 -0
  88. package/src/cli/commands/stats.ts +146 -0
  89. package/src/cli/commands/tree.ts +107 -0
  90. package/src/cli/flag-schemas.ts +275 -0
  91. package/src/cli/help.ts +386 -0
  92. package/src/cli/index.ts +9 -0
  93. package/src/cli/main.ts +145 -0
  94. package/src/cli/options.ts +31 -0
  95. package/src/cli/typo-suggester.test.ts +105 -0
  96. package/src/cli/typo-suggester.ts +130 -0
  97. package/src/cli/utils.ts +126 -0
  98. package/src/core/index.ts +1 -0
  99. package/src/core/types.ts +140 -0
  100. package/src/embeddings/index.ts +8 -0
  101. package/src/embeddings/openai-provider.ts +165 -0
  102. package/src/embeddings/semantic-search.ts +583 -0
  103. package/src/embeddings/types.ts +82 -0
  104. package/src/embeddings/vector-store.ts +299 -0
  105. package/src/index/index.ts +4 -0
  106. package/src/index/indexer.ts +446 -0
  107. package/src/index/storage.ts +196 -0
  108. package/src/index/types.ts +109 -0
  109. package/src/index/watcher.ts +131 -0
  110. package/src/index.ts +8 -0
  111. package/src/mcp/server.ts +483 -0
  112. package/src/parser/index.ts +1 -0
  113. package/src/parser/parser.test.ts +291 -0
  114. package/src/parser/parser.ts +395 -0
  115. package/src/parser/section-filter.ts +270 -0
  116. package/src/search/query-parser.test.ts +260 -0
  117. package/src/search/query-parser.ts +319 -0
  118. package/src/search/searcher.test.ts +182 -0
  119. package/src/search/searcher.ts +602 -0
  120. package/src/summarize/budget-bugs.test.ts +620 -0
  121. package/src/summarize/formatters.ts +419 -0
  122. package/src/summarize/index.ts +20 -0
  123. package/src/summarize/summarizer.test.ts +275 -0
  124. package/src/summarize/summarizer.ts +528 -0
  125. package/src/summarize/verify-bugs.test.ts +238 -0
  126. package/src/utils/index.ts +1 -0
  127. package/src/utils/tokens.test.ts +142 -0
  128. package/src/utils/tokens.ts +186 -0
  129. package/tests/fixtures/cli/.mdcontext/config.json +8 -0
  130. package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
  131. package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
  132. package/tests/fixtures/cli/.mdcontext/indexes/sections.json +233 -0
  133. package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
  134. package/tests/fixtures/cli/.mdcontext/vectors.meta.json +1264 -0
  135. package/tests/fixtures/cli/README.md +9 -0
  136. package/tests/fixtures/cli/api-reference.md +11 -0
  137. package/tests/fixtures/cli/getting-started.md +11 -0
  138. package/tsconfig.json +26 -0
  139. package/vitest.config.ts +21 -0
  140. package/vitest.setup.ts +12 -0
@@ -0,0 +1,266 @@
1
+ import { Effect } from 'effect';
2
+
3
+ /**
4
+ * Core data types for mdcontext
5
+ * Based on DESIGN.md specifications
6
+ */
7
+ interface MdDocument {
8
+ readonly id: string;
9
+ readonly path: string;
10
+ readonly title: string;
11
+ readonly frontmatter: Record<string, unknown>;
12
+ readonly sections: readonly MdSection[];
13
+ readonly links: readonly MdLink[];
14
+ readonly codeBlocks: readonly MdCodeBlock[];
15
+ readonly metadata: DocumentMetadata;
16
+ }
17
+ interface DocumentMetadata {
18
+ readonly wordCount: number;
19
+ readonly tokenCount: number;
20
+ readonly headingCount: number;
21
+ readonly linkCount: number;
22
+ readonly codeBlockCount: number;
23
+ readonly lastModified: Date;
24
+ readonly indexedAt: Date;
25
+ }
26
+ type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
27
+ interface MdSection {
28
+ readonly id: string;
29
+ readonly heading: string;
30
+ readonly level: HeadingLevel;
31
+ readonly content: string;
32
+ readonly plainText: string;
33
+ readonly startLine: number;
34
+ readonly endLine: number;
35
+ readonly children: readonly MdSection[];
36
+ readonly metadata: SectionMetadata;
37
+ }
38
+ interface SectionMetadata {
39
+ readonly wordCount: number;
40
+ readonly tokenCount: number;
41
+ readonly hasCode: boolean;
42
+ readonly hasList: boolean;
43
+ readonly hasTable: boolean;
44
+ }
45
+ type LinkType = 'internal' | 'external' | 'image';
46
+ interface MdLink {
47
+ readonly type: LinkType;
48
+ readonly href: string;
49
+ readonly text: string;
50
+ readonly sectionId: string;
51
+ readonly line: number;
52
+ }
53
+ interface MdCodeBlock {
54
+ readonly language: string | null;
55
+ readonly content: string;
56
+ readonly sectionId: string;
57
+ readonly startLine: number;
58
+ readonly endLine: number;
59
+ }
60
+ interface ParseError {
61
+ readonly _tag: 'ParseError';
62
+ readonly message: string;
63
+ readonly line?: number | undefined;
64
+ readonly column?: number | undefined;
65
+ }
66
+ declare const ParseError: (message: string, line?: number, column?: number) => ParseError;
67
+ interface IoError {
68
+ readonly _tag: 'IoError';
69
+ readonly message: string;
70
+ readonly path: string;
71
+ readonly cause?: unknown;
72
+ }
73
+ declare const IoError: (message: string, path: string, cause?: unknown) => IoError;
74
+ interface IndexError {
75
+ readonly _tag: 'IndexError';
76
+ readonly cause: 'DiskFull' | 'Permission' | 'Corrupted' | 'Unknown';
77
+ readonly message: string;
78
+ }
79
+ declare const IndexError: (cause: IndexError["cause"], message: string) => IndexError;
80
+
81
+ /**
82
+ * Index data types for mdcontext
83
+ */
84
+ interface IndexConfig {
85
+ readonly version: number;
86
+ readonly rootPath: string;
87
+ readonly include: readonly string[];
88
+ readonly exclude: readonly string[];
89
+ readonly createdAt: string;
90
+ readonly updatedAt: string;
91
+ }
92
+ interface DocumentIndex {
93
+ readonly version: number;
94
+ readonly rootPath: string;
95
+ readonly documents: Record<string, DocumentEntry>;
96
+ }
97
+ interface DocumentEntry {
98
+ readonly id: string;
99
+ readonly path: string;
100
+ readonly title: string;
101
+ readonly mtime: number;
102
+ readonly hash: string;
103
+ readonly tokenCount: number;
104
+ readonly sectionCount: number;
105
+ }
106
+ interface SectionIndex {
107
+ readonly version: number;
108
+ readonly sections: Record<string, SectionEntry>;
109
+ readonly byHeading: Record<string, readonly string[]>;
110
+ readonly byDocument: Record<string, readonly string[]>;
111
+ }
112
+ interface SectionEntry {
113
+ readonly id: string;
114
+ readonly documentId: string;
115
+ readonly documentPath: string;
116
+ readonly heading: string;
117
+ readonly level: number;
118
+ readonly startLine: number;
119
+ readonly endLine: number;
120
+ readonly tokenCount: number;
121
+ readonly hasCode: boolean;
122
+ readonly hasList: boolean;
123
+ readonly hasTable: boolean;
124
+ }
125
+ interface LinkIndex {
126
+ readonly version: number;
127
+ readonly forward: Record<string, readonly string[]>;
128
+ readonly backward: Record<string, readonly string[]>;
129
+ readonly broken: readonly string[];
130
+ }
131
+ interface IndexResult {
132
+ readonly documentsIndexed: number;
133
+ readonly sectionsIndexed: number;
134
+ readonly linksIndexed: number;
135
+ readonly totalDocuments: number;
136
+ readonly totalSections: number;
137
+ readonly totalLinks: number;
138
+ readonly duration: number;
139
+ readonly errors: readonly IndexBuildError[];
140
+ }
141
+ interface IndexBuildError {
142
+ readonly path: string;
143
+ readonly message: string;
144
+ }
145
+ declare const INDEX_DIR = ".mdcontext";
146
+ declare const INDEX_VERSION = 1;
147
+ declare const getIndexPaths: (rootPath: string) => {
148
+ root: string;
149
+ config: string;
150
+ documents: string;
151
+ sections: string;
152
+ links: string;
153
+ cache: string;
154
+ parsed: string;
155
+ };
156
+
157
+ /**
158
+ * Indexer service for building and updating indexes
159
+ */
160
+
161
+ interface IndexOptions {
162
+ readonly force?: boolean;
163
+ readonly exclude?: readonly string[];
164
+ }
165
+ declare const buildIndex: (rootPath: string, options?: IndexOptions) => Effect.Effect<IndexResult, Error>;
166
+ declare const getOutgoingLinks: (rootPath: string, filePath: string) => Effect.Effect<readonly string[], Error>;
167
+ declare const getIncomingLinks: (rootPath: string, filePath: string) => Effect.Effect<readonly string[], Error>;
168
+ declare const getBrokenLinks: (rootPath: string) => Effect.Effect<readonly string[], Error>;
169
+
170
+ /**
171
+ * Index storage operations
172
+ */
173
+
174
+ declare const computeHash: (content: string) => string;
175
+ interface IndexStorage {
176
+ readonly rootPath: string;
177
+ readonly paths: ReturnType<typeof getIndexPaths>;
178
+ }
179
+ declare const createStorage: (rootPath: string) => IndexStorage;
180
+ declare const initializeIndex: (storage: IndexStorage) => Effect.Effect<void, Error>;
181
+ declare const loadConfig: (storage: IndexStorage) => Effect.Effect<IndexConfig | null, Error>;
182
+ declare const saveConfig: (storage: IndexStorage, config: IndexConfig) => Effect.Effect<void, Error>;
183
+ declare const loadDocumentIndex: (storage: IndexStorage) => Effect.Effect<DocumentIndex | null, Error>;
184
+ declare const saveDocumentIndex: (storage: IndexStorage, index: DocumentIndex) => Effect.Effect<void, Error>;
185
+ declare const createEmptyDocumentIndex: (rootPath: string) => DocumentIndex;
186
+ declare const loadSectionIndex: (storage: IndexStorage) => Effect.Effect<SectionIndex | null, Error>;
187
+ declare const saveSectionIndex: (storage: IndexStorage, index: SectionIndex) => Effect.Effect<void, Error>;
188
+ declare const createEmptySectionIndex: () => SectionIndex;
189
+ declare const loadLinkIndex: (storage: IndexStorage) => Effect.Effect<LinkIndex | null, Error>;
190
+ declare const saveLinkIndex: (storage: IndexStorage, index: LinkIndex) => Effect.Effect<void, Error>;
191
+ declare const createEmptyLinkIndex: () => LinkIndex;
192
+ declare const indexExists: (storage: IndexStorage) => Effect.Effect<boolean, Error>;
193
+
194
+ /**
195
+ * File watcher for automatic re-indexing
196
+ */
197
+
198
+ interface WatcherOptions extends IndexOptions {
199
+ readonly debounceMs?: number;
200
+ readonly onIndex?: (result: {
201
+ documentsIndexed: number;
202
+ duration: number;
203
+ }) => void;
204
+ readonly onError?: (error: Error) => void;
205
+ }
206
+ interface Watcher {
207
+ readonly stop: () => void;
208
+ }
209
+ declare const watchDirectory: (rootPath: string, options?: WatcherOptions) => Effect.Effect<Watcher, Error>;
210
+
211
+ /**
212
+ * Markdown parser using remark/unified
213
+ * Handles GFM (tables, task lists) and YAML frontmatter
214
+ */
215
+
216
+ interface ParseOptions {
217
+ readonly path?: string;
218
+ readonly lastModified?: Date;
219
+ }
220
+ declare const parse: (content: string, options?: ParseOptions) => Effect.Effect<MdDocument, ParseError>;
221
+ /**
222
+ * Parse a markdown file from the filesystem
223
+ */
224
+ declare const parseFile: (filePath: string) => Effect.Effect<MdDocument, ParseError | {
225
+ _tag: "IoError";
226
+ message: string;
227
+ path: string;
228
+ }>;
229
+
230
+ /**
231
+ * Token counting utilities using tiktoken
232
+ */
233
+
234
+ /**
235
+ * Count tokens in a string using the cl100k_base encoding
236
+ * (compatible with GPT-4, GPT-3.5-turbo, and Claude models)
237
+ */
238
+ declare const countTokens: (text: string) => Effect.Effect<number, never, never>;
239
+ /**
240
+ * Synchronous token counting with improved approximation
241
+ *
242
+ * Uses heuristics calibrated against cl100k_base encoding:
243
+ * - Base prose: ~3.5 chars/token (conservative to never under-count)
244
+ * - Code blocks: Content at ~2.8 chars/token + fixed overhead per block
245
+ * - Inline code: ~2.5 chars/token + 2 tokens per backtick pair
246
+ * - Paths: ~3.0 chars/token (slashes tokenize separately)
247
+ * - Newlines: ~1 token each (they often become separate tokens)
248
+ * - Punctuation/symbols: adds ~0.8 tokens per mark
249
+ * - CJK characters: ~1.2 tokens per character
250
+ * - Emojis: ~2.5 tokens per emoji
251
+ *
252
+ * Safety margin of 10% to handle edge cases and ensure budget compliance.
253
+ * The conservative ratios combined with safety margin ensure we NEVER under-count.
254
+ */
255
+ declare const countTokensApprox: (text: string) => number;
256
+ /**
257
+ * Count words in text
258
+ */
259
+ declare const countWords: (text: string) => number;
260
+ /**
261
+ * Free the tiktoken encoder to release WebAssembly resources.
262
+ * Call this in test teardown to prevent process hang.
263
+ */
264
+ declare const freeEncoder: () => void;
265
+
266
+ export { type DocumentEntry, type DocumentIndex, type DocumentMetadata, type HeadingLevel, INDEX_DIR, INDEX_VERSION, type IndexBuildError, type IndexConfig, IndexError, type IndexOptions, type IndexResult, type IndexStorage, IoError, type LinkIndex, type LinkType, type MdCodeBlock, type MdDocument, type MdLink, type MdSection, ParseError, type ParseOptions, type SectionEntry, type SectionIndex, type SectionMetadata, type Watcher, type WatcherOptions, buildIndex, computeHash, countTokens, countTokensApprox, countWords, createEmptyDocumentIndex, createEmptyLinkIndex, createEmptySectionIndex, createStorage, freeEncoder, getBrokenLinks, getIncomingLinks, getIndexPaths, getOutgoingLinks, indexExists, initializeIndex, loadConfig, loadDocumentIndex, loadLinkIndex, loadSectionIndex, parse, parseFile, saveConfig, saveDocumentIndex, saveLinkIndex, saveSectionIndex, watchDirectory };
package/dist/index.js ADDED
@@ -0,0 +1,86 @@
1
+ import {
2
+ watchDirectory
3
+ } from "./chunk-KRYIFLQR.js";
4
+ import {
5
+ INDEX_DIR,
6
+ INDEX_VERSION,
7
+ buildIndex,
8
+ computeHash,
9
+ countTokens,
10
+ countTokensApprox,
11
+ countWords,
12
+ createEmptyDocumentIndex,
13
+ createEmptyLinkIndex,
14
+ createEmptySectionIndex,
15
+ createStorage,
16
+ freeEncoder,
17
+ getBrokenLinks,
18
+ getIncomingLinks,
19
+ getIndexPaths,
20
+ getOutgoingLinks,
21
+ indexExists,
22
+ initializeIndex,
23
+ loadConfig,
24
+ loadDocumentIndex,
25
+ loadLinkIndex,
26
+ loadSectionIndex,
27
+ parse,
28
+ parseFile,
29
+ saveConfig,
30
+ saveDocumentIndex,
31
+ saveLinkIndex,
32
+ saveSectionIndex
33
+ } from "./chunk-S7E6TFX6.js";
34
+
35
+ // src/core/types.ts
36
+ var ParseError = (message, line, column) => ({
37
+ _tag: "ParseError",
38
+ message,
39
+ line,
40
+ column
41
+ });
42
+ var IoError = (message, path, cause) => ({
43
+ _tag: "IoError",
44
+ message,
45
+ path,
46
+ cause
47
+ });
48
+ var IndexError = (cause, message) => ({
49
+ _tag: "IndexError",
50
+ cause,
51
+ message
52
+ });
53
+ export {
54
+ INDEX_DIR,
55
+ INDEX_VERSION,
56
+ IndexError,
57
+ IoError,
58
+ ParseError,
59
+ buildIndex,
60
+ computeHash,
61
+ countTokens,
62
+ countTokensApprox,
63
+ countWords,
64
+ createEmptyDocumentIndex,
65
+ createEmptyLinkIndex,
66
+ createEmptySectionIndex,
67
+ createStorage,
68
+ freeEncoder,
69
+ getBrokenLinks,
70
+ getIncomingLinks,
71
+ getIndexPaths,
72
+ getOutgoingLinks,
73
+ indexExists,
74
+ initializeIndex,
75
+ loadConfig,
76
+ loadDocumentIndex,
77
+ loadLinkIndex,
78
+ loadSectionIndex,
79
+ parse,
80
+ parseFile,
81
+ saveConfig,
82
+ saveDocumentIndex,
83
+ saveLinkIndex,
84
+ saveSectionIndex,
85
+ watchDirectory
86
+ };
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node