mdcontext 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +28 -0
- package/.changeset/config.json +11 -0
- package/.claude/settings.local.json +25 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +85 -0
- package/.github/workflows/release.yml +113 -0
- package/.tldrignore +112 -0
- package/BACKLOG.md +338 -0
- package/CONTRIBUTING.md +186 -0
- package/NOTES/NOTES +44 -0
- package/README.md +434 -11
- package/biome.json +36 -0
- package/cspell.config.yaml +14 -0
- 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 +88 -0
- 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 +803 -0
- 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 +1629 -0
- 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.d.ts +1 -0
- package/dist/cli/main.js +5458 -0
- package/dist/index.d.ts +653 -0
- package/dist/index.js +79 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +472 -0
- 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 +625 -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/CONFIG.md +1123 -0
- package/docs/DESIGN.md +439 -0
- package/docs/ERRORS.md +383 -0
- package/docs/PROJECT.md +88 -0
- package/docs/ROADMAP.md +407 -0
- package/docs/summarization.md +320 -0
- package/docs/test-links.md +9 -0
- package/justfile +40 -0
- package/package.json +74 -9
- package/pnpm-workspace.yaml +5 -0
- 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-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/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/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/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-error-analysis.md +521 -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/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/research-quality-review.md +834 -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/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/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/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 +58 -0
- 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 +210 -0
- package/src/cli/argv-preprocessor.ts +202 -0
- package/src/cli/cli.test.ts +627 -0
- package/src/cli/commands/backlinks.ts +54 -0
- package/src/cli/commands/config-cmd.ts +642 -0
- package/src/cli/commands/context.ts +285 -0
- package/src/cli/commands/duplicates.ts +122 -0
- package/src/cli/commands/embeddings.ts +529 -0
- package/src/cli/commands/index-cmd.ts +480 -0
- package/src/cli/commands/index.ts +16 -0
- package/src/cli/commands/links.ts +52 -0
- package/src/cli/commands/search.ts +1281 -0
- package/src/cli/commands/stats.ts +149 -0
- package/src/cli/commands/tree.ts +128 -0
- 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 +341 -0
- package/src/cli/help.ts +588 -0
- package/src/cli/index.ts +9 -0
- package/src/cli/main.ts +435 -0
- package/src/cli/options.ts +41 -0
- package/src/cli/shared-error-handling.ts +199 -0
- package/src/cli/typo-suggester.test.ts +105 -0
- package/src/cli/typo-suggester.ts +130 -0
- package/src/cli/utils.ts +259 -0
- 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/index.ts +1 -0
- package/src/core/types.ts +113 -0
- 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 +10 -0
- package/src/embeddings/openai-provider.ts +414 -0
- 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 +1270 -0
- package/src/embeddings/types.ts +359 -0
- package/src/embeddings/vector-store.ts +708 -0
- 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/index.ts +4 -0
- package/src/index/indexer.ts +684 -0
- package/src/index/storage.ts +260 -0
- package/src/index/types.ts +147 -0
- package/src/index/watcher.ts +189 -0
- package/src/index.ts +30 -0
- package/src/integration/search-keyword.test.ts +678 -0
- package/src/mcp/server.ts +612 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.test.ts +291 -0
- package/src/parser/parser.ts +394 -0
- package/src/parser/section-filter.test.ts +277 -0
- package/src/parser/section-filter.ts +392 -0
- 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/query-parser.test.ts +260 -0
- package/src/search/query-parser.ts +319 -0
- package/src/search/searcher.test.ts +280 -0
- package/src/search/searcher.ts +724 -0
- 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/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 +597 -0
- package/src/summarize/verify-bugs.test.ts +238 -0
- package/src/types/huggingface-transformers.d.ts +66 -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/active-provider.json +7 -0
- package/tests/fixtures/cli/.mdcontext/config.json +8 -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 +33 -0
- package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +247 -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/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/tsconfig.json +26 -0
- package/vitest.config.ts +16 -0
- package/vitest.setup.ts +12 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Precedence Chain
|
|
3
|
+
*
|
|
4
|
+
* Composes ConfigProviders to establish the standard CLI config precedence:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* CLI Flags (highest priority)
|
|
8
|
+
* ↓
|
|
9
|
+
* Environment Variables (MDCONTEXT_*)
|
|
10
|
+
* ↓
|
|
11
|
+
* Config File (mdcontext.config.ts/json)
|
|
12
|
+
* ↓
|
|
13
|
+
* Defaults (lowest priority)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Uses a flattened Map approach to avoid memory issues with deep orElse chains.
|
|
17
|
+
*
|
|
18
|
+
* ## Usage
|
|
19
|
+
*
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createConfigProvider, ConfigProviderOptions } from './config/precedence.js'
|
|
22
|
+
* import { Effect } from 'effect'
|
|
23
|
+
*
|
|
24
|
+
* const options: ConfigProviderOptions = {
|
|
25
|
+
* cliOverrides: { index: { maxDepth: 5 } }, // From CLI flags
|
|
26
|
+
* configPath: './custom.config.json', // Optional explicit path
|
|
27
|
+
* workingDir: process.cwd(), // For config file search
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* const provider = await Effect.runPromise(createConfigProvider(options))
|
|
31
|
+
* // Use provider with Effect.withConfigProvider
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { ConfigProvider, Effect } from 'effect'
|
|
36
|
+
import type { ConfigError } from '../errors/index.js'
|
|
37
|
+
import { loadConfigFile, loadConfigFromPath } from './file-provider.js'
|
|
38
|
+
import type { PartialMdContextConfig } from './service.js'
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Types
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Options for creating the config provider chain
|
|
46
|
+
*/
|
|
47
|
+
export interface ConfigProviderOptions {
|
|
48
|
+
/**
|
|
49
|
+
* CLI flag overrides (highest priority)
|
|
50
|
+
* These values take precedence over all other sources
|
|
51
|
+
*/
|
|
52
|
+
cliOverrides?: PartialMdContextConfig
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Explicit path to config file
|
|
56
|
+
* If provided, this file is used instead of searching
|
|
57
|
+
*/
|
|
58
|
+
configPath?: string
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Working directory for config file search
|
|
62
|
+
* Defaults to process.cwd()
|
|
63
|
+
*/
|
|
64
|
+
workingDir?: string
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Environment variable prefix
|
|
68
|
+
* Defaults to 'MDCONTEXT'
|
|
69
|
+
* Variables are expected in format: MDCONTEXT_INDEX_MAXDEPTH
|
|
70
|
+
*/
|
|
71
|
+
envPrefix?: string
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Skip loading config file entirely
|
|
75
|
+
* Useful for testing or when only using env/CLI config
|
|
76
|
+
*/
|
|
77
|
+
skipConfigFile?: boolean
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Skip environment variable provider
|
|
81
|
+
* Useful for testing
|
|
82
|
+
*/
|
|
83
|
+
skipEnv?: boolean
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Flattening Utilities
|
|
88
|
+
// ============================================================================
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Flatten a nested config object into dot-separated key-value pairs.
|
|
92
|
+
*
|
|
93
|
+
* Example:
|
|
94
|
+
* ```
|
|
95
|
+
* { index: { maxDepth: 5 } } -> Map([['index.maxDepth', '5']])
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export const flattenConfig = (
|
|
99
|
+
config: PartialMdContextConfig,
|
|
100
|
+
prefix = '',
|
|
101
|
+
): Map<string, string> => {
|
|
102
|
+
const result = new Map<string, string>()
|
|
103
|
+
|
|
104
|
+
const flatten = (obj: unknown, currentPrefix: string): void => {
|
|
105
|
+
if (obj === null || obj === undefined) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (Array.isArray(obj)) {
|
|
110
|
+
// Convert arrays to comma-separated strings
|
|
111
|
+
result.set(currentPrefix, obj.join(','))
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (typeof obj === 'object') {
|
|
116
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
117
|
+
const newKey = currentPrefix ? `${currentPrefix}.${key}` : key
|
|
118
|
+
flatten(value, newKey)
|
|
119
|
+
}
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Primitive values
|
|
124
|
+
result.set(currentPrefix, String(obj))
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
flatten(config, prefix)
|
|
128
|
+
return result
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// Environment Variable Mapping
|
|
133
|
+
// ============================================================================
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sequence delimiter for array values in environment variables.
|
|
137
|
+
* MDCONTEXT_INDEX_EXCLUDEPATTERNS=node_modules,dist
|
|
138
|
+
*/
|
|
139
|
+
const ENV_SEQ_DELIM = ','
|
|
140
|
+
|
|
141
|
+
// ============================================================================
|
|
142
|
+
// Programmatic ENV_KEY_MAPPING Generation
|
|
143
|
+
// ============================================================================
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Configuration schema structure defining all keys for each section.
|
|
147
|
+
* This is the single source of truth for configuration keys.
|
|
148
|
+
*
|
|
149
|
+
* Adding a new config key:
|
|
150
|
+
* 1. Add it to the appropriate section here
|
|
151
|
+
* 2. Add it to the schema in schema.ts
|
|
152
|
+
* 3. The ENV_KEY_MAPPING is automatically generated
|
|
153
|
+
*/
|
|
154
|
+
export const CONFIG_SCHEMA_KEYS = {
|
|
155
|
+
index: [
|
|
156
|
+
'maxDepth',
|
|
157
|
+
'excludePatterns',
|
|
158
|
+
'fileExtensions',
|
|
159
|
+
'followSymlinks',
|
|
160
|
+
'indexDir',
|
|
161
|
+
],
|
|
162
|
+
search: [
|
|
163
|
+
'defaultLimit',
|
|
164
|
+
'maxLimit',
|
|
165
|
+
'minSimilarity',
|
|
166
|
+
'includeSnippets',
|
|
167
|
+
'snippetLength',
|
|
168
|
+
'autoIndexThreshold',
|
|
169
|
+
],
|
|
170
|
+
embeddings: [
|
|
171
|
+
'provider',
|
|
172
|
+
'baseURL',
|
|
173
|
+
'model',
|
|
174
|
+
'dimensions',
|
|
175
|
+
'batchSize',
|
|
176
|
+
'maxRetries',
|
|
177
|
+
'retryDelayMs',
|
|
178
|
+
'timeoutMs',
|
|
179
|
+
'apiKey',
|
|
180
|
+
],
|
|
181
|
+
summarization: [
|
|
182
|
+
'briefTokenBudget',
|
|
183
|
+
'summaryTokenBudget',
|
|
184
|
+
'compressionRatio',
|
|
185
|
+
'minSectionTokens',
|
|
186
|
+
'maxTopics',
|
|
187
|
+
'minPartialBudget',
|
|
188
|
+
],
|
|
189
|
+
output: ['format', 'color', 'prettyJson', 'verbose', 'debug'],
|
|
190
|
+
paths: ['root', 'configFile', 'cacheDir'],
|
|
191
|
+
} as const
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Generate the ENV_KEY_MAPPING from the schema definition.
|
|
195
|
+
*
|
|
196
|
+
* ENV format: MDCONTEXT_SECTION_KEY (all lowercase)
|
|
197
|
+
* Config format: section.key (camelCase preserved)
|
|
198
|
+
*/
|
|
199
|
+
const generateEnvKeyMapping = (): Record<string, string> => {
|
|
200
|
+
const mapping: Record<string, string> = {}
|
|
201
|
+
for (const [section, keys] of Object.entries(CONFIG_SCHEMA_KEYS)) {
|
|
202
|
+
for (const key of keys) {
|
|
203
|
+
const envKey = `${section}_${key}`.toLowerCase()
|
|
204
|
+
const configKey = `${section}.${key}`
|
|
205
|
+
mapping[envKey] = configKey
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return mapping
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Known config keys for case mapping.
|
|
213
|
+
* Generated programmatically from CONFIG_SCHEMA_KEYS.
|
|
214
|
+
*/
|
|
215
|
+
const ENV_KEY_MAPPING: Record<string, string> = generateEnvKeyMapping()
|
|
216
|
+
|
|
217
|
+
// Type-level completeness check
|
|
218
|
+
type ConfigSchemaKey = {
|
|
219
|
+
[S in keyof typeof CONFIG_SCHEMA_KEYS]: `${S}.${(typeof CONFIG_SCHEMA_KEYS)[S][number]}`
|
|
220
|
+
}[keyof typeof CONFIG_SCHEMA_KEYS]
|
|
221
|
+
|
|
222
|
+
type _MissingMappings = Exclude<
|
|
223
|
+
ConfigSchemaKey,
|
|
224
|
+
(typeof ENV_KEY_MAPPING)[string]
|
|
225
|
+
>
|
|
226
|
+
|
|
227
|
+
// Pure type-level assertion: will fail to compile if any mappings are missing
|
|
228
|
+
type AssertTrue<T extends true> = T
|
|
229
|
+
// @ts-expect-error - Type-level assertion, intentionally unused
|
|
230
|
+
type _CompletenessCheck = AssertTrue<
|
|
231
|
+
_MissingMappings extends never ? true : false
|
|
232
|
+
>
|
|
233
|
+
/**
|
|
234
|
+
* Read environment variables with the given prefix and map them to config keys.
|
|
235
|
+
*
|
|
236
|
+
* @param prefix - Environment variable prefix (default: 'MDCONTEXT')
|
|
237
|
+
* @returns Map of config keys to values
|
|
238
|
+
*/
|
|
239
|
+
export const readEnvConfig = (prefix = 'MDCONTEXT'): Map<string, string> => {
|
|
240
|
+
const result = new Map<string, string>()
|
|
241
|
+
const prefixWithUnderscore = `${prefix}_`
|
|
242
|
+
|
|
243
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
244
|
+
if (key.startsWith(prefixWithUnderscore) && value !== undefined) {
|
|
245
|
+
const envKey = key.slice(prefixWithUnderscore.length).toLowerCase()
|
|
246
|
+
const configKey = ENV_KEY_MAPPING[envKey]
|
|
247
|
+
|
|
248
|
+
if (configKey) {
|
|
249
|
+
result.set(configKey, value)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return result
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Create a ConfigProvider from environment variables with the given prefix.
|
|
259
|
+
* Kept for backwards compatibility.
|
|
260
|
+
*
|
|
261
|
+
* @param prefix - Environment variable prefix (default: 'MDCONTEXT')
|
|
262
|
+
* @returns ConfigProvider that reads from environment
|
|
263
|
+
*/
|
|
264
|
+
export const createEnvConfigProvider = (
|
|
265
|
+
prefix = 'MDCONTEXT',
|
|
266
|
+
): ConfigProvider.ConfigProvider => {
|
|
267
|
+
const envMap = readEnvConfig(prefix)
|
|
268
|
+
return ConfigProvider.fromMap(envMap, {
|
|
269
|
+
pathDelim: '.',
|
|
270
|
+
seqDelim: ENV_SEQ_DELIM,
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ============================================================================
|
|
275
|
+
// Combined Provider
|
|
276
|
+
// ============================================================================
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Create the full config provider chain with proper precedence.
|
|
280
|
+
*
|
|
281
|
+
* Precedence (highest to lowest):
|
|
282
|
+
* 1. CLI flags (if provided)
|
|
283
|
+
* 2. Environment variables (MDCONTEXT_*)
|
|
284
|
+
* 3. Config file (if found)
|
|
285
|
+
* 4. Built-in defaults (handled by Config schema)
|
|
286
|
+
*
|
|
287
|
+
* @param options - Configuration options
|
|
288
|
+
* @returns Effect yielding the composed ConfigProvider
|
|
289
|
+
*/
|
|
290
|
+
export const createConfigProvider = (
|
|
291
|
+
options: ConfigProviderOptions = {},
|
|
292
|
+
): Effect.Effect<ConfigProvider.ConfigProvider, ConfigError> =>
|
|
293
|
+
Effect.gen(function* () {
|
|
294
|
+
const {
|
|
295
|
+
cliOverrides,
|
|
296
|
+
configPath,
|
|
297
|
+
workingDir = process.cwd(),
|
|
298
|
+
envPrefix = 'MDCONTEXT',
|
|
299
|
+
skipConfigFile = false,
|
|
300
|
+
skipEnv = false,
|
|
301
|
+
} = options
|
|
302
|
+
|
|
303
|
+
// Build merged config map with precedence (lowest to highest)
|
|
304
|
+
const mergedMap = new Map<string, string>()
|
|
305
|
+
|
|
306
|
+
// 1. File config (lowest priority)
|
|
307
|
+
if (!skipConfigFile) {
|
|
308
|
+
let fileConfig: PartialMdContextConfig | undefined
|
|
309
|
+
|
|
310
|
+
if (configPath) {
|
|
311
|
+
fileConfig = yield* loadConfigFromPath(configPath)
|
|
312
|
+
} else {
|
|
313
|
+
const result = yield* loadConfigFile(workingDir)
|
|
314
|
+
if (result.found) {
|
|
315
|
+
fileConfig = result.config
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (fileConfig) {
|
|
320
|
+
const flattened = flattenConfig(fileConfig)
|
|
321
|
+
for (const [k, v] of flattened) {
|
|
322
|
+
mergedMap.set(k, v)
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// 2. Environment variables (higher priority - overwrites file config)
|
|
328
|
+
if (!skipEnv) {
|
|
329
|
+
const envConfig = readEnvConfig(envPrefix)
|
|
330
|
+
for (const [k, v] of envConfig) {
|
|
331
|
+
mergedMap.set(k, v)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 3. CLI overrides (highest priority - overwrites everything)
|
|
336
|
+
if (cliOverrides && Object.keys(cliOverrides).length > 0) {
|
|
337
|
+
const flattened = flattenConfig(cliOverrides)
|
|
338
|
+
for (const [k, v] of flattened) {
|
|
339
|
+
mergedMap.set(k, v)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return ConfigProvider.fromMap(mergedMap, {
|
|
344
|
+
pathDelim: '.',
|
|
345
|
+
seqDelim: ENV_SEQ_DELIM,
|
|
346
|
+
})
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Create a ConfigProvider chain synchronously (when you don't need file loading).
|
|
351
|
+
*
|
|
352
|
+
* Useful when:
|
|
353
|
+
* - You already have the config file content
|
|
354
|
+
* - You only want env vars and CLI overrides
|
|
355
|
+
* - Testing without file I/O
|
|
356
|
+
*
|
|
357
|
+
* @param options - Configuration options
|
|
358
|
+
* @returns The composed ConfigProvider
|
|
359
|
+
*/
|
|
360
|
+
export const createConfigProviderSync = (
|
|
361
|
+
options: Omit<ConfigProviderOptions, 'configPath' | 'workingDir'> & {
|
|
362
|
+
fileConfig?: PartialMdContextConfig
|
|
363
|
+
} = {},
|
|
364
|
+
): ConfigProvider.ConfigProvider => {
|
|
365
|
+
const {
|
|
366
|
+
cliOverrides,
|
|
367
|
+
fileConfig,
|
|
368
|
+
envPrefix = 'MDCONTEXT',
|
|
369
|
+
skipConfigFile = false,
|
|
370
|
+
skipEnv = false,
|
|
371
|
+
} = options
|
|
372
|
+
|
|
373
|
+
// Build merged config map with precedence (lowest to highest)
|
|
374
|
+
const mergedMap = new Map<string, string>()
|
|
375
|
+
|
|
376
|
+
// 1. File config (lowest priority)
|
|
377
|
+
if (!skipConfigFile && fileConfig) {
|
|
378
|
+
const flattened = flattenConfig(fileConfig)
|
|
379
|
+
for (const [k, v] of flattened) {
|
|
380
|
+
mergedMap.set(k, v)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// 2. Environment variables (higher priority)
|
|
385
|
+
if (!skipEnv) {
|
|
386
|
+
const envConfig = readEnvConfig(envPrefix)
|
|
387
|
+
for (const [k, v] of envConfig) {
|
|
388
|
+
mergedMap.set(k, v)
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 3. CLI overrides (highest priority)
|
|
393
|
+
if (cliOverrides && Object.keys(cliOverrides).length > 0) {
|
|
394
|
+
const flattened = flattenConfig(cliOverrides)
|
|
395
|
+
for (const [k, v] of flattened) {
|
|
396
|
+
mergedMap.set(k, v)
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return ConfigProvider.fromMap(mergedMap, {
|
|
401
|
+
pathDelim: '.',
|
|
402
|
+
seqDelim: ENV_SEQ_DELIM,
|
|
403
|
+
})
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// ============================================================================
|
|
407
|
+
// Convenience Functions
|
|
408
|
+
// ============================================================================
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Create a minimal ConfigProvider for testing.
|
|
412
|
+
*
|
|
413
|
+
* Includes only CLI overrides and optionally file config.
|
|
414
|
+
* No environment variables are read.
|
|
415
|
+
*
|
|
416
|
+
* @param cliOverrides - CLI flag overrides
|
|
417
|
+
* @param fileConfig - Optional file config values
|
|
418
|
+
* @returns ConfigProvider for testing
|
|
419
|
+
*/
|
|
420
|
+
export const createTestConfigProvider = (
|
|
421
|
+
cliOverrides?: PartialMdContextConfig,
|
|
422
|
+
fileConfig?: PartialMdContextConfig,
|
|
423
|
+
): ConfigProvider.ConfigProvider => {
|
|
424
|
+
const options: Parameters<typeof createConfigProviderSync>[0] = {
|
|
425
|
+
skipEnv: true,
|
|
426
|
+
}
|
|
427
|
+
if (cliOverrides !== undefined) {
|
|
428
|
+
options.cliOverrides = cliOverrides
|
|
429
|
+
}
|
|
430
|
+
if (fileConfig !== undefined) {
|
|
431
|
+
options.fileConfig = fileConfig
|
|
432
|
+
}
|
|
433
|
+
return createConfigProviderSync(options)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Create a ConfigProvider from CLI flag overrides.
|
|
438
|
+
* Kept for backwards compatibility.
|
|
439
|
+
*
|
|
440
|
+
* @param overrides - Partial config from CLI flags
|
|
441
|
+
* @returns ConfigProvider that provides CLI values
|
|
442
|
+
*/
|
|
443
|
+
export const createCliConfigProvider = (
|
|
444
|
+
overrides: PartialMdContextConfig,
|
|
445
|
+
): ConfigProvider.ConfigProvider => {
|
|
446
|
+
const flattened = flattenConfig(overrides)
|
|
447
|
+
return ConfigProvider.fromMap(flattened, {
|
|
448
|
+
pathDelim: '.',
|
|
449
|
+
seqDelim: ENV_SEQ_DELIM,
|
|
450
|
+
})
|
|
451
|
+
}
|