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.
- package/.changeset/README.md +28 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/release.yml +113 -0
- package/.tldrignore +112 -0
- package/AGENTS.md +46 -0
- package/BACKLOG.md +338 -0
- package/README.md +231 -11
- package/biome.json +36 -0
- package/cspell.config.yaml +14 -0
- package/dist/chunk-KRYIFLQR.js +92 -0
- package/dist/chunk-S7E6TFX6.js +742 -0
- package/dist/chunk-VVTGZNBT.js +1519 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +2015 -0
- package/dist/index.d.ts +266 -0
- package/dist/index.js +86 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +376 -0
- package/docs/019-USAGE.md +586 -0
- package/docs/020-current-implementation.md +364 -0
- package/docs/021-DOGFOODING-FINDINGS.md +175 -0
- package/docs/BACKLOG.md +80 -0
- package/docs/DESIGN.md +439 -0
- package/docs/PROJECT.md +88 -0
- package/docs/ROADMAP.md +407 -0
- package/docs/test-links.md +9 -0
- package/package.json +69 -10
- package/pnpm-workspace.yaml +5 -0
- package/research/config-analysis/01-current-implementation.md +470 -0
- package/research/config-analysis/02-strategy-recommendation.md +428 -0
- package/research/config-analysis/03-task-candidates.md +715 -0
- package/research/config-analysis/033-research-configuration-management.md +828 -0
- package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
- package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
- package/research/dogfood/consolidated-tool-evaluation.md +373 -0
- package/research/dogfood/strategy-a/a-synthesis.md +184 -0
- package/research/dogfood/strategy-a/a1-docs.md +226 -0
- package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
- package/research/dogfood/strategy-a/a3-llm.md +164 -0
- package/research/dogfood/strategy-b/b-synthesis.md +228 -0
- package/research/dogfood/strategy-b/b1-architecture.md +207 -0
- package/research/dogfood/strategy-b/b2-gaps.md +258 -0
- package/research/dogfood/strategy-b/b3-workflows.md +250 -0
- package/research/dogfood/strategy-c/c-synthesis.md +451 -0
- package/research/dogfood/strategy-c/c1-explorer.md +192 -0
- package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
- package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
- package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
- package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
- package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
- package/research/effect-cli-error-handling.md +845 -0
- package/research/effect-errors-as-values.md +943 -0
- package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
- package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
- package/research/errors-task-analysis/embeddings-analysis.md +709 -0
- package/research/errors-task-analysis/index-search-analysis.md +812 -0
- package/research/mdcontext-error-analysis.md +521 -0
- package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
- package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
- package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
- package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
- package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
- package/research/semantic-search/002-research-embedding-models.md +490 -0
- package/research/semantic-search/003-research-rag-alternatives.md +523 -0
- package/research/semantic-search/004-research-vector-search.md +841 -0
- package/research/semantic-search/032-research-semantic-search.md +427 -0
- package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
- package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
- package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
- package/research/task-management-2026/03-lightweight-file-based.md +567 -0
- package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
- package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
- package/research/task-management-2026/linear/02-api-integrations.md +930 -0
- package/research/task-management-2026/linear/03-ai-features.md +368 -0
- package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
- package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
- package/scripts/rebuild-hnswlib.js +63 -0
- package/src/cli/argv-preprocessor.test.ts +210 -0
- package/src/cli/argv-preprocessor.ts +202 -0
- package/src/cli/cli.test.ts +430 -0
- package/src/cli/commands/backlinks.ts +54 -0
- package/src/cli/commands/context.ts +197 -0
- package/src/cli/commands/index-cmd.ts +300 -0
- package/src/cli/commands/index.ts +13 -0
- package/src/cli/commands/links.ts +52 -0
- package/src/cli/commands/search.ts +451 -0
- package/src/cli/commands/stats.ts +146 -0
- package/src/cli/commands/tree.ts +107 -0
- package/src/cli/flag-schemas.ts +275 -0
- package/src/cli/help.ts +386 -0
- package/src/cli/index.ts +9 -0
- package/src/cli/main.ts +145 -0
- package/src/cli/options.ts +31 -0
- package/src/cli/typo-suggester.test.ts +105 -0
- package/src/cli/typo-suggester.ts +130 -0
- package/src/cli/utils.ts +126 -0
- package/src/core/index.ts +1 -0
- package/src/core/types.ts +140 -0
- package/src/embeddings/index.ts +8 -0
- package/src/embeddings/openai-provider.ts +165 -0
- package/src/embeddings/semantic-search.ts +583 -0
- package/src/embeddings/types.ts +82 -0
- package/src/embeddings/vector-store.ts +299 -0
- package/src/index/index.ts +4 -0
- package/src/index/indexer.ts +446 -0
- package/src/index/storage.ts +196 -0
- package/src/index/types.ts +109 -0
- package/src/index/watcher.ts +131 -0
- package/src/index.ts +8 -0
- package/src/mcp/server.ts +483 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.test.ts +291 -0
- package/src/parser/parser.ts +395 -0
- package/src/parser/section-filter.ts +270 -0
- package/src/search/query-parser.test.ts +260 -0
- package/src/search/query-parser.ts +319 -0
- package/src/search/searcher.test.ts +182 -0
- package/src/search/searcher.ts +602 -0
- package/src/summarize/budget-bugs.test.ts +620 -0
- package/src/summarize/formatters.ts +419 -0
- package/src/summarize/index.ts +20 -0
- package/src/summarize/summarizer.test.ts +275 -0
- package/src/summarize/summarizer.ts +528 -0
- package/src/summarize/verify-bugs.test.ts +238 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/tokens.test.ts +142 -0
- package/src/utils/tokens.ts +186 -0
- package/tests/fixtures/cli/.mdcontext/config.json +8 -0
- package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
- package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +233 -0
- package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/vectors.meta.json +1264 -0
- package/tests/fixtures/cli/README.md +9 -0
- package/tests/fixtures/cli/api-reference.md +11 -0
- package/tests/fixtures/cli/getting-started.md +11 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +21 -0
- package/vitest.setup.ts +12 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index data types for mdcontext
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Configuration
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
export interface IndexConfig {
|
|
10
|
+
readonly version: number
|
|
11
|
+
readonly rootPath: string
|
|
12
|
+
readonly include: readonly string[]
|
|
13
|
+
readonly exclude: readonly string[]
|
|
14
|
+
readonly createdAt: string
|
|
15
|
+
readonly updatedAt: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Document Index
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
export interface DocumentIndex {
|
|
23
|
+
readonly version: number
|
|
24
|
+
readonly rootPath: string
|
|
25
|
+
readonly documents: Record<string, DocumentEntry>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DocumentEntry {
|
|
29
|
+
readonly id: string
|
|
30
|
+
readonly path: string
|
|
31
|
+
readonly title: string
|
|
32
|
+
readonly mtime: number
|
|
33
|
+
readonly hash: string
|
|
34
|
+
readonly tokenCount: number
|
|
35
|
+
readonly sectionCount: number
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Section Index
|
|
40
|
+
// ============================================================================
|
|
41
|
+
|
|
42
|
+
export interface SectionIndex {
|
|
43
|
+
readonly version: number
|
|
44
|
+
readonly sections: Record<string, SectionEntry>
|
|
45
|
+
readonly byHeading: Record<string, readonly string[]>
|
|
46
|
+
readonly byDocument: Record<string, readonly string[]>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface SectionEntry {
|
|
50
|
+
readonly id: string
|
|
51
|
+
readonly documentId: string
|
|
52
|
+
readonly documentPath: string
|
|
53
|
+
readonly heading: string
|
|
54
|
+
readonly level: number
|
|
55
|
+
readonly startLine: number
|
|
56
|
+
readonly endLine: number
|
|
57
|
+
readonly tokenCount: number
|
|
58
|
+
readonly hasCode: boolean
|
|
59
|
+
readonly hasList: boolean
|
|
60
|
+
readonly hasTable: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Link Index
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
export interface LinkIndex {
|
|
68
|
+
readonly version: number
|
|
69
|
+
readonly forward: Record<string, readonly string[]>
|
|
70
|
+
readonly backward: Record<string, readonly string[]>
|
|
71
|
+
readonly broken: readonly string[]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Index Result
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
export interface IndexResult {
|
|
79
|
+
readonly documentsIndexed: number
|
|
80
|
+
readonly sectionsIndexed: number
|
|
81
|
+
readonly linksIndexed: number
|
|
82
|
+
readonly totalDocuments: number
|
|
83
|
+
readonly totalSections: number
|
|
84
|
+
readonly totalLinks: number
|
|
85
|
+
readonly duration: number
|
|
86
|
+
readonly errors: readonly IndexBuildError[]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface IndexBuildError {
|
|
90
|
+
readonly path: string
|
|
91
|
+
readonly message: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Index Paths
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
export const INDEX_DIR = '.mdcontext'
|
|
99
|
+
export const INDEX_VERSION = 1
|
|
100
|
+
|
|
101
|
+
export const getIndexPaths = (rootPath: string) => ({
|
|
102
|
+
root: `${rootPath}/${INDEX_DIR}`,
|
|
103
|
+
config: `${rootPath}/${INDEX_DIR}/config.json`,
|
|
104
|
+
documents: `${rootPath}/${INDEX_DIR}/indexes/documents.json`,
|
|
105
|
+
sections: `${rootPath}/${INDEX_DIR}/indexes/sections.json`,
|
|
106
|
+
links: `${rootPath}/${INDEX_DIR}/indexes/links.json`,
|
|
107
|
+
cache: `${rootPath}/${INDEX_DIR}/cache`,
|
|
108
|
+
parsed: `${rootPath}/${INDEX_DIR}/cache/parsed`,
|
|
109
|
+
})
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File watcher for automatic re-indexing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as path from 'node:path'
|
|
6
|
+
import { watch } from 'chokidar'
|
|
7
|
+
import { Effect } from 'effect'
|
|
8
|
+
|
|
9
|
+
import { buildIndex, type IndexOptions } from './indexer.js'
|
|
10
|
+
import { createStorage, indexExists } from './storage.js'
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Watcher Types
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
export interface WatcherOptions extends IndexOptions {
|
|
17
|
+
readonly debounceMs?: number
|
|
18
|
+
readonly onIndex?: (result: {
|
|
19
|
+
documentsIndexed: number
|
|
20
|
+
duration: number
|
|
21
|
+
}) => void
|
|
22
|
+
readonly onError?: (error: Error) => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Watcher {
|
|
26
|
+
readonly stop: () => void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Watcher Implementation
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
const isMarkdownFile = (filePath: string): boolean =>
|
|
34
|
+
filePath.endsWith('.md') || filePath.endsWith('.mdx')
|
|
35
|
+
|
|
36
|
+
export const watchDirectory = (
|
|
37
|
+
rootPath: string,
|
|
38
|
+
options: WatcherOptions = {},
|
|
39
|
+
): Effect.Effect<Watcher, Error> =>
|
|
40
|
+
Effect.gen(function* () {
|
|
41
|
+
const resolvedRoot = path.resolve(rootPath)
|
|
42
|
+
const storage = createStorage(resolvedRoot)
|
|
43
|
+
const debounceMs = options.debounceMs ?? 300
|
|
44
|
+
|
|
45
|
+
// Ensure index exists
|
|
46
|
+
const exists = yield* indexExists(storage)
|
|
47
|
+
if (!exists) {
|
|
48
|
+
// Build initial index
|
|
49
|
+
const result = yield* buildIndex(resolvedRoot, options)
|
|
50
|
+
options.onIndex?.({
|
|
51
|
+
documentsIndexed: result.documentsIndexed,
|
|
52
|
+
duration: result.duration,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Create a debounce queue
|
|
57
|
+
const pendingPaths = new Set<string>()
|
|
58
|
+
let debounceTimer: NodeJS.Timeout | null = null
|
|
59
|
+
|
|
60
|
+
const scheduleReindex = () => {
|
|
61
|
+
if (debounceTimer) {
|
|
62
|
+
clearTimeout(debounceTimer)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
debounceTimer = setTimeout(async () => {
|
|
66
|
+
if (pendingPaths.size === 0) return
|
|
67
|
+
|
|
68
|
+
pendingPaths.clear()
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const result = await Effect.runPromise(
|
|
72
|
+
buildIndex(resolvedRoot, options),
|
|
73
|
+
)
|
|
74
|
+
options.onIndex?.({
|
|
75
|
+
documentsIndexed: result.documentsIndexed,
|
|
76
|
+
duration: result.duration,
|
|
77
|
+
})
|
|
78
|
+
} catch (error) {
|
|
79
|
+
options.onError?.(
|
|
80
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
}, debounceMs)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Set up chokidar watcher
|
|
87
|
+
const watcher = watch(resolvedRoot, {
|
|
88
|
+
ignored: [
|
|
89
|
+
/(^|[/\\])\../, // Ignore dotfiles
|
|
90
|
+
'**/node_modules/**',
|
|
91
|
+
],
|
|
92
|
+
persistent: true,
|
|
93
|
+
ignoreInitial: true,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
watcher.on('add', (filePath) => {
|
|
97
|
+
if (isMarkdownFile(filePath)) {
|
|
98
|
+
pendingPaths.add(filePath)
|
|
99
|
+
scheduleReindex()
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
watcher.on('change', (filePath) => {
|
|
104
|
+
if (isMarkdownFile(filePath)) {
|
|
105
|
+
pendingPaths.add(filePath)
|
|
106
|
+
scheduleReindex()
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
watcher.on('unlink', (filePath) => {
|
|
111
|
+
if (isMarkdownFile(filePath)) {
|
|
112
|
+
pendingPaths.add(filePath)
|
|
113
|
+
scheduleReindex()
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
watcher.on('error', (error: unknown) => {
|
|
118
|
+
options.onError?.(
|
|
119
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
120
|
+
)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
stop: () => {
|
|
125
|
+
if (debounceTimer) {
|
|
126
|
+
clearTimeout(debounceTimer)
|
|
127
|
+
}
|
|
128
|
+
watcher.close()
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
})
|