distill-mcp 0.6.0-beta
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/bin/cli.js +133 -0
- package/dist/analytics/session-tracker.d.ts +74 -0
- package/dist/analytics/session-tracker.d.ts.map +1 -0
- package/dist/analytics/session-tracker.js +123 -0
- package/dist/ast/benchmark.test.d.ts +7 -0
- package/dist/ast/benchmark.test.d.ts.map +1 -0
- package/dist/ast/benchmark.test.js +175 -0
- package/dist/ast/go/index.d.ts +9 -0
- package/dist/ast/go/index.d.ts.map +1 -0
- package/dist/ast/go/index.js +8 -0
- package/dist/ast/go/parser.d.ts +31 -0
- package/dist/ast/go/parser.d.ts.map +1 -0
- package/dist/ast/go/parser.js +428 -0
- package/dist/ast/go/parser.test.d.ts +5 -0
- package/dist/ast/go/parser.test.d.ts.map +1 -0
- package/dist/ast/go/parser.test.js +241 -0
- package/dist/ast/go/queries.d.ts +51 -0
- package/dist/ast/go/queries.d.ts.map +1 -0
- package/dist/ast/go/queries.js +114 -0
- package/dist/ast/go/utils.d.ts +66 -0
- package/dist/ast/go/utils.d.ts.map +1 -0
- package/dist/ast/go/utils.js +140 -0
- package/dist/ast/index.d.ts +39 -0
- package/dist/ast/index.d.ts.map +1 -0
- package/dist/ast/index.js +245 -0
- package/dist/ast/php/index.d.ts +9 -0
- package/dist/ast/php/index.d.ts.map +1 -0
- package/dist/ast/php/index.js +8 -0
- package/dist/ast/php/parser.d.ts +31 -0
- package/dist/ast/php/parser.d.ts.map +1 -0
- package/dist/ast/php/parser.js +388 -0
- package/dist/ast/php/parser.test.d.ts +5 -0
- package/dist/ast/php/parser.test.d.ts.map +1 -0
- package/dist/ast/php/parser.test.js +328 -0
- package/dist/ast/php/queries.d.ts +61 -0
- package/dist/ast/php/queries.d.ts.map +1 -0
- package/dist/ast/php/queries.js +117 -0
- package/dist/ast/php/utils.d.ts +83 -0
- package/dist/ast/php/utils.d.ts.map +1 -0
- package/dist/ast/php/utils.js +246 -0
- package/dist/ast/python/index.d.ts +9 -0
- package/dist/ast/python/index.d.ts.map +1 -0
- package/dist/ast/python/index.js +8 -0
- package/dist/ast/python/parser.d.ts +32 -0
- package/dist/ast/python/parser.d.ts.map +1 -0
- package/dist/ast/python/parser.js +422 -0
- package/dist/ast/python/parser.test.d.ts +5 -0
- package/dist/ast/python/parser.test.d.ts.map +1 -0
- package/dist/ast/python/parser.test.js +186 -0
- package/dist/ast/python/queries.d.ts +73 -0
- package/dist/ast/python/queries.d.ts.map +1 -0
- package/dist/ast/python/queries.js +137 -0
- package/dist/ast/python/utils.d.ts +63 -0
- package/dist/ast/python/utils.d.ts.map +1 -0
- package/dist/ast/python/utils.js +159 -0
- package/dist/ast/quick-scan.d.ts +40 -0
- package/dist/ast/quick-scan.d.ts.map +1 -0
- package/dist/ast/quick-scan.js +287 -0
- package/dist/ast/rust/index.d.ts +9 -0
- package/dist/ast/rust/index.d.ts.map +1 -0
- package/dist/ast/rust/index.js +8 -0
- package/dist/ast/rust/parser.d.ts +31 -0
- package/dist/ast/rust/parser.d.ts.map +1 -0
- package/dist/ast/rust/parser.js +416 -0
- package/dist/ast/rust/parser.test.d.ts +5 -0
- package/dist/ast/rust/parser.test.d.ts.map +1 -0
- package/dist/ast/rust/parser.test.js +329 -0
- package/dist/ast/rust/queries.d.ts +66 -0
- package/dist/ast/rust/queries.d.ts.map +1 -0
- package/dist/ast/rust/queries.js +132 -0
- package/dist/ast/rust/utils.d.ts +91 -0
- package/dist/ast/rust/utils.d.ts.map +1 -0
- package/dist/ast/rust/utils.js +254 -0
- package/dist/ast/swift/index.d.ts +10 -0
- package/dist/ast/swift/index.d.ts.map +1 -0
- package/dist/ast/swift/index.js +8 -0
- package/dist/ast/swift/parser.d.ts +31 -0
- package/dist/ast/swift/parser.d.ts.map +1 -0
- package/dist/ast/swift/parser.js +554 -0
- package/dist/ast/swift/parser.test.d.ts +5 -0
- package/dist/ast/swift/parser.test.d.ts.map +1 -0
- package/dist/ast/swift/parser.test.js +398 -0
- package/dist/ast/swift/queries.d.ts +71 -0
- package/dist/ast/swift/queries.d.ts.map +1 -0
- package/dist/ast/swift/queries.js +137 -0
- package/dist/ast/swift/utils.d.ts +94 -0
- package/dist/ast/swift/utils.d.ts.map +1 -0
- package/dist/ast/swift/utils.js +411 -0
- package/dist/ast/types.d.ts +96 -0
- package/dist/ast/types.d.ts.map +1 -0
- package/dist/ast/types.js +21 -0
- package/dist/ast/typescript.d.ts +24 -0
- package/dist/ast/typescript.d.ts.map +1 -0
- package/dist/ast/typescript.js +357 -0
- package/dist/cache/file-hash.d.ts +33 -0
- package/dist/cache/file-hash.d.ts.map +1 -0
- package/dist/cache/file-hash.js +59 -0
- package/dist/cache/index.d.ts +9 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +8 -0
- package/dist/cache/smart-cache.d.ts +68 -0
- package/dist/cache/smart-cache.d.ts.map +1 -0
- package/dist/cache/smart-cache.js +266 -0
- package/dist/cache/types.d.ts +102 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +6 -0
- package/dist/cli/analyze.d.ts +43 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +250 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +127 -0
- package/dist/cli/hooks.d.ts +14 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +229 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/setup.d.ts +10 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +117 -0
- package/dist/cli/utils.d.ts +30 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +116 -0
- package/dist/compressors/config.d.ts +9 -0
- package/dist/compressors/config.d.ts.map +1 -0
- package/dist/compressors/config.js +183 -0
- package/dist/compressors/conversation.d.ts +109 -0
- package/dist/compressors/conversation.d.ts.map +1 -0
- package/dist/compressors/conversation.js +404 -0
- package/dist/compressors/diff.d.ts +35 -0
- package/dist/compressors/diff.d.ts.map +1 -0
- package/dist/compressors/diff.js +389 -0
- package/dist/compressors/generic.d.ts +9 -0
- package/dist/compressors/generic.d.ts.map +1 -0
- package/dist/compressors/generic.js +188 -0
- package/dist/compressors/index.d.ts +31 -0
- package/dist/compressors/index.d.ts.map +1 -0
- package/dist/compressors/index.js +82 -0
- package/dist/compressors/logs.d.ts +9 -0
- package/dist/compressors/logs.d.ts.map +1 -0
- package/dist/compressors/logs.js +245 -0
- package/dist/compressors/multifile.d.ts +106 -0
- package/dist/compressors/multifile.d.ts.map +1 -0
- package/dist/compressors/multifile.js +498 -0
- package/dist/compressors/semantic.d.ts +33 -0
- package/dist/compressors/semantic.d.ts.map +1 -0
- package/dist/compressors/semantic.js +233 -0
- package/dist/compressors/stacktrace.d.ts +9 -0
- package/dist/compressors/stacktrace.d.ts.map +1 -0
- package/dist/compressors/stacktrace.js +259 -0
- package/dist/compressors/types.d.ts +146 -0
- package/dist/compressors/types.d.ts.map +1 -0
- package/dist/compressors/types.js +6 -0
- package/dist/config/output-config.d.ts +56 -0
- package/dist/config/output-config.d.ts.map +1 -0
- package/dist/config/output-config.js +78 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/middleware/chain.d.ts +49 -0
- package/dist/middleware/chain.d.ts.map +1 -0
- package/dist/middleware/chain.js +126 -0
- package/dist/middleware/index.d.ts +4 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/logging.d.ts +8 -0
- package/dist/middleware/logging.d.ts.map +1 -0
- package/dist/middleware/logging.js +71 -0
- package/dist/middleware/types.d.ts +58 -0
- package/dist/middleware/types.d.ts.map +1 -0
- package/dist/middleware/types.js +7 -0
- package/dist/parsers/eslint.d.ts +8 -0
- package/dist/parsers/eslint.d.ts.map +1 -0
- package/dist/parsers/eslint.js +132 -0
- package/dist/parsers/generic.d.ts +8 -0
- package/dist/parsers/generic.d.ts.map +1 -0
- package/dist/parsers/generic.js +234 -0
- package/dist/parsers/index.d.ts +34 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +216 -0
- package/dist/parsers/types.d.ts +84 -0
- package/dist/parsers/types.d.ts.map +1 -0
- package/dist/parsers/types.js +6 -0
- package/dist/parsers/typescript.d.ts +8 -0
- package/dist/parsers/typescript.d.ts.map +1 -0
- package/dist/parsers/typescript.js +107 -0
- package/dist/pipelines/definitions.d.ts +50 -0
- package/dist/pipelines/definitions.d.ts.map +1 -0
- package/dist/pipelines/definitions.js +206 -0
- package/dist/sandbox/executor.d.ts +12 -0
- package/dist/sandbox/executor.d.ts.map +1 -0
- package/dist/sandbox/executor.js +191 -0
- package/dist/sandbox/index.d.ts +11 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +9 -0
- package/dist/sandbox/sandbox.test.d.ts +7 -0
- package/dist/sandbox/sandbox.test.d.ts.map +1 -0
- package/dist/sandbox/sandbox.test.js +202 -0
- package/dist/sandbox/sdk/analyze.d.ts +36 -0
- package/dist/sandbox/sdk/analyze.d.ts.map +1 -0
- package/dist/sandbox/sdk/analyze.js +413 -0
- package/dist/sandbox/sdk/analyze.test.d.ts +7 -0
- package/dist/sandbox/sdk/analyze.test.d.ts.map +1 -0
- package/dist/sandbox/sdk/analyze.test.js +191 -0
- package/dist/sandbox/sdk/code.d.ts +20 -0
- package/dist/sandbox/sdk/code.d.ts.map +1 -0
- package/dist/sandbox/sdk/code.js +104 -0
- package/dist/sandbox/sdk/compress.d.ts +23 -0
- package/dist/sandbox/sdk/compress.d.ts.map +1 -0
- package/dist/sandbox/sdk/compress.js +107 -0
- package/dist/sandbox/sdk/conversation.d.ts +148 -0
- package/dist/sandbox/sdk/conversation.d.ts.map +1 -0
- package/dist/sandbox/sdk/conversation.js +177 -0
- package/dist/sandbox/sdk/files.d.ts +29 -0
- package/dist/sandbox/sdk/files.d.ts.map +1 -0
- package/dist/sandbox/sdk/files.js +41 -0
- package/dist/sandbox/sdk/git.d.ts +37 -0
- package/dist/sandbox/sdk/git.d.ts.map +1 -0
- package/dist/sandbox/sdk/git.js +313 -0
- package/dist/sandbox/sdk/git.test.d.ts +8 -0
- package/dist/sandbox/sdk/git.test.d.ts.map +1 -0
- package/dist/sandbox/sdk/git.test.js +160 -0
- package/dist/sandbox/sdk/index.d.ts +16 -0
- package/dist/sandbox/sdk/index.d.ts.map +1 -0
- package/dist/sandbox/sdk/index.js +15 -0
- package/dist/sandbox/sdk/multifile.d.ts +63 -0
- package/dist/sandbox/sdk/multifile.d.ts.map +1 -0
- package/dist/sandbox/sdk/multifile.js +130 -0
- package/dist/sandbox/sdk/pipeline.d.ts +16 -0
- package/dist/sandbox/sdk/pipeline.d.ts.map +1 -0
- package/dist/sandbox/sdk/pipeline.js +454 -0
- package/dist/sandbox/sdk/pipeline.test.d.ts +7 -0
- package/dist/sandbox/sdk/pipeline.test.d.ts.map +1 -0
- package/dist/sandbox/sdk/pipeline.test.js +197 -0
- package/dist/sandbox/sdk/search.d.ts +36 -0
- package/dist/sandbox/sdk/search.d.ts.map +1 -0
- package/dist/sandbox/sdk/search.js +338 -0
- package/dist/sandbox/sdk/search.test.d.ts +7 -0
- package/dist/sandbox/sdk/search.test.d.ts.map +1 -0
- package/dist/sandbox/sdk/search.test.js +183 -0
- package/dist/sandbox/sdk/utils.d.ts +18 -0
- package/dist/sandbox/sdk/utils.d.ts.map +1 -0
- package/dist/sandbox/sdk/utils.js +24 -0
- package/dist/sandbox/security/code-analyzer.d.ts +15 -0
- package/dist/sandbox/security/code-analyzer.d.ts.map +1 -0
- package/dist/sandbox/security/code-analyzer.js +87 -0
- package/dist/sandbox/security/index.d.ts +6 -0
- package/dist/sandbox/security/index.d.ts.map +1 -0
- package/dist/sandbox/security/index.js +5 -0
- package/dist/sandbox/security/path-validator.d.ts +23 -0
- package/dist/sandbox/security/path-validator.d.ts.map +1 -0
- package/dist/sandbox/security/path-validator.js +113 -0
- package/dist/sandbox/types.d.ts +577 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +14 -0
- package/dist/server.d.ts +36 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +133 -0
- package/dist/summarizers/build-logs.d.ts +11 -0
- package/dist/summarizers/build-logs.d.ts.map +1 -0
- package/dist/summarizers/build-logs.js +234 -0
- package/dist/summarizers/generic.d.ts +11 -0
- package/dist/summarizers/generic.d.ts.map +1 -0
- package/dist/summarizers/generic.js +93 -0
- package/dist/summarizers/index.d.ts +20 -0
- package/dist/summarizers/index.d.ts.map +1 -0
- package/dist/summarizers/index.js +43 -0
- package/dist/summarizers/server-logs.d.ts +11 -0
- package/dist/summarizers/server-logs.d.ts.map +1 -0
- package/dist/summarizers/server-logs.js +215 -0
- package/dist/summarizers/test-logs.d.ts +11 -0
- package/dist/summarizers/test-logs.d.ts.map +1 -0
- package/dist/summarizers/test-logs.js +258 -0
- package/dist/summarizers/types.d.ts +146 -0
- package/dist/summarizers/types.d.ts.map +1 -0
- package/dist/summarizers/types.js +21 -0
- package/dist/tools/analyze-build-output.d.ts +30 -0
- package/dist/tools/analyze-build-output.d.ts.map +1 -0
- package/dist/tools/analyze-build-output.js +45 -0
- package/dist/tools/analyze-context.d.ts +23 -0
- package/dist/tools/analyze-context.d.ts.map +1 -0
- package/dist/tools/analyze-context.js +78 -0
- package/dist/tools/auto-optimize.d.ts +9 -0
- package/dist/tools/auto-optimize.d.ts.map +1 -0
- package/dist/tools/auto-optimize.js +191 -0
- package/dist/tools/code-execute.d.ts +9 -0
- package/dist/tools/code-execute.d.ts.map +1 -0
- package/dist/tools/code-execute.js +84 -0
- package/dist/tools/code-skeleton.d.ts +33 -0
- package/dist/tools/code-skeleton.d.ts.map +1 -0
- package/dist/tools/code-skeleton.js +206 -0
- package/dist/tools/compress-context.d.ts +33 -0
- package/dist/tools/compress-context.d.ts.map +1 -0
- package/dist/tools/compress-context.js +64 -0
- package/dist/tools/context-budget.d.ts +43 -0
- package/dist/tools/context-budget.d.ts.map +1 -0
- package/dist/tools/context-budget.js +260 -0
- package/dist/tools/context-budget.test.d.ts +5 -0
- package/dist/tools/context-budget.test.d.ts.map +1 -0
- package/dist/tools/context-budget.test.js +219 -0
- package/dist/tools/conversation-compress.d.ts +46 -0
- package/dist/tools/conversation-compress.d.ts.map +1 -0
- package/dist/tools/conversation-compress.js +78 -0
- package/dist/tools/conversation-memory.d.ts +75 -0
- package/dist/tools/conversation-memory.d.ts.map +1 -0
- package/dist/tools/conversation-memory.js +289 -0
- package/dist/tools/deduplicate-errors.d.ts +30 -0
- package/dist/tools/deduplicate-errors.d.ts.map +1 -0
- package/dist/tools/deduplicate-errors.js +72 -0
- package/dist/tools/detect-retry-loop.d.ts +40 -0
- package/dist/tools/detect-retry-loop.d.ts.map +1 -0
- package/dist/tools/detect-retry-loop.js +212 -0
- package/dist/tools/diff-compress.d.ts +40 -0
- package/dist/tools/diff-compress.d.ts.map +1 -0
- package/dist/tools/diff-compress.js +94 -0
- package/dist/tools/discover-tools.d.ts +11 -0
- package/dist/tools/discover-tools.d.ts.map +1 -0
- package/dist/tools/discover-tools.js +163 -0
- package/dist/tools/dynamic-loader.d.ts +131 -0
- package/dist/tools/dynamic-loader.d.ts.map +1 -0
- package/dist/tools/dynamic-loader.js +378 -0
- package/dist/tools/dynamic-loader.test.d.ts +10 -0
- package/dist/tools/dynamic-loader.test.d.ts.map +1 -0
- package/dist/tools/dynamic-loader.test.js +164 -0
- package/dist/tools/lazy-mcp.d.ts +31 -0
- package/dist/tools/lazy-mcp.d.ts.map +1 -0
- package/dist/tools/lazy-mcp.js +151 -0
- package/dist/tools/lazy-mcp.test.d.ts +10 -0
- package/dist/tools/lazy-mcp.test.d.ts.map +1 -0
- package/dist/tools/lazy-mcp.test.js +172 -0
- package/dist/tools/multifile-compress.d.ts +36 -0
- package/dist/tools/multifile-compress.d.ts.map +1 -0
- package/dist/tools/multifile-compress.js +223 -0
- package/dist/tools/optimization-tips.d.ts +18 -0
- package/dist/tools/optimization-tips.d.ts.map +1 -0
- package/dist/tools/optimization-tips.js +133 -0
- package/dist/tools/registry.d.ts +70 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +169 -0
- package/dist/tools/semantic-compress.d.ts +39 -0
- package/dist/tools/semantic-compress.d.ts.map +1 -0
- package/dist/tools/semantic-compress.js +113 -0
- package/dist/tools/semantic-compress.test.d.ts +5 -0
- package/dist/tools/semantic-compress.test.d.ts.map +1 -0
- package/dist/tools/semantic-compress.test.js +182 -0
- package/dist/tools/session-stats.d.ts +34 -0
- package/dist/tools/session-stats.d.ts.map +1 -0
- package/dist/tools/session-stats.js +194 -0
- package/dist/tools/set-output-config.d.ts +38 -0
- package/dist/tools/set-output-config.d.ts.map +1 -0
- package/dist/tools/set-output-config.js +122 -0
- package/dist/tools/smart-cache-tool.d.ts +38 -0
- package/dist/tools/smart-cache-tool.d.ts.map +1 -0
- package/dist/tools/smart-cache-tool.js +224 -0
- package/dist/tools/smart-file-read.d.ts +52 -0
- package/dist/tools/smart-file-read.d.ts.map +1 -0
- package/dist/tools/smart-file-read.js +481 -0
- package/dist/tools/smart-pipeline.d.ts +40 -0
- package/dist/tools/smart-pipeline.d.ts.map +1 -0
- package/dist/tools/smart-pipeline.js +295 -0
- package/dist/tools/summarize-logs.d.ts +36 -0
- package/dist/tools/summarize-logs.d.ts.map +1 -0
- package/dist/tools/summarize-logs.js +184 -0
- package/dist/tools/token-budget.test.d.ts +11 -0
- package/dist/tools/token-budget.test.d.ts.map +1 -0
- package/dist/tools/token-budget.test.js +275 -0
- package/dist/utils/bm25.d.ts +86 -0
- package/dist/utils/bm25.d.ts.map +1 -0
- package/dist/utils/bm25.js +153 -0
- package/dist/utils/bm25.test.d.ts +5 -0
- package/dist/utils/bm25.test.d.ts.map +1 -0
- package/dist/utils/bm25.test.js +156 -0
- package/dist/utils/command-normalizer.d.ts +39 -0
- package/dist/utils/command-normalizer.d.ts.map +1 -0
- package/dist/utils/command-normalizer.js +90 -0
- package/dist/utils/content-detector.d.ts +27 -0
- package/dist/utils/content-detector.d.ts.map +1 -0
- package/dist/utils/content-detector.js +127 -0
- package/dist/utils/embeddings.d.ts +54 -0
- package/dist/utils/embeddings.d.ts.map +1 -0
- package/dist/utils/embeddings.js +97 -0
- package/dist/utils/embeddings.test.d.ts +8 -0
- package/dist/utils/embeddings.test.d.ts.map +1 -0
- package/dist/utils/embeddings.test.js +96 -0
- package/dist/utils/error-normalizer.d.ts +39 -0
- package/dist/utils/error-normalizer.d.ts.map +1 -0
- package/dist/utils/error-normalizer.js +233 -0
- package/dist/utils/hybrid-search.d.ts +79 -0
- package/dist/utils/hybrid-search.d.ts.map +1 -0
- package/dist/utils/hybrid-search.js +146 -0
- package/dist/utils/hybrid-search.test.d.ts +5 -0
- package/dist/utils/hybrid-search.test.d.ts.map +1 -0
- package/dist/utils/hybrid-search.test.js +172 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +12 -0
- package/dist/utils/language-detector.d.ts +27 -0
- package/dist/utils/language-detector.d.ts.map +1 -0
- package/dist/utils/language-detector.js +94 -0
- package/dist/utils/log-parser.d.ts +46 -0
- package/dist/utils/log-parser.d.ts.map +1 -0
- package/dist/utils/log-parser.js +287 -0
- package/dist/utils/output-estimator.d.ts +54 -0
- package/dist/utils/output-estimator.d.ts.map +1 -0
- package/dist/utils/output-estimator.js +119 -0
- package/dist/utils/output-estimator.test.d.ts +5 -0
- package/dist/utils/output-estimator.test.d.ts.map +1 -0
- package/dist/utils/output-estimator.test.js +115 -0
- package/dist/utils/output-similarity.d.ts +48 -0
- package/dist/utils/output-similarity.d.ts.map +1 -0
- package/dist/utils/output-similarity.js +140 -0
- package/dist/utils/project-detector.d.ts +16 -0
- package/dist/utils/project-detector.d.ts.map +1 -0
- package/dist/utils/project-detector.js +119 -0
- package/dist/utils/segment-scorer.d.ts +99 -0
- package/dist/utils/segment-scorer.d.ts.map +1 -0
- package/dist/utils/segment-scorer.js +148 -0
- package/dist/utils/signature-grouper.d.ts +58 -0
- package/dist/utils/signature-grouper.d.ts.map +1 -0
- package/dist/utils/signature-grouper.js +185 -0
- package/dist/utils/tfidf.d.ts +45 -0
- package/dist/utils/tfidf.d.ts.map +1 -0
- package/dist/utils/tfidf.js +204 -0
- package/dist/utils/tfidf.test.d.ts +5 -0
- package/dist/utils/tfidf.test.d.ts.map +1 -0
- package/dist/utils/tfidf.test.js +115 -0
- package/dist/utils/token-counter.d.ts +35 -0
- package/dist/utils/token-counter.d.ts.map +1 -0
- package/dist/utils/token-counter.js +83 -0
- package/dist/utils/toon-serializer.d.ts +120 -0
- package/dist/utils/toon-serializer.d.ts.map +1 -0
- package/dist/utils/toon-serializer.js +472 -0
- package/dist/utils/toon-serializer.test.d.ts +7 -0
- package/dist/utils/toon-serializer.test.d.ts.map +1 -0
- package/dist/utils/toon-serializer.test.js +290 -0
- package/package.json +63 -0
- package/scripts/install.ps1 +133 -0
- package/scripts/install.sh +183 -0
- package/scripts/pre-commit-hook.sh +86 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Tree-sitter Parser
|
|
3
|
+
*
|
|
4
|
+
* AST parser for Python using Tree-sitter for accurate code analysis.
|
|
5
|
+
*/
|
|
6
|
+
import Parser from "web-tree-sitter";
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { createRequire } from "module";
|
|
9
|
+
import { join, dirname } from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
import { createEmptyStructure } from "../types.js";
|
|
12
|
+
import { extractDocstring, getFunctionSignature, getClassSignature, createCodeElement, getBodyNode, getImportName, getImportSignature, } from "./utils.js";
|
|
13
|
+
// Singleton for lazy initialization
|
|
14
|
+
let parserInstance = null;
|
|
15
|
+
let pythonLanguage = null;
|
|
16
|
+
let initPromise = null;
|
|
17
|
+
/**
|
|
18
|
+
* Get the path to the Python WASM file
|
|
19
|
+
*/
|
|
20
|
+
function getPythonWasmPath() {
|
|
21
|
+
// Use createRequire to resolve the path in ESM context
|
|
22
|
+
const require = createRequire(import.meta.url);
|
|
23
|
+
try {
|
|
24
|
+
const wasmDir = dirname(require.resolve("tree-sitter-wasms/package.json"));
|
|
25
|
+
return join(wasmDir, "out", "tree-sitter-python.wasm");
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Fallback: try common locations
|
|
29
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
return join(__dirname, "..", "..", "..", "node_modules", "tree-sitter-wasms", "out", "tree-sitter-python.wasm");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Initialize Tree-sitter and load Python language
|
|
35
|
+
*/
|
|
36
|
+
async function initParser() {
|
|
37
|
+
if (parserInstance && pythonLanguage)
|
|
38
|
+
return;
|
|
39
|
+
if (initPromise) {
|
|
40
|
+
await initPromise;
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
initPromise = (async () => {
|
|
44
|
+
await Parser.init();
|
|
45
|
+
parserInstance = new Parser();
|
|
46
|
+
const wasmPath = getPythonWasmPath();
|
|
47
|
+
// Read WASM file as buffer for reliable loading in all environments
|
|
48
|
+
const wasmBuffer = readFileSync(wasmPath);
|
|
49
|
+
pythonLanguage = await Parser.Language.load(wasmBuffer);
|
|
50
|
+
parserInstance.setLanguage(pythonLanguage);
|
|
51
|
+
})();
|
|
52
|
+
await initPromise;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parse Python code and return AST tree
|
|
56
|
+
*/
|
|
57
|
+
async function parseCode(content) {
|
|
58
|
+
await initParser();
|
|
59
|
+
if (!parserInstance) {
|
|
60
|
+
throw new Error("Parser not initialized");
|
|
61
|
+
}
|
|
62
|
+
return parserInstance.parse(content);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a node is at module level (not nested inside a class or function)
|
|
66
|
+
*/
|
|
67
|
+
function isModuleLevel(node) {
|
|
68
|
+
let parent = node.parent;
|
|
69
|
+
while (parent) {
|
|
70
|
+
if (parent.type === "function_definition" || parent.type === "class_definition") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
parent = parent.parent;
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if a function is async
|
|
79
|
+
*/
|
|
80
|
+
function isAsyncFunction(node) {
|
|
81
|
+
// In Tree-sitter Python, 'async' is a child of function_definition
|
|
82
|
+
for (const child of node.children) {
|
|
83
|
+
if (child.type === "async")
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the parent class name if this function is a method
|
|
90
|
+
*/
|
|
91
|
+
function getParentClassName(node) {
|
|
92
|
+
let parent = node.parent;
|
|
93
|
+
while (parent) {
|
|
94
|
+
if (parent.type === "class_definition") {
|
|
95
|
+
const nameNode = parent.childForFieldName("name");
|
|
96
|
+
return nameNode?.text;
|
|
97
|
+
}
|
|
98
|
+
parent = parent.parent;
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Parse Python content and extract structure
|
|
104
|
+
* @param options ParseOptions - set detailed: true for signature/documentation
|
|
105
|
+
*/
|
|
106
|
+
export function parsePython(content, options = {}) {
|
|
107
|
+
const { detailed = false } = options;
|
|
108
|
+
// Use synchronous parsing for the interface
|
|
109
|
+
// Tree-sitter is async for initialization but sync for parsing after that
|
|
110
|
+
let structure = null;
|
|
111
|
+
// We need to handle async initialization
|
|
112
|
+
// For now, use a sync approach with cached parser
|
|
113
|
+
if (!parserInstance || !pythonLanguage) {
|
|
114
|
+
// Return empty structure if parser not ready
|
|
115
|
+
// The async version will be called on first use
|
|
116
|
+
return createEmptyStructure("python", content.split("\n").length);
|
|
117
|
+
}
|
|
118
|
+
const tree = parserInstance.parse(content);
|
|
119
|
+
if (!tree) {
|
|
120
|
+
return createEmptyStructure("python", content.split("\n").length);
|
|
121
|
+
}
|
|
122
|
+
structure = extractStructure(tree, content, detailed);
|
|
123
|
+
return structure;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Async version of parsePython for initial calls
|
|
127
|
+
*/
|
|
128
|
+
export async function parsePythonAsync(content, options = {}) {
|
|
129
|
+
const { detailed = false } = options;
|
|
130
|
+
await initParser();
|
|
131
|
+
if (!parserInstance) {
|
|
132
|
+
return createEmptyStructure("python", content.split("\n").length);
|
|
133
|
+
}
|
|
134
|
+
const tree = parserInstance.parse(content);
|
|
135
|
+
if (!tree) {
|
|
136
|
+
return createEmptyStructure("python", content.split("\n").length);
|
|
137
|
+
}
|
|
138
|
+
return extractStructure(tree, content, detailed);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Extract file structure from parsed tree
|
|
142
|
+
*/
|
|
143
|
+
function extractStructure(tree, content, detailed = false) {
|
|
144
|
+
const lines = content.split("\n");
|
|
145
|
+
const structure = createEmptyStructure("python", lines.length);
|
|
146
|
+
const rootNode = tree.rootNode;
|
|
147
|
+
// Walk the tree and extract elements
|
|
148
|
+
walkNode(rootNode, structure, lines, detailed);
|
|
149
|
+
return structure;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Recursively walk the AST and extract code elements
|
|
153
|
+
* @param detailed When true, extract signature and documentation
|
|
154
|
+
*/
|
|
155
|
+
function walkNode(node, structure, lines, detailed) {
|
|
156
|
+
switch (node.type) {
|
|
157
|
+
case "import_statement":
|
|
158
|
+
case "import_from_statement": {
|
|
159
|
+
const opts = {};
|
|
160
|
+
if (detailed) {
|
|
161
|
+
opts.signature = getImportSignature(node);
|
|
162
|
+
}
|
|
163
|
+
structure.imports.push(createCodeElement("import", getImportName(node), node, opts));
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case "function_definition": {
|
|
167
|
+
if (isModuleLevel(node)) {
|
|
168
|
+
const nameNode = node.childForFieldName("name");
|
|
169
|
+
const bodyNode = getBodyNode(node);
|
|
170
|
+
const isAsync = isAsyncFunction(node);
|
|
171
|
+
const opts = { isAsync };
|
|
172
|
+
if (detailed) {
|
|
173
|
+
opts.signature = getFunctionSignature(node, isAsync);
|
|
174
|
+
opts.documentation = extractDocstring(bodyNode);
|
|
175
|
+
}
|
|
176
|
+
structure.functions.push(createCodeElement("function", nameNode?.text ?? "unknown", node, opts));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// It's a method
|
|
180
|
+
const nameNode = node.childForFieldName("name");
|
|
181
|
+
const bodyNode = getBodyNode(node);
|
|
182
|
+
const isAsync = isAsyncFunction(node);
|
|
183
|
+
const parentClass = getParentClassName(node);
|
|
184
|
+
const opts = { isAsync, parent: parentClass };
|
|
185
|
+
if (detailed) {
|
|
186
|
+
opts.signature = getFunctionSignature(node, isAsync);
|
|
187
|
+
opts.documentation = extractDocstring(bodyNode);
|
|
188
|
+
}
|
|
189
|
+
structure.functions.push(createCodeElement("method", nameNode?.text ?? "unknown", node, opts));
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case "class_definition": {
|
|
194
|
+
const nameNode = node.childForFieldName("name");
|
|
195
|
+
const bodyNode = getBodyNode(node);
|
|
196
|
+
const opts = {};
|
|
197
|
+
if (detailed) {
|
|
198
|
+
opts.signature = getClassSignature(node);
|
|
199
|
+
opts.documentation = extractDocstring(bodyNode);
|
|
200
|
+
}
|
|
201
|
+
structure.classes.push(createCodeElement("class", nameNode?.text ?? "unknown", node, opts));
|
|
202
|
+
// Walk into class body to find methods
|
|
203
|
+
if (bodyNode) {
|
|
204
|
+
for (const child of bodyNode.children) {
|
|
205
|
+
walkNode(child, structure, lines, detailed);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return; // Don't walk children again
|
|
209
|
+
}
|
|
210
|
+
case "expression_statement": {
|
|
211
|
+
// Check for module-level assignments (variables)
|
|
212
|
+
if (isModuleLevel(node)) {
|
|
213
|
+
const assignment = node.firstNamedChild;
|
|
214
|
+
if (assignment?.type === "assignment") {
|
|
215
|
+
const leftNode = assignment.childForFieldName("left");
|
|
216
|
+
if (leftNode?.type === "identifier") {
|
|
217
|
+
const opts = {};
|
|
218
|
+
if (detailed) {
|
|
219
|
+
opts.signature = node.text.split("\n")[0];
|
|
220
|
+
}
|
|
221
|
+
structure.variables.push(createCodeElement("variable", leftNode.text, node, opts));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case "decorated_definition": {
|
|
228
|
+
// Let the child function/class handle itself
|
|
229
|
+
for (const child of node.children) {
|
|
230
|
+
walkNode(child, structure, lines, detailed);
|
|
231
|
+
}
|
|
232
|
+
return; // Don't walk again
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Walk children
|
|
236
|
+
for (const child of node.children) {
|
|
237
|
+
walkNode(child, structure, lines, detailed);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Extract a specific element from Python code
|
|
242
|
+
*/
|
|
243
|
+
export async function extractPythonElement(content, target, options) {
|
|
244
|
+
const structure = await parsePythonAsync(content);
|
|
245
|
+
let element;
|
|
246
|
+
switch (target.type) {
|
|
247
|
+
case "function":
|
|
248
|
+
case "method":
|
|
249
|
+
element = structure.functions.find((f) => f.name === target.name);
|
|
250
|
+
break;
|
|
251
|
+
case "class":
|
|
252
|
+
element = structure.classes.find((c) => c.name === target.name);
|
|
253
|
+
break;
|
|
254
|
+
case "variable":
|
|
255
|
+
element = structure.variables.find((v) => v.name === target.name);
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
if (!element) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const lines = content.split("\n");
|
|
262
|
+
// Find start line (include documentation if requested)
|
|
263
|
+
let startLine = element.startLine;
|
|
264
|
+
if (options.includeComments && element.documentation) {
|
|
265
|
+
// Look for docstrings/comments above the element
|
|
266
|
+
for (let i = element.startLine - 2; i >= 0; i--) {
|
|
267
|
+
const line = lines[i]?.trim() ?? "";
|
|
268
|
+
if (line.startsWith("#") || line.startsWith('"""') || line.startsWith("'''") || line.startsWith("@")) {
|
|
269
|
+
startLine = i + 1;
|
|
270
|
+
}
|
|
271
|
+
else if (line === "") {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const extractedLines = lines.slice(startLine - 1, element.endLine);
|
|
280
|
+
const extractedCode = extractedLines.join("\n");
|
|
281
|
+
// Find related imports
|
|
282
|
+
const relatedImports = [];
|
|
283
|
+
if (options.includeImports) {
|
|
284
|
+
for (const imp of structure.imports) {
|
|
285
|
+
if (extractedCode.includes(imp.name)) {
|
|
286
|
+
const importLine = lines[imp.startLine - 1];
|
|
287
|
+
if (importLine && !relatedImports.includes(importLine)) {
|
|
288
|
+
relatedImports.push(importLine);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
content: extractedCode,
|
|
295
|
+
elements: [element],
|
|
296
|
+
relatedImports,
|
|
297
|
+
startLine,
|
|
298
|
+
endLine: element.endLine,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Search for elements matching a query
|
|
303
|
+
*/
|
|
304
|
+
export async function searchPythonElements(content, query) {
|
|
305
|
+
const structure = await parsePythonAsync(content);
|
|
306
|
+
const queryLower = query.toLowerCase();
|
|
307
|
+
const results = [];
|
|
308
|
+
const allElements = [...structure.functions, ...structure.classes, ...structure.variables];
|
|
309
|
+
for (const element of allElements) {
|
|
310
|
+
if (element.name.toLowerCase().includes(queryLower) ||
|
|
311
|
+
element.signature?.toLowerCase().includes(queryLower) ||
|
|
312
|
+
element.documentation?.toLowerCase().includes(queryLower)) {
|
|
313
|
+
results.push(element);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return results;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* LanguageParser implementation for Python
|
|
320
|
+
*/
|
|
321
|
+
export const pythonTreeSitterParser = {
|
|
322
|
+
languages: ["python"],
|
|
323
|
+
parse(content, options) {
|
|
324
|
+
// Synchronous parse - requires parser to be initialized first
|
|
325
|
+
// If not initialized, return empty structure
|
|
326
|
+
// The async initialization will happen on first tool call
|
|
327
|
+
if (!parserInstance || !pythonLanguage) {
|
|
328
|
+
// Trigger async init for next call
|
|
329
|
+
initParser().catch(() => { });
|
|
330
|
+
return parsePython(content, options);
|
|
331
|
+
}
|
|
332
|
+
return parsePython(content, options);
|
|
333
|
+
},
|
|
334
|
+
extractElement(content, target, options) {
|
|
335
|
+
// This is sync interface but we need async
|
|
336
|
+
// For now, ensure parser is initialized and use sync parsing
|
|
337
|
+
if (!parserInstance || !pythonLanguage) {
|
|
338
|
+
// Can't do async in sync interface, return null
|
|
339
|
+
// Trigger init for next call
|
|
340
|
+
initParser().catch(() => { });
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
// Extraction needs detailed parsing for proper display
|
|
344
|
+
const structure = parsePython(content, { detailed: true });
|
|
345
|
+
let element;
|
|
346
|
+
switch (target.type) {
|
|
347
|
+
case "function":
|
|
348
|
+
case "method":
|
|
349
|
+
element = structure.functions.find((f) => f.name === target.name);
|
|
350
|
+
break;
|
|
351
|
+
case "class":
|
|
352
|
+
element = structure.classes.find((c) => c.name === target.name);
|
|
353
|
+
break;
|
|
354
|
+
case "variable":
|
|
355
|
+
element = structure.variables.find((v) => v.name === target.name);
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
if (!element)
|
|
359
|
+
return null;
|
|
360
|
+
const lines = content.split("\n");
|
|
361
|
+
let startLine = element.startLine;
|
|
362
|
+
if (options.includeComments && element.documentation) {
|
|
363
|
+
for (let i = element.startLine - 2; i >= 0; i--) {
|
|
364
|
+
const line = lines[i]?.trim() ?? "";
|
|
365
|
+
if (line.startsWith("#") || line.startsWith('"""') || line.startsWith("'''") || line.startsWith("@")) {
|
|
366
|
+
startLine = i + 1;
|
|
367
|
+
}
|
|
368
|
+
else if (line === "") {
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const extractedLines = lines.slice(startLine - 1, element.endLine);
|
|
377
|
+
const extractedCode = extractedLines.join("\n");
|
|
378
|
+
const relatedImports = [];
|
|
379
|
+
if (options.includeImports) {
|
|
380
|
+
for (const imp of structure.imports) {
|
|
381
|
+
if (extractedCode.includes(imp.name)) {
|
|
382
|
+
const importLine = lines[imp.startLine - 1];
|
|
383
|
+
if (importLine && !relatedImports.includes(importLine)) {
|
|
384
|
+
relatedImports.push(importLine);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
content: extractedCode,
|
|
391
|
+
elements: [element],
|
|
392
|
+
relatedImports,
|
|
393
|
+
startLine,
|
|
394
|
+
endLine: element.endLine,
|
|
395
|
+
};
|
|
396
|
+
},
|
|
397
|
+
searchElements(content, query) {
|
|
398
|
+
if (!parserInstance || !pythonLanguage) {
|
|
399
|
+
initParser().catch(() => { });
|
|
400
|
+
return [];
|
|
401
|
+
}
|
|
402
|
+
// Search needs detailed parsing to match against signature/documentation
|
|
403
|
+
const structure = parsePython(content, { detailed: true });
|
|
404
|
+
const queryLower = query.toLowerCase();
|
|
405
|
+
const results = [];
|
|
406
|
+
const allElements = [...structure.functions, ...structure.classes, ...structure.variables];
|
|
407
|
+
for (const element of allElements) {
|
|
408
|
+
if (element.name.toLowerCase().includes(queryLower) ||
|
|
409
|
+
element.signature?.toLowerCase().includes(queryLower) ||
|
|
410
|
+
element.documentation?.toLowerCase().includes(queryLower)) {
|
|
411
|
+
results.push(element);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return results;
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
/**
|
|
418
|
+
* Initialize the parser (call this at server startup)
|
|
419
|
+
*/
|
|
420
|
+
export async function initPythonParser() {
|
|
421
|
+
await initParser();
|
|
422
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.test.d.ts","sourceRoot":"","sources":["../../../src/ast/python/parser.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Tree-sitter Parser Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeAll } from "vitest";
|
|
5
|
+
import { pythonTreeSitterParser, parsePythonAsync, initPythonParser, } from "./parser.js";
|
|
6
|
+
// Sample Python code for testing
|
|
7
|
+
const SAMPLE_PYTHON = `
|
|
8
|
+
"""Module docstring."""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
from typing import List, Optional
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
|
|
14
|
+
# Constants
|
|
15
|
+
MAX_SIZE = 100
|
|
16
|
+
DEBUG = True
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class User:
|
|
20
|
+
"""A user class with name and age."""
|
|
21
|
+
name: str
|
|
22
|
+
age: int
|
|
23
|
+
|
|
24
|
+
def greet(self) -> str:
|
|
25
|
+
"""Return a greeting message."""
|
|
26
|
+
return f"Hello, {self.name}!"
|
|
27
|
+
|
|
28
|
+
async def fetch_data(self) -> dict:
|
|
29
|
+
"""Fetch user data asynchronously."""
|
|
30
|
+
return {"name": self.name, "age": self.age}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AdminUser(User):
|
|
34
|
+
"""Admin user with extra permissions."""
|
|
35
|
+
permissions: List[str]
|
|
36
|
+
|
|
37
|
+
def has_permission(self, perm: str) -> bool:
|
|
38
|
+
return perm in self.permissions
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def calculate_sum(numbers: List[int]) -> int:
|
|
42
|
+
"""Calculate the sum of a list of numbers."""
|
|
43
|
+
return sum(numbers)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def fetch_users() -> List[User]:
|
|
47
|
+
"""Fetch all users from the database."""
|
|
48
|
+
return []
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def nested_function():
|
|
52
|
+
def inner():
|
|
53
|
+
pass
|
|
54
|
+
return inner
|
|
55
|
+
`;
|
|
56
|
+
describe("Python Tree-sitter Parser", () => {
|
|
57
|
+
beforeAll(async () => {
|
|
58
|
+
await initPythonParser();
|
|
59
|
+
});
|
|
60
|
+
describe("parsePythonAsync", () => {
|
|
61
|
+
it("should parse imports correctly", async () => {
|
|
62
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
63
|
+
expect(structure.language).toBe("python");
|
|
64
|
+
expect(structure.imports.length).toBeGreaterThanOrEqual(3);
|
|
65
|
+
const importNames = structure.imports.map((i) => i.name);
|
|
66
|
+
expect(importNames).toContain("os");
|
|
67
|
+
});
|
|
68
|
+
it("should parse functions correctly", async () => {
|
|
69
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
70
|
+
const funcNames = structure.functions.map((f) => f.name);
|
|
71
|
+
expect(funcNames).toContain("calculate_sum");
|
|
72
|
+
expect(funcNames).toContain("fetch_users");
|
|
73
|
+
expect(funcNames).toContain("nested_function");
|
|
74
|
+
});
|
|
75
|
+
it("should detect async functions", async () => {
|
|
76
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
77
|
+
const fetchUsers = structure.functions.find((f) => f.name === "fetch_users");
|
|
78
|
+
expect(fetchUsers).toBeDefined();
|
|
79
|
+
expect(fetchUsers?.isAsync).toBe(true);
|
|
80
|
+
const calculateSum = structure.functions.find((f) => f.name === "calculate_sum");
|
|
81
|
+
expect(calculateSum?.isAsync).toBeFalsy();
|
|
82
|
+
});
|
|
83
|
+
it("should parse classes correctly", async () => {
|
|
84
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
85
|
+
expect(structure.classes.length).toBeGreaterThanOrEqual(2);
|
|
86
|
+
const classNames = structure.classes.map((c) => c.name);
|
|
87
|
+
expect(classNames).toContain("User");
|
|
88
|
+
expect(classNames).toContain("AdminUser");
|
|
89
|
+
});
|
|
90
|
+
it("should extract docstrings", async () => {
|
|
91
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON, { detailed: true });
|
|
92
|
+
const userClass = structure.classes.find((c) => c.name === "User");
|
|
93
|
+
expect(userClass?.documentation).toContain("user class");
|
|
94
|
+
const calcSum = structure.functions.find((f) => f.name === "calculate_sum");
|
|
95
|
+
expect(calcSum?.documentation).toContain("sum");
|
|
96
|
+
});
|
|
97
|
+
it("should parse methods inside classes", async () => {
|
|
98
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
99
|
+
const methods = structure.functions.filter((f) => f.type === "method");
|
|
100
|
+
expect(methods.length).toBeGreaterThanOrEqual(3);
|
|
101
|
+
const methodNames = methods.map((m) => m.name);
|
|
102
|
+
expect(methodNames).toContain("greet");
|
|
103
|
+
expect(methodNames).toContain("fetch_data");
|
|
104
|
+
expect(methodNames).toContain("has_permission");
|
|
105
|
+
});
|
|
106
|
+
it("should track parent class for methods", async () => {
|
|
107
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
108
|
+
const greet = structure.functions.find((f) => f.name === "greet");
|
|
109
|
+
expect(greet?.parent).toBe("User");
|
|
110
|
+
const hasPermission = structure.functions.find((f) => f.name === "has_permission");
|
|
111
|
+
expect(hasPermission?.parent).toBe("AdminUser");
|
|
112
|
+
});
|
|
113
|
+
it("should parse module-level variables", async () => {
|
|
114
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
115
|
+
const varNames = structure.variables.map((v) => v.name);
|
|
116
|
+
expect(varNames).toContain("MAX_SIZE");
|
|
117
|
+
expect(varNames).toContain("DEBUG");
|
|
118
|
+
});
|
|
119
|
+
it("should return correct line numbers", async () => {
|
|
120
|
+
const structure = await parsePythonAsync(SAMPLE_PYTHON);
|
|
121
|
+
const userClass = structure.classes.find((c) => c.name === "User");
|
|
122
|
+
expect(userClass?.startLine).toBeGreaterThan(0);
|
|
123
|
+
expect(userClass?.endLine).toBeGreaterThan(userClass?.startLine ?? 0);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe("LanguageParser interface", () => {
|
|
127
|
+
it("should implement parse() method", () => {
|
|
128
|
+
// Note: This will return empty structure on first call if parser not initialized
|
|
129
|
+
const structure = pythonTreeSitterParser.parse(SAMPLE_PYTHON);
|
|
130
|
+
expect(structure).toBeDefined();
|
|
131
|
+
expect(structure.language).toBe("python");
|
|
132
|
+
});
|
|
133
|
+
it("should implement extractElement() method", async () => {
|
|
134
|
+
await initPythonParser();
|
|
135
|
+
const result = pythonTreeSitterParser.extractElement(SAMPLE_PYTHON, { type: "function", name: "calculate_sum" }, { includeImports: true, includeComments: true });
|
|
136
|
+
expect(result).not.toBeNull();
|
|
137
|
+
expect(result?.content).toContain("def calculate_sum");
|
|
138
|
+
expect(result?.elements[0]?.name).toBe("calculate_sum");
|
|
139
|
+
});
|
|
140
|
+
it("should implement searchElements() method", async () => {
|
|
141
|
+
await initPythonParser();
|
|
142
|
+
const results = pythonTreeSitterParser.searchElements(SAMPLE_PYTHON, "user");
|
|
143
|
+
expect(results.length).toBeGreaterThan(0);
|
|
144
|
+
const names = results.map((r) => r.name.toLowerCase());
|
|
145
|
+
expect(names.some((n) => n.includes("user"))).toBe(true);
|
|
146
|
+
});
|
|
147
|
+
it("should return null for non-existent elements", async () => {
|
|
148
|
+
await initPythonParser();
|
|
149
|
+
const result = pythonTreeSitterParser.extractElement(SAMPLE_PYTHON, { type: "function", name: "non_existent_function" }, { includeImports: false, includeComments: false });
|
|
150
|
+
expect(result).toBeNull();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe("Edge cases", () => {
|
|
154
|
+
it("should handle empty content", async () => {
|
|
155
|
+
const structure = await parsePythonAsync("");
|
|
156
|
+
expect(structure.language).toBe("python");
|
|
157
|
+
expect(structure.totalLines).toBe(1);
|
|
158
|
+
expect(structure.functions).toHaveLength(0);
|
|
159
|
+
});
|
|
160
|
+
it("should handle syntax errors gracefully", async () => {
|
|
161
|
+
const invalidCode = `
|
|
162
|
+
def broken_function(
|
|
163
|
+
# Missing closing parenthesis and body
|
|
164
|
+
`;
|
|
165
|
+
const structure = await parsePythonAsync(invalidCode);
|
|
166
|
+
expect(structure).toBeDefined();
|
|
167
|
+
expect(structure.language).toBe("python");
|
|
168
|
+
});
|
|
169
|
+
it("should handle decorated functions", async () => {
|
|
170
|
+
const code = `
|
|
171
|
+
@decorator
|
|
172
|
+
def decorated_func():
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
@decorator1
|
|
176
|
+
@decorator2
|
|
177
|
+
async def multi_decorated():
|
|
178
|
+
pass
|
|
179
|
+
`;
|
|
180
|
+
const structure = await parsePythonAsync(code);
|
|
181
|
+
const funcNames = structure.functions.map((f) => f.name);
|
|
182
|
+
expect(funcNames).toContain("decorated_func");
|
|
183
|
+
expect(funcNames).toContain("multi_decorated");
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Tree-sitter Queries
|
|
3
|
+
*
|
|
4
|
+
* S-expression queries for extracting Python code elements.
|
|
5
|
+
* Tree-sitter uses a query language similar to Lisp S-expressions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Query to find all function definitions (including async)
|
|
9
|
+
* Captures:
|
|
10
|
+
* - @function: the function_definition node
|
|
11
|
+
* - @name: the function name
|
|
12
|
+
*/
|
|
13
|
+
export declare const FUNCTION_QUERY = "\n(function_definition\n name: (identifier) @name) @function\n";
|
|
14
|
+
/**
|
|
15
|
+
* Query to find all class definitions
|
|
16
|
+
* Captures:
|
|
17
|
+
* - @class: the class_definition node
|
|
18
|
+
* - @name: the class name
|
|
19
|
+
*/
|
|
20
|
+
export declare const CLASS_QUERY = "\n(class_definition\n name: (identifier) @name) @class\n";
|
|
21
|
+
/**
|
|
22
|
+
* Query to find all import statements
|
|
23
|
+
* Captures:
|
|
24
|
+
* - @import: the import statement node
|
|
25
|
+
*/
|
|
26
|
+
export declare const IMPORT_QUERY = "\n[\n (import_statement) @import\n (import_from_statement) @import\n]\n";
|
|
27
|
+
/**
|
|
28
|
+
* Query to find all decorated definitions
|
|
29
|
+
* Captures:
|
|
30
|
+
* - @decorator: the decorator node
|
|
31
|
+
* - @definition: the decorated definition (function or class)
|
|
32
|
+
*/
|
|
33
|
+
export declare const DECORATED_QUERY = "\n(decorated_definition\n (decorator) @decorator\n definition: [\n (function_definition) @function\n (class_definition) @class\n ])\n";
|
|
34
|
+
/**
|
|
35
|
+
* Query to find all assignments at module level (variables)
|
|
36
|
+
* Captures:
|
|
37
|
+
* - @variable: the assignment node
|
|
38
|
+
* - @name: the variable name
|
|
39
|
+
*/
|
|
40
|
+
export declare const VARIABLE_QUERY = "\n(module\n (expression_statement\n (assignment\n left: (identifier) @name) @variable))\n";
|
|
41
|
+
/**
|
|
42
|
+
* Query to find all type aliases (using TypeAlias or simple assignment with type annotation)
|
|
43
|
+
* Captures:
|
|
44
|
+
* - @type_alias: the type alias definition
|
|
45
|
+
*/
|
|
46
|
+
export declare const TYPE_ALIAS_QUERY = "\n(module\n (type_alias_statement\n name: (type) @name) @type_alias)\n";
|
|
47
|
+
/**
|
|
48
|
+
* Query to find class methods
|
|
49
|
+
* Captures:
|
|
50
|
+
* - @method: the function_definition node inside a class
|
|
51
|
+
* - @name: the method name
|
|
52
|
+
* - @class_name: the parent class name
|
|
53
|
+
*/
|
|
54
|
+
export declare const METHOD_QUERY = "\n(class_definition\n name: (identifier) @class_name\n body: (block\n (function_definition\n name: (identifier) @method_name) @method))\n";
|
|
55
|
+
/**
|
|
56
|
+
* Combined query for all top-level definitions
|
|
57
|
+
* This is more efficient than running multiple queries
|
|
58
|
+
*/
|
|
59
|
+
export declare const ALL_DEFINITIONS_QUERY = "\n; Functions at module level\n(module\n (function_definition\n name: (identifier) @func_name) @function)\n\n; Decorated functions at module level\n(module\n (decorated_definition\n (function_definition\n name: (identifier) @decorated_func_name) @decorated_function))\n\n; Classes at module level\n(module\n (class_definition\n name: (identifier) @class_name) @class)\n\n; Decorated classes at module level\n(module\n (decorated_definition\n (class_definition\n name: (identifier) @decorated_class_name) @decorated_class))\n\n; Import statements\n(import_statement) @import\n(import_from_statement) @import_from\n\n; Module-level variables\n(module\n (expression_statement\n (assignment\n left: (identifier) @var_name) @variable))\n";
|
|
60
|
+
/**
|
|
61
|
+
* Query patterns as a single object for easy access
|
|
62
|
+
*/
|
|
63
|
+
export declare const QUERIES: {
|
|
64
|
+
readonly function: "\n(function_definition\n name: (identifier) @name) @function\n";
|
|
65
|
+
readonly class: "\n(class_definition\n name: (identifier) @name) @class\n";
|
|
66
|
+
readonly import: "\n[\n (import_statement) @import\n (import_from_statement) @import\n]\n";
|
|
67
|
+
readonly decorated: "\n(decorated_definition\n (decorator) @decorator\n definition: [\n (function_definition) @function\n (class_definition) @class\n ])\n";
|
|
68
|
+
readonly variable: "\n(module\n (expression_statement\n (assignment\n left: (identifier) @name) @variable))\n";
|
|
69
|
+
readonly typeAlias: "\n(module\n (type_alias_statement\n name: (type) @name) @type_alias)\n";
|
|
70
|
+
readonly method: "\n(class_definition\n name: (identifier) @class_name\n body: (block\n (function_definition\n name: (identifier) @method_name) @method))\n";
|
|
71
|
+
readonly all: "\n; Functions at module level\n(module\n (function_definition\n name: (identifier) @func_name) @function)\n\n; Decorated functions at module level\n(module\n (decorated_definition\n (function_definition\n name: (identifier) @decorated_func_name) @decorated_function))\n\n; Classes at module level\n(module\n (class_definition\n name: (identifier) @class_name) @class)\n\n; Decorated classes at module level\n(module\n (decorated_definition\n (class_definition\n name: (identifier) @decorated_class_name) @decorated_class))\n\n; Import statements\n(import_statement) @import\n(import_from_statement) @import_from\n\n; Module-level variables\n(module\n (expression_statement\n (assignment\n left: (identifier) @var_name) @variable))\n";
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=queries.d.ts.map
|