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.
- package/.changeset/config.json +9 -9
- package/.claude/settings.local.json +25 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +85 -0
- package/CONTRIBUTING.md +186 -0
- package/NOTES/NOTES +44 -0
- package/README.md +206 -3
- package/biome.json +1 -1
- package/dist/chunk-23UPXDNL.js +3044 -0
- package/dist/chunk-2W7MO2DL.js +1366 -0
- package/dist/chunk-3NUAZGMA.js +1689 -0
- package/dist/chunk-7TOWB2XB.js +366 -0
- package/dist/chunk-7XOTOADQ.js +3065 -0
- package/dist/chunk-AH2PDM2K.js +3042 -0
- package/dist/chunk-BNXWSZ63.js +3742 -0
- package/dist/chunk-BTL5DJVU.js +3222 -0
- package/dist/chunk-HDHYG7E4.js +104 -0
- package/dist/chunk-HLR4KZBP.js +3234 -0
- package/dist/chunk-IP3FRFEB.js +1045 -0
- package/dist/chunk-KHU56VDO.js +3042 -0
- package/dist/chunk-KRYIFLQR.js +85 -89
- package/dist/chunk-LBSDNLEM.js +287 -0
- package/dist/chunk-MNTQ7HCP.js +2643 -0
- package/dist/chunk-MUJELQQ6.js +1387 -0
- package/dist/chunk-MXJGMSLV.js +2199 -0
- package/dist/chunk-N6QJGC3Z.js +2636 -0
- package/dist/chunk-OBELGBPM.js +1713 -0
- package/dist/chunk-OT7R5XTA.js +3192 -0
- package/dist/chunk-P7X4RA2T.js +106 -0
- package/dist/chunk-PIDUQNC2.js +3185 -0
- package/dist/chunk-POGCDIH4.js +3187 -0
- package/dist/chunk-PSIEOQGZ.js +3043 -0
- package/dist/chunk-PVRT3IHA.js +3238 -0
- package/dist/chunk-QNN4TT23.js +1430 -0
- package/dist/chunk-RE3R45RJ.js +3042 -0
- package/dist/chunk-S7E6TFX6.js +718 -657
- package/dist/chunk-SG6GLU4U.js +1378 -0
- package/dist/chunk-SJCDV2ST.js +274 -0
- package/dist/chunk-SYE5XLF3.js +104 -0
- package/dist/chunk-T5VLYBZD.js +103 -0
- package/dist/chunk-TOQB7VWU.js +3238 -0
- package/dist/chunk-VFNMZ4ZQ.js +3228 -0
- package/dist/chunk-VVTGZNBT.js +1533 -1423
- package/dist/chunk-W7Q4RFEV.js +104 -0
- package/dist/chunk-XTYYVRLO.js +3190 -0
- package/dist/chunk-Y6MDYVJD.js +3063 -0
- package/dist/cli/main.js +4072 -629
- package/dist/index.d.ts +420 -33
- package/dist/index.js +8 -15
- package/dist/mcp/server.js +103 -7
- package/dist/schema-BAWSG7KY.js +22 -0
- package/dist/schema-E3QUPL26.js +20 -0
- package/dist/schema-EHL7WUT6.js +20 -0
- package/docs/019-USAGE.md +44 -5
- package/docs/020-current-implementation.md +8 -8
- package/docs/021-DOGFOODING-FINDINGS.md +1 -1
- package/docs/CONFIG.md +1123 -0
- package/docs/ERRORS.md +383 -0
- package/docs/summarization.md +320 -0
- package/justfile +40 -0
- package/package.json +39 -33
- package/research/INDEX.md +315 -0
- package/research/code-review/README.md +90 -0
- package/research/code-review/cli-error-handling-review.md +979 -0
- package/research/code-review/code-review-validation-report.md +464 -0
- package/research/code-review/main-ts-review.md +1128 -0
- package/research/config-docs/SUMMARY.md +357 -0
- package/research/config-docs/TEST-RESULTS.md +776 -0
- package/research/config-docs/TODO.md +542 -0
- package/research/config-docs/analysis.md +744 -0
- package/research/config-docs/fix-validation.md +502 -0
- package/research/config-docs/help-audit.md +264 -0
- package/research/config-docs/help-system-analysis.md +890 -0
- package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
- package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
- package/research/issue-review.md +603 -0
- package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
- package/research/llm-summarization/alternative-providers-2026.md +1428 -0
- package/research/llm-summarization/anthropic-2026.md +367 -0
- package/research/llm-summarization/claude-cli-integration.md +1706 -0
- package/research/llm-summarization/cli-integration-patterns.md +3155 -0
- package/research/llm-summarization/openai-2026.md +473 -0
- package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
- package/research/llm-summarization/opencode-cli-integration.md +1552 -0
- package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
- package/research/llm-summarization/prototype-results.md +56 -0
- package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
- package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
- package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
- package/research/mdcontext-pudding/01-index-embed.md +956 -0
- package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
- package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
- package/research/mdcontext-pudding/02-search.md +970 -0
- package/research/mdcontext-pudding/03-context.md +779 -0
- package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
- package/research/mdcontext-pudding/04-tree.md +704 -0
- package/research/mdcontext-pudding/05-config.md +1038 -0
- package/research/mdcontext-pudding/06-links-summary.txt +87 -0
- package/research/mdcontext-pudding/06-links.md +679 -0
- package/research/mdcontext-pudding/07-stats.md +693 -0
- package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
- package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
- package/research/mdcontext-pudding/README.md +168 -0
- package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
- package/research/research-quality-review.md +834 -0
- package/research/semantic-search/embedding-text-analysis.md +156 -0
- package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
- package/research/semantic-search/query-processing-analysis.md +207 -0
- package/research/semantic-search/root-cause-and-solution.md +114 -0
- package/research/semantic-search/threshold-validation-report.md +69 -0
- package/research/semantic-search/vector-search-analysis.md +63 -0
- package/research/test-path-issues.md +276 -0
- package/review/ALP-76/1-error-type-design.md +962 -0
- package/review/ALP-76/2-error-handling-patterns.md +906 -0
- package/review/ALP-76/3-error-presentation.md +624 -0
- package/review/ALP-76/4-test-coverage.md +625 -0
- package/review/ALP-76/5-migration-completeness.md +440 -0
- package/review/ALP-76/6-effect-best-practices.md +755 -0
- package/scripts/apply-branch-protection.sh +47 -0
- package/scripts/branch-protection-templates.json +79 -0
- package/scripts/prototype-summarization.ts +346 -0
- package/scripts/rebuild-hnswlib.js +32 -37
- package/scripts/setup-branch-protection.sh +64 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
- package/src/cli/argv-preprocessor.test.ts +2 -2
- package/src/cli/cli.test.ts +230 -33
- package/src/cli/commands/config-cmd.ts +642 -0
- package/src/cli/commands/context.ts +97 -9
- package/src/cli/commands/duplicates.ts +122 -0
- package/src/cli/commands/embeddings.ts +529 -0
- package/src/cli/commands/index-cmd.ts +210 -30
- package/src/cli/commands/index.ts +3 -0
- package/src/cli/commands/search.ts +894 -64
- package/src/cli/commands/stats.ts +3 -0
- package/src/cli/commands/tree.ts +26 -5
- package/src/cli/config-layer.ts +176 -0
- package/src/cli/error-handler.test.ts +235 -0
- package/src/cli/error-handler.ts +655 -0
- package/src/cli/flag-schemas.ts +66 -0
- package/src/cli/help.ts +209 -7
- package/src/cli/main.ts +348 -58
- package/src/cli/options.ts +10 -0
- package/src/cli/shared-error-handling.ts +199 -0
- package/src/cli/utils.ts +150 -17
- package/src/config/file-provider.test.ts +320 -0
- package/src/config/file-provider.ts +273 -0
- package/src/config/index.ts +72 -0
- package/src/config/integration.test.ts +667 -0
- package/src/config/precedence.test.ts +277 -0
- package/src/config/precedence.ts +451 -0
- package/src/config/schema.test.ts +414 -0
- package/src/config/schema.ts +603 -0
- package/src/config/service.test.ts +320 -0
- package/src/config/service.ts +243 -0
- package/src/config/testing.test.ts +264 -0
- package/src/config/testing.ts +110 -0
- package/src/core/types.ts +6 -33
- package/src/duplicates/detector.test.ts +183 -0
- package/src/duplicates/detector.ts +414 -0
- package/src/duplicates/index.ts +18 -0
- package/src/embeddings/embedding-namespace.test.ts +300 -0
- package/src/embeddings/embedding-namespace.ts +947 -0
- package/src/embeddings/heading-boost.test.ts +222 -0
- package/src/embeddings/hnsw-build-options.test.ts +198 -0
- package/src/embeddings/hyde.test.ts +272 -0
- package/src/embeddings/hyde.ts +264 -0
- package/src/embeddings/index.ts +2 -0
- package/src/embeddings/openai-provider.ts +332 -83
- package/src/embeddings/pricing.json +22 -0
- package/src/embeddings/provider-constants.ts +204 -0
- package/src/embeddings/provider-errors.test.ts +967 -0
- package/src/embeddings/provider-errors.ts +565 -0
- package/src/embeddings/provider-factory.test.ts +240 -0
- package/src/embeddings/provider-factory.ts +225 -0
- package/src/embeddings/provider-integration.test.ts +788 -0
- package/src/embeddings/query-preprocessing.test.ts +187 -0
- package/src/embeddings/semantic-search-threshold.test.ts +508 -0
- package/src/embeddings/semantic-search.ts +780 -93
- package/src/embeddings/types.ts +293 -16
- package/src/embeddings/vector-store.ts +486 -77
- package/src/embeddings/voyage-provider.ts +313 -0
- package/src/errors/errors.test.ts +845 -0
- package/src/errors/index.ts +533 -0
- package/src/index/ignore-patterns.test.ts +354 -0
- package/src/index/ignore-patterns.ts +305 -0
- package/src/index/indexer.ts +286 -48
- package/src/index/storage.ts +94 -30
- package/src/index/types.ts +40 -2
- package/src/index/watcher.ts +67 -9
- package/src/index.ts +22 -0
- package/src/integration/search-keyword.test.ts +678 -0
- package/src/mcp/server.ts +135 -6
- package/src/parser/parser.ts +18 -19
- package/src/parser/section-filter.test.ts +277 -0
- package/src/parser/section-filter.ts +125 -3
- package/src/search/__tests__/hybrid-search.test.ts +650 -0
- package/src/search/bm25-store.ts +366 -0
- package/src/search/cross-encoder.test.ts +253 -0
- package/src/search/cross-encoder.ts +406 -0
- package/src/search/fuzzy-search.test.ts +419 -0
- package/src/search/fuzzy-search.ts +273 -0
- package/src/search/hybrid-search.ts +448 -0
- package/src/search/path-matcher.test.ts +276 -0
- package/src/search/path-matcher.ts +33 -0
- package/src/search/searcher.test.ts +99 -1
- package/src/search/searcher.ts +189 -67
- package/src/search/wink-bm25.d.ts +30 -0
- package/src/summarization/cli-providers/claude.ts +202 -0
- package/src/summarization/cli-providers/detection.test.ts +273 -0
- package/src/summarization/cli-providers/detection.ts +118 -0
- package/src/summarization/cli-providers/index.ts +8 -0
- package/src/summarization/cost.test.ts +139 -0
- package/src/summarization/cost.ts +102 -0
- package/src/summarization/error-handler.test.ts +127 -0
- package/src/summarization/error-handler.ts +111 -0
- package/src/summarization/index.ts +102 -0
- package/src/summarization/pipeline.test.ts +498 -0
- package/src/summarization/pipeline.ts +231 -0
- package/src/summarization/prompts.test.ts +269 -0
- package/src/summarization/prompts.ts +133 -0
- package/src/summarization/provider-factory.test.ts +396 -0
- package/src/summarization/provider-factory.ts +178 -0
- package/src/summarization/types.ts +184 -0
- package/src/summarize/summarizer.ts +104 -35
- package/src/types/huggingface-transformers.d.ts +66 -0
- package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/indexes/documents.json +4 -4
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +14 -0
- package/tests/integration/embed-index.test.ts +712 -0
- package/tests/integration/search-context.test.ts +469 -0
- package/tests/integration/search-semantic.test.ts +522 -0
- package/vitest.config.ts +1 -6
- package/AGENTS.md +0 -46
- package/tests/fixtures/cli/.mdcontext/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/vectors.meta.json +0 -1264
|
@@ -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
|