claude-code-workflow 6.1.4 → 6.2.2
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/.claude/CLAUDE.md +10 -0
- package/.claude/agents/action-planning-agent.md +857 -778
- package/.claude/agents/cli-execution-agent.md +266 -269
- package/.claude/agents/cli-explore-agent.md +2 -2
- package/.claude/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/agents/cli-planning-agent.md +4 -4
- package/.claude/agents/code-developer.md +7 -6
- package/.claude/agents/conceptual-planning-agent.md +2 -2
- package/.claude/agents/context-search-agent.md +31 -32
- package/.claude/agents/doc-generator.md +4 -4
- package/.claude/agents/memory-bridge.md +93 -93
- package/.claude/agents/test-context-search-agent.md +8 -7
- package/.claude/agents/test-fix-agent.md +7 -6
- package/.claude/commands/clean.md +516 -0
- package/.claude/commands/memory/compact.md +383 -0
- package/.claude/commands/memory/docs-full-cli.md +471 -471
- package/.claude/commands/memory/docs-related-cli.md +386 -386
- package/.claude/commands/memory/docs.md +615 -615
- package/.claude/commands/memory/load.md +5 -5
- package/.claude/commands/memory/tech-research-rules.md +310 -0
- package/.claude/commands/memory/update-full.md +332 -332
- package/.claude/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/commands/task/create.md +151 -151
- package/.claude/commands/version.md +254 -254
- package/.claude/commands/workflow/brainstorm/api-designer.md +587 -585
- package/.claude/commands/workflow/brainstorm/artifacts.md +1 -0
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/commands/workflow/brainstorm/system-architect.md +389 -387
- package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/commands/workflow/debug.md +321 -0
- package/.claude/commands/workflow/execute.md +13 -0
- package/.claude/commands/workflow/init.md +165 -164
- package/.claude/commands/workflow/lite-execute.md +119 -13
- package/.claude/commands/workflow/lite-fix.md +623 -621
- package/.claude/commands/workflow/lite-plan.md +610 -592
- package/.claude/commands/workflow/plan.md +5 -5
- package/.claude/commands/workflow/review-module-cycle.md +2 -0
- package/.claude/commands/workflow/review-session-cycle.md +2 -0
- package/.claude/commands/workflow/review.md +297 -291
- package/.claude/commands/workflow/session/complete.md +153 -500
- package/.claude/commands/workflow/session/list.md +95 -95
- package/.claude/commands/workflow/session/resume.md +60 -60
- package/.claude/commands/workflow/session/start.md +199 -199
- package/.claude/commands/workflow/tdd-plan.md +3 -3
- package/.claude/commands/workflow/tdd-verify.md +23 -9
- package/.claude/commands/workflow/test-cycle-execute.md +2 -0
- package/.claude/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/commands/workflow/tools/conflict-resolution.md +104 -18
- package/.claude/commands/workflow/tools/context-gather.md +436 -434
- package/.claude/commands/workflow/tools/task-generate-agent.md +490 -291
- package/.claude/commands/workflow/tools/task-generate-tdd.md +18 -10
- package/.claude/commands/workflow/tools/test-concept-enhanced.md +2 -1
- package/.claude/commands/workflow/tools/test-context-gather.md +1 -0
- package/.claude/commands/workflow/tools/test-task-generate.md +1 -0
- package/.claude/commands/workflow/ui-design/import-from-code.md +9 -6
- package/.claude/skills/command-guide/SKILL.md +5 -5
- package/.claude/skills/command-guide/index/all-commands.json +1 -1
- package/.claude/skills/command-guide/index/by-category.json +1 -1
- package/.claude/skills/command-guide/index/by-use-case.json +1 -1
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +857 -778
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +266 -269
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +142 -92
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +4 -4
- package/.claude/skills/command-guide/reference/agents/code-developer.md +7 -6
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +2 -2
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +31 -32
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +4 -4
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +8 -7
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +7 -6
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +17 -16
- package/.claude/skills/command-guide/reference/commands/memory/load.md +5 -5
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +194 -357
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +4 -4
- package/.claude/skills/command-guide/reference/commands/task/create.md +151 -151
- package/.claude/skills/command-guide/reference/commands/version.md +254 -254
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -585
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +443 -443
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -220
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -200
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -387
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -221
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +25 -20
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -164
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +748 -686
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +664 -621
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +645 -592
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +5 -5
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +25 -18
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +547 -500
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +45 -27
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +35 -19
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +90 -33
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +3 -3
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +23 -9
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -699
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +103 -17
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +487 -291
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +17 -10
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +1 -1
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +6 -6
- package/.claude/workflows/chinese-response.md +38 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-api.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-components.txt +122 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-config.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-core.txt +60 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-patterns.txt +70 -0
- package/.claude/workflows/cli-templates/prompts/rules/rule-testing.txt +81 -0
- package/.claude/workflows/cli-templates/prompts/rules/tech-rules-agent-prompt.txt +89 -0
- package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -131
- package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +5 -9
- package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +5 -9
- package/.claude/workflows/cli-templates/protocols/analysis-protocol.md +112 -0
- package/.claude/workflows/cli-templates/protocols/write-protocol.md +201 -0
- package/.claude/workflows/cli-templates/schemas/conflict-resolution-schema.json +137 -0
- package/.claude/workflows/cli-templates/schemas/debug-log-json-schema.json +127 -0
- package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +25 -0
- package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +25 -0
- package/.claude/workflows/cli-tools-usage.md +526 -0
- package/{CLAUDE.md → .claude/workflows/coding-philosophy.md} +24 -45
- package/.claude/workflows/context-tools.md +84 -0
- package/.claude/workflows/file-modification.md +64 -0
- package/.claude/workflows/tool-strategy.md +216 -79
- package/.claude/workflows/windows-platform.md +16 -0
- package/.claude/workflows/workflow-architecture.md +942 -942
- package/.codex/AGENTS.md +63 -330
- package/.codex/prompts/debug.md +318 -0
- package/.codex/prompts/execute.md +273 -0
- package/.codex/prompts/lite-execute.md +164 -0
- package/.codex/prompts/lite-plan.md +469 -0
- package/.codex/prompts.zip +0 -0
- package/.gemini/GEMINI.md +25 -164
- package/.qwen/QWEN.md +0 -139
- package/README.md +29 -9
- package/ccw/README.md +30 -6
- package/ccw/bin/ccw-mcp.js +7 -0
- package/ccw/bin/ccw.js +9 -9
- package/ccw/package.json +65 -47
- package/ccw/src/.workflow/.cli-history/history.db +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-shm +0 -0
- package/ccw/src/.workflow/.cli-history/history.db-wal +0 -0
- package/ccw/src/cli.ts +244 -0
- package/ccw/src/commands/cli.ts +740 -0
- package/ccw/src/commands/core-memory.ts +770 -0
- package/ccw/src/commands/hook.ts +315 -0
- package/ccw/src/commands/install.ts +519 -0
- package/ccw/src/commands/{list.js → list.ts} +1 -1
- package/ccw/src/commands/memory.ts +1090 -0
- package/ccw/src/commands/{serve.js → serve.ts} +14 -5
- package/ccw/src/commands/session-path-resolver.ts +372 -0
- package/ccw/src/commands/session.ts +1141 -0
- package/ccw/src/commands/{stop.js → stop.ts} +16 -6
- package/ccw/src/commands/tool.ts +201 -0
- package/ccw/src/commands/{uninstall.js → uninstall.ts} +89 -40
- package/ccw/src/commands/{upgrade.js → upgrade.ts} +68 -23
- package/ccw/src/commands/{view.js → view.ts} +22 -8
- package/ccw/src/config/storage-paths.ts +670 -0
- package/ccw/src/core/cache-manager.ts +294 -0
- package/ccw/src/core/claude-freshness.ts +319 -0
- package/ccw/src/core/core-memory-store.ts +1528 -0
- package/ccw/src/core/{dashboard-generator-patch.js → dashboard-generator-patch.ts} +18 -0
- package/ccw/src/core/{dashboard-generator.js → dashboard-generator.ts} +69 -12
- package/ccw/src/core/data-aggregator.ts +584 -0
- package/ccw/src/core/history-importer.ts +625 -0
- package/ccw/src/core/{lite-scanner.js → lite-scanner-complete.ts} +162 -66
- package/ccw/src/core/lite-scanner.ts +469 -0
- package/ccw/src/core/{manifest.js → manifest.ts} +104 -34
- package/ccw/src/core/memory-embedder-bridge.ts +262 -0
- package/ccw/src/core/memory-store.ts +978 -0
- package/ccw/src/core/routes/ccw-routes.ts +96 -0
- package/ccw/src/core/routes/claude-routes.ts +1183 -0
- package/ccw/src/core/routes/cli-routes.ts +561 -0
- package/ccw/src/core/routes/codexlens-routes.ts +806 -0
- package/ccw/src/core/routes/core-memory-routes.ts +605 -0
- package/ccw/src/core/routes/files-routes.ts +428 -0
- package/ccw/src/core/routes/graph-routes.md +164 -0
- package/ccw/src/core/routes/graph-routes.ts +626 -0
- package/ccw/src/core/routes/help-routes.ts +308 -0
- package/ccw/src/core/routes/hooks-routes.ts +405 -0
- package/ccw/src/core/routes/mcp-routes.ts +1271 -0
- package/ccw/src/core/routes/mcp-routes.ts.backup +550 -0
- package/ccw/src/core/routes/mcp-templates-db.ts +268 -0
- package/ccw/src/core/routes/memory-routes.ts +1206 -0
- package/ccw/src/core/routes/rules-routes.ts +526 -0
- package/ccw/src/core/routes/session-routes.ts +467 -0
- package/ccw/src/core/routes/skills-routes.ts +599 -0
- package/ccw/src/core/routes/status-routes.ts +57 -0
- package/ccw/src/core/routes/system-routes.ts +427 -0
- package/ccw/src/core/server.ts +431 -0
- package/ccw/src/core/session-clustering-service.ts +1258 -0
- package/ccw/src/core/session-scanner.ts +283 -0
- package/ccw/src/core/websocket.ts +190 -0
- package/ccw/src/{index.js → index.ts} +1 -0
- package/ccw/src/mcp-server/index.ts +186 -0
- package/ccw/src/templates/assets/css/github-dark.min.css +10 -0
- package/ccw/src/templates/assets/css/github.min.css +10 -0
- package/ccw/src/templates/assets/js/cytoscape.min.js +32 -0
- package/ccw/src/templates/assets/js/d3.min.js +2 -0
- package/ccw/src/templates/assets/js/highlight.min.js +1244 -0
- package/ccw/src/templates/assets/js/lucide.min.js +12 -0
- package/ccw/src/templates/assets/js/marked.min.js +69 -0
- package/ccw/src/templates/assets/js/tailwind.js +83 -0
- package/ccw/src/templates/dashboard-css/01-base.css +11 -0
- package/ccw/src/templates/dashboard-css/02-session.css +22 -0
- package/ccw/src/templates/dashboard-css/04-lite-tasks.css +10 -0
- package/ccw/src/templates/dashboard-css/06-cards.css +10 -4
- package/ccw/src/templates/dashboard-css/07-managers.css +1178 -7
- package/ccw/src/templates/dashboard-css/09-explorer.css +23 -12
- package/ccw/src/templates/dashboard-css/10-cli-status.css +337 -0
- package/ccw/src/templates/dashboard-css/11-cli-history.css +271 -0
- package/ccw/src/templates/dashboard-css/12-cli-legacy.css +796 -0
- package/ccw/src/templates/dashboard-css/13-cli-ccw.css +199 -0
- package/ccw/src/templates/dashboard-css/14-cli-modals.css +258 -0
- package/ccw/src/templates/dashboard-css/15-cli-endpoints.css +305 -0
- package/ccw/src/templates/dashboard-css/16-cli-session.css +241 -0
- package/ccw/src/templates/dashboard-css/17-cli-conversation.css +283 -0
- package/ccw/src/templates/dashboard-css/18-cli-settings.css +160 -0
- package/ccw/src/templates/dashboard-css/19-cli-native-session.css +496 -0
- package/ccw/src/templates/dashboard-css/20-cli-taskqueue.css +188 -0
- package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +310 -0
- package/ccw/src/templates/dashboard-css/22-cli-semantic.css +240 -0
- package/ccw/src/templates/dashboard-css/23-memory.css +2390 -0
- package/ccw/src/templates/dashboard-css/24-prompt-history.css +1089 -0
- package/ccw/src/templates/dashboard-css/25-skills-rules.css +326 -0
- package/ccw/src/templates/dashboard-css/26-claude-manager.css +908 -0
- package/ccw/src/templates/dashboard-css/27-graph-explorer.css +1678 -0
- package/ccw/src/templates/dashboard-css/28-mcp-manager.css +748 -0
- package/ccw/src/templates/dashboard-css/29-help.css +264 -0
- package/ccw/src/templates/dashboard-css/30-core-memory.css +1700 -0
- package/ccw/src/templates/dashboard-js/api.js +162 -142
- package/ccw/src/templates/dashboard-js/components/carousel.js +4 -4
- package/ccw/src/templates/dashboard-js/components/cli-history.js +876 -0
- package/ccw/src/templates/dashboard-js/components/cli-status.js +978 -0
- package/ccw/src/templates/dashboard-js/components/global-notifications.js +508 -219
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +1277 -282
- package/ccw/src/templates/dashboard-js/components/index-manager.js +302 -0
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +718 -27
- package/ccw/src/templates/dashboard-js/components/modals.js +66 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +80 -12
- package/ccw/src/templates/dashboard-js/components/notifications.js +758 -194
- package/ccw/src/templates/dashboard-js/components/storage-manager.js +478 -0
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +157 -6
- package/ccw/src/templates/dashboard-js/components/task-queue-sidebar.js +716 -0
- package/ccw/src/templates/dashboard-js/help-i18n.js +272 -0
- package/ccw/src/templates/dashboard-js/i18n.js +2807 -0
- package/ccw/src/templates/dashboard-js/main.js +15 -0
- package/ccw/src/templates/dashboard-js/state.js +243 -42
- package/ccw/src/templates/dashboard-js/utils.js +47 -1
- package/ccw/src/templates/dashboard-js/views/claude-manager.js +912 -0
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +2272 -0
- package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +964 -0
- package/ccw/src/templates/dashboard-js/views/core-memory-clusters.js +503 -0
- package/ccw/src/templates/dashboard-js/views/core-memory.js +782 -0
- package/ccw/src/templates/dashboard-js/views/explorer.js +888 -852
- package/ccw/src/templates/dashboard-js/views/graph-explorer.js +1157 -0
- package/ccw/src/templates/dashboard-js/views/help.js +856 -0
- package/ccw/src/templates/dashboard-js/views/history.js +337 -0
- package/ccw/src/templates/dashboard-js/views/home.js +61 -15
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +311 -43
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +204 -28
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +2187 -411
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.backup +1729 -0
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js.new +928 -0
- package/ccw/src/templates/dashboard-js/views/memory.js +1221 -0
- package/ccw/src/templates/dashboard-js/views/prompt-history.js +713 -0
- package/ccw/src/templates/dashboard-js/views/rules-manager.js +828 -0
- package/ccw/src/templates/dashboard-js/views/session-detail.js +54 -53
- package/ccw/src/templates/dashboard-js/views/skills-manager.js +819 -0
- package/ccw/src/templates/dashboard.html +185 -85
- package/ccw/src/templates/hooks-config-example.json +60 -0
- package/ccw/src/tools/classify-folders.ts +245 -0
- package/ccw/src/tools/cli-config-manager.ts +268 -0
- package/ccw/src/tools/cli-executor.ts +2014 -0
- package/ccw/src/tools/cli-history-store.ts +1195 -0
- package/ccw/src/tools/codex-lens.ts +1141 -0
- package/ccw/src/tools/{convert-tokens-to-css.js → convert-tokens-to-css.ts} +73 -23
- package/ccw/src/tools/core-memory.ts +444 -0
- package/ccw/src/tools/detect-changed-modules.ts +325 -0
- package/ccw/src/tools/{discover-design-files.js → discover-design-files.ts} +74 -24
- package/ccw/src/tools/edit-file.ts +568 -0
- package/ccw/src/tools/{generate-module-docs.js → generate-module-docs.ts} +207 -185
- package/ccw/src/tools/{get-modules-by-depth.js → get-modules-by-depth.ts} +120 -79
- package/ccw/src/tools/index.ts +370 -0
- package/ccw/src/tools/native-session-discovery.ts +795 -0
- package/ccw/src/tools/notifier.ts +129 -0
- package/ccw/src/tools/read-file.ts +410 -0
- package/ccw/src/tools/resume-strategy.ts +345 -0
- package/ccw/src/tools/session-content-parser.ts +619 -0
- package/ccw/src/tools/session-manager.ts +1026 -0
- package/ccw/src/tools/smart-context.ts +228 -0
- package/ccw/src/tools/smart-search.ts +2065 -0
- package/ccw/src/tools/smart-search.ts.backup +1233 -0
- package/ccw/src/tools/storage-manager.ts +455 -0
- package/ccw/src/tools/write-file.ts +222 -0
- package/ccw/src/types/config.ts +11 -0
- package/ccw/src/types/index.ts +3 -0
- package/ccw/src/types/session.ts +25 -0
- package/ccw/src/types/tool.ts +41 -0
- package/ccw/src/utils/{browser-launcher.js → browser-launcher.ts} +10 -8
- package/ccw/src/utils/file-utils.ts +48 -0
- package/ccw/src/utils/{path-resolver.js → path-resolver.ts} +114 -78
- package/ccw/src/utils/path-validator.ts +153 -0
- package/ccw/src/utils/{ui.js → ui.ts} +32 -25
- package/codex-lens/pyproject.toml +48 -0
- package/codex-lens/src/codexlens/.workflow/.cli-history/history.db +0 -0
- package/codex-lens/src/codexlens/__init__.py +28 -0
- package/codex-lens/src/codexlens/__main__.py +14 -0
- package/codex-lens/src/codexlens/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/__main__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/entities.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/__pycache__/errors.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__init__.py +27 -0
- package/codex-lens/src/codexlens/cli/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/output.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +1931 -0
- package/codex-lens/src/codexlens/cli/embedding_manager.py +620 -0
- package/codex-lens/src/codexlens/cli/model_manager.py +289 -0
- package/codex-lens/src/codexlens/cli/output.py +124 -0
- package/codex-lens/src/codexlens/config.py +201 -0
- package/codex-lens/src/codexlens/entities.py +121 -0
- package/codex-lens/src/codexlens/errors.py +55 -0
- package/codex-lens/src/codexlens/indexing/README.md +77 -0
- package/codex-lens/src/codexlens/indexing/__init__.py +4 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/__pycache__/symbol_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/indexing/symbol_extractor.py +243 -0
- package/codex-lens/src/codexlens/parsers/__init__.py +8 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/encoding.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/factory.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/tokenizer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/__pycache__/treesitter_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/parsers/encoding.py +202 -0
- package/codex-lens/src/codexlens/parsers/factory.py +256 -0
- package/codex-lens/src/codexlens/parsers/tokenizer.py +98 -0
- package/codex-lens/src/codexlens/parsers/treesitter_parser.py +335 -0
- package/codex-lens/src/codexlens/search/__init__.py +15 -0
- package/codex-lens/src/codexlens/search/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/enrichment.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/query_parser.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/chain_search.py +647 -0
- package/codex-lens/src/codexlens/search/enrichment.py +150 -0
- package/codex-lens/src/codexlens/search/hybrid_search.py +313 -0
- package/codex-lens/src/codexlens/search/query_parser.py +242 -0
- package/codex-lens/src/codexlens/search/ranking.py +274 -0
- package/codex-lens/src/codexlens/semantic/__init__.py +39 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/ann_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/code_extractor.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/embedder.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/graph_analyzer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/llm_enhancer.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/ann_index.py +414 -0
- package/codex-lens/src/codexlens/semantic/chunker.py +448 -0
- package/codex-lens/src/codexlens/semantic/code_extractor.py +274 -0
- package/codex-lens/src/codexlens/semantic/embedder.py +185 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +955 -0
- package/codex-lens/src/codexlens/storage/__init__.py +29 -0
- package/codex-lens/src/codexlens/storage/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/dir_index.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/file_cache.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/migration_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/registry.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/__pycache__/sqlite_utils.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/dir_index.py +1850 -0
- package/codex-lens/src/codexlens/storage/file_cache.py +32 -0
- package/codex-lens/src/codexlens/storage/index_tree.py +776 -0
- package/codex-lens/src/codexlens/storage/migration_manager.py +154 -0
- package/codex-lens/src/codexlens/storage/migrations/__init__.py +1 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_001_normalize_keywords.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_002_add_token_metadata.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_003_code_relationships.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_004_dual_fts.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/__pycache__/migration_005_cleanup_unused_fields.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_001_normalize_keywords.py +123 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_002_add_token_metadata.py +48 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_004_dual_fts.py +232 -0
- package/codex-lens/src/codexlens/storage/migrations/migration_005_cleanup_unused_fields.py +196 -0
- package/codex-lens/src/codexlens/storage/path_mapper.py +274 -0
- package/codex-lens/src/codexlens/storage/registry.py +670 -0
- package/codex-lens/src/codexlens/storage/sqlite_store.py +576 -0
- package/codex-lens/src/codexlens/storage/sqlite_utils.py +64 -0
- package/package.json +4 -1
- package/.claude/commands/memory/tech-research.md +0 -477
- package/.claude/scripts/classify-folders.sh +0 -39
- package/.claude/scripts/convert_tokens_to_css.sh +0 -229
- package/.claude/scripts/detect_changed_modules.sh +0 -161
- package/.claude/scripts/discover-design-files.sh +0 -87
- package/.claude/scripts/extract-animations.js +0 -243
- package/.claude/scripts/extract-computed-styles.js +0 -118
- package/.claude/scripts/extract-layout-structure.js +0 -411
- package/.claude/scripts/generate_module_docs.sh +0 -717
- package/.claude/scripts/get_modules_by_depth.sh +0 -170
- package/.claude/scripts/ui-generate-preview.sh +0 -395
- package/.claude/scripts/ui-instantiate-prototypes.sh +0 -815
- package/.claude/scripts/update_module_claude.sh +0 -337
- package/.claude/workflows/context-search-strategy.md +0 -77
- package/.claude/workflows/intelligent-tools-strategy.md +0 -662
- package/ccw/src/cli.js +0 -119
- package/ccw/src/commands/install.js +0 -324
- package/ccw/src/commands/tool.js +0 -138
- package/ccw/src/core/data-aggregator.js +0 -409
- package/ccw/src/core/server.js +0 -2063
- package/ccw/src/core/session-scanner.js +0 -235
- package/ccw/src/tools/classify-folders.js +0 -204
- package/ccw/src/tools/detect-changed-modules.js +0 -288
- package/ccw/src/tools/edit-file.js +0 -266
- package/ccw/src/tools/index.js +0 -176
- package/ccw/src/utils/file-utils.js +0 -48
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Optional encoding detection module for CodexLens.
|
|
2
|
+
|
|
3
|
+
Provides automatic encoding detection with graceful fallback to UTF-8.
|
|
4
|
+
Install with: pip install codexlens[encoding]
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Tuple, Optional
|
|
12
|
+
|
|
13
|
+
log = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
# Feature flag for encoding detection availability
|
|
16
|
+
ENCODING_DETECTION_AVAILABLE = False
|
|
17
|
+
_import_error: Optional[str] = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _detect_chardet_backend() -> Tuple[bool, Optional[str]]:
|
|
21
|
+
"""Detect if chardet or charset-normalizer is available."""
|
|
22
|
+
try:
|
|
23
|
+
import chardet
|
|
24
|
+
return True, None
|
|
25
|
+
except ImportError:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
from charset_normalizer import from_bytes
|
|
30
|
+
return True, None
|
|
31
|
+
except ImportError:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
return False, "chardet not available. Install with: pip install codexlens[encoding]"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Initialize on module load
|
|
38
|
+
ENCODING_DETECTION_AVAILABLE, _import_error = _detect_chardet_backend()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def check_encoding_available() -> Tuple[bool, Optional[str]]:
|
|
42
|
+
"""Check if encoding detection dependencies are available.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Tuple of (available, error_message)
|
|
46
|
+
"""
|
|
47
|
+
return ENCODING_DETECTION_AVAILABLE, _import_error
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def detect_encoding(content_bytes: bytes, confidence_threshold: float = 0.7) -> str:
|
|
51
|
+
"""Detect encoding from file content bytes.
|
|
52
|
+
|
|
53
|
+
Uses chardet or charset-normalizer with configurable confidence threshold.
|
|
54
|
+
Falls back to UTF-8 if confidence is too low or detection unavailable.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
content_bytes: Raw file content as bytes
|
|
58
|
+
confidence_threshold: Minimum confidence (0.0-1.0) to accept detection
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
Detected encoding name (e.g., 'utf-8', 'iso-8859-1', 'gbk')
|
|
62
|
+
Returns 'utf-8' as fallback if detection fails or confidence too low
|
|
63
|
+
"""
|
|
64
|
+
if not ENCODING_DETECTION_AVAILABLE:
|
|
65
|
+
log.debug("Encoding detection not available, using UTF-8 fallback")
|
|
66
|
+
return "utf-8"
|
|
67
|
+
|
|
68
|
+
if not content_bytes:
|
|
69
|
+
return "utf-8"
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
# Try chardet first
|
|
73
|
+
try:
|
|
74
|
+
import chardet
|
|
75
|
+
result = chardet.detect(content_bytes)
|
|
76
|
+
encoding = result.get("encoding")
|
|
77
|
+
confidence = result.get("confidence", 0.0)
|
|
78
|
+
|
|
79
|
+
if encoding and confidence >= confidence_threshold:
|
|
80
|
+
log.debug(f"Detected encoding: {encoding} (confidence: {confidence:.2f})")
|
|
81
|
+
# Normalize encoding name: replace underscores with hyphens
|
|
82
|
+
return encoding.lower().replace('_', '-')
|
|
83
|
+
else:
|
|
84
|
+
log.debug(
|
|
85
|
+
f"Low confidence encoding detection: {encoding} "
|
|
86
|
+
f"(confidence: {confidence:.2f}), using UTF-8 fallback"
|
|
87
|
+
)
|
|
88
|
+
return "utf-8"
|
|
89
|
+
except ImportError:
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
# Fallback to charset-normalizer
|
|
93
|
+
try:
|
|
94
|
+
from charset_normalizer import from_bytes
|
|
95
|
+
results = from_bytes(content_bytes)
|
|
96
|
+
if results:
|
|
97
|
+
best = results.best()
|
|
98
|
+
if best and best.encoding:
|
|
99
|
+
log.debug(f"Detected encoding via charset-normalizer: {best.encoding}")
|
|
100
|
+
# Normalize encoding name: replace underscores with hyphens
|
|
101
|
+
return best.encoding.lower().replace('_', '-')
|
|
102
|
+
except ImportError:
|
|
103
|
+
pass
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
log.warning(f"Encoding detection failed: {e}, using UTF-8 fallback")
|
|
107
|
+
|
|
108
|
+
return "utf-8"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def read_file_safe(
|
|
112
|
+
path: Path | str,
|
|
113
|
+
confidence_threshold: float = 0.7,
|
|
114
|
+
max_detection_bytes: int = 100_000
|
|
115
|
+
) -> Tuple[str, str]:
|
|
116
|
+
"""Read file with automatic encoding detection and safe decoding.
|
|
117
|
+
|
|
118
|
+
Reads file bytes, detects encoding, and decodes with error replacement
|
|
119
|
+
to preserve file structure even with encoding issues.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
path: Path to file to read
|
|
123
|
+
confidence_threshold: Minimum confidence for encoding detection
|
|
124
|
+
max_detection_bytes: Maximum bytes to use for encoding detection (default 100KB)
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Tuple of (content, detected_encoding)
|
|
128
|
+
- content: Decoded file content (with � for unmappable bytes)
|
|
129
|
+
- detected_encoding: Detected encoding name
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
OSError: If file cannot be read
|
|
133
|
+
IsADirectoryError: If path is a directory
|
|
134
|
+
"""
|
|
135
|
+
file_path = Path(path) if isinstance(path, str) else path
|
|
136
|
+
|
|
137
|
+
# Read file bytes
|
|
138
|
+
try:
|
|
139
|
+
content_bytes = file_path.read_bytes()
|
|
140
|
+
except Exception as e:
|
|
141
|
+
log.error(f"Failed to read file {file_path}: {e}")
|
|
142
|
+
raise
|
|
143
|
+
|
|
144
|
+
# Detect encoding from first N bytes for performance
|
|
145
|
+
detection_sample = content_bytes[:max_detection_bytes] if len(content_bytes) > max_detection_bytes else content_bytes
|
|
146
|
+
encoding = detect_encoding(detection_sample, confidence_threshold)
|
|
147
|
+
|
|
148
|
+
# Decode with error replacement to preserve structure
|
|
149
|
+
try:
|
|
150
|
+
content = content_bytes.decode(encoding, errors='replace')
|
|
151
|
+
log.debug(f"Successfully decoded {file_path} using {encoding}")
|
|
152
|
+
return content, encoding
|
|
153
|
+
except Exception as e:
|
|
154
|
+
# Final fallback to UTF-8 with replacement
|
|
155
|
+
log.warning(f"Failed to decode {file_path} with {encoding}, using UTF-8: {e}")
|
|
156
|
+
content = content_bytes.decode('utf-8', errors='replace')
|
|
157
|
+
return content, 'utf-8'
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def is_binary_file(path: Path | str, sample_size: int = 8192) -> bool:
|
|
161
|
+
"""Check if file is likely binary by sampling first bytes.
|
|
162
|
+
|
|
163
|
+
Uses heuristic: if >30% of sample bytes are null or non-text, consider binary.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
path: Path to file to check
|
|
167
|
+
sample_size: Number of bytes to sample (default 8KB)
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
True if file appears to be binary, False otherwise
|
|
171
|
+
"""
|
|
172
|
+
file_path = Path(path) if isinstance(path, str) else path
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
with file_path.open('rb') as f:
|
|
176
|
+
sample = f.read(sample_size)
|
|
177
|
+
|
|
178
|
+
if not sample:
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
# Count null bytes and non-printable characters
|
|
182
|
+
null_count = sample.count(b'\x00')
|
|
183
|
+
non_text_count = sum(1 for byte in sample if byte < 0x20 and byte not in (0x09, 0x0a, 0x0d))
|
|
184
|
+
|
|
185
|
+
# If >30% null bytes or >50% non-text, consider binary
|
|
186
|
+
null_ratio = null_count / len(sample)
|
|
187
|
+
non_text_ratio = non_text_count / len(sample)
|
|
188
|
+
|
|
189
|
+
return null_ratio > 0.3 or non_text_ratio > 0.5
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
log.debug(f"Binary check failed for {file_path}: {e}, assuming text")
|
|
193
|
+
return False
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
__all__ = [
|
|
197
|
+
"ENCODING_DETECTION_AVAILABLE",
|
|
198
|
+
"check_encoding_available",
|
|
199
|
+
"detect_encoding",
|
|
200
|
+
"read_file_safe",
|
|
201
|
+
"is_binary_file",
|
|
202
|
+
]
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Parser factory for CodexLens.
|
|
2
|
+
|
|
3
|
+
Python and JavaScript/TypeScript parsing use Tree-Sitter grammars when
|
|
4
|
+
available. Regex fallbacks are retained to preserve the existing parser
|
|
5
|
+
interface and behavior in minimal environments.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Dict, List, Optional, Protocol
|
|
14
|
+
|
|
15
|
+
from codexlens.config import Config
|
|
16
|
+
from codexlens.entities import IndexedFile, Symbol
|
|
17
|
+
from codexlens.parsers.treesitter_parser import TreeSitterSymbolParser
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Parser(Protocol):
|
|
21
|
+
def parse(self, text: str, path: Path) -> IndexedFile: ...
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class SimpleRegexParser:
|
|
26
|
+
language_id: str
|
|
27
|
+
|
|
28
|
+
def parse(self, text: str, path: Path) -> IndexedFile:
|
|
29
|
+
# Try tree-sitter first for supported languages
|
|
30
|
+
if self.language_id in {"python", "javascript", "typescript"}:
|
|
31
|
+
ts_parser = TreeSitterSymbolParser(self.language_id, path)
|
|
32
|
+
if ts_parser.is_available():
|
|
33
|
+
symbols = ts_parser.parse_symbols(text)
|
|
34
|
+
if symbols is not None:
|
|
35
|
+
return IndexedFile(
|
|
36
|
+
path=str(path.resolve()),
|
|
37
|
+
language=self.language_id,
|
|
38
|
+
symbols=symbols,
|
|
39
|
+
chunks=[],
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Fallback to regex parsing
|
|
43
|
+
if self.language_id == "python":
|
|
44
|
+
symbols = _parse_python_symbols_regex(text)
|
|
45
|
+
elif self.language_id in {"javascript", "typescript"}:
|
|
46
|
+
symbols = _parse_js_ts_symbols_regex(text)
|
|
47
|
+
elif self.language_id == "java":
|
|
48
|
+
symbols = _parse_java_symbols(text)
|
|
49
|
+
elif self.language_id == "go":
|
|
50
|
+
symbols = _parse_go_symbols(text)
|
|
51
|
+
elif self.language_id == "markdown":
|
|
52
|
+
symbols = _parse_markdown_symbols(text)
|
|
53
|
+
elif self.language_id == "text":
|
|
54
|
+
symbols = _parse_text_symbols(text)
|
|
55
|
+
else:
|
|
56
|
+
symbols = _parse_generic_symbols(text)
|
|
57
|
+
|
|
58
|
+
return IndexedFile(
|
|
59
|
+
path=str(path.resolve()),
|
|
60
|
+
language=self.language_id,
|
|
61
|
+
symbols=symbols,
|
|
62
|
+
chunks=[],
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ParserFactory:
|
|
67
|
+
def __init__(self, config: Config) -> None:
|
|
68
|
+
self.config = config
|
|
69
|
+
self._parsers: Dict[str, Parser] = {}
|
|
70
|
+
|
|
71
|
+
def get_parser(self, language_id: str) -> Parser:
|
|
72
|
+
if language_id not in self._parsers:
|
|
73
|
+
self._parsers[language_id] = SimpleRegexParser(language_id)
|
|
74
|
+
return self._parsers[language_id]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Regex-based fallback parsers
|
|
78
|
+
_PY_CLASS_RE = re.compile(r"^\s*class\s+([A-Za-z_]\w*)\b")
|
|
79
|
+
_PY_DEF_RE = re.compile(r"^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _parse_python_symbols(text: str) -> List[Symbol]:
|
|
85
|
+
"""Parse Python symbols, using tree-sitter if available, regex fallback."""
|
|
86
|
+
ts_parser = TreeSitterSymbolParser("python")
|
|
87
|
+
if ts_parser.is_available():
|
|
88
|
+
symbols = ts_parser.parse_symbols(text)
|
|
89
|
+
if symbols is not None:
|
|
90
|
+
return symbols
|
|
91
|
+
return _parse_python_symbols_regex(text)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _parse_js_ts_symbols(
|
|
95
|
+
text: str,
|
|
96
|
+
language_id: str = "javascript",
|
|
97
|
+
path: Optional[Path] = None,
|
|
98
|
+
) -> List[Symbol]:
|
|
99
|
+
"""Parse JS/TS symbols, using tree-sitter if available, regex fallback."""
|
|
100
|
+
ts_parser = TreeSitterSymbolParser(language_id, path)
|
|
101
|
+
if ts_parser.is_available():
|
|
102
|
+
symbols = ts_parser.parse_symbols(text)
|
|
103
|
+
if symbols is not None:
|
|
104
|
+
return symbols
|
|
105
|
+
return _parse_js_ts_symbols_regex(text)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _parse_python_symbols_regex(text: str) -> List[Symbol]:
|
|
109
|
+
symbols: List[Symbol] = []
|
|
110
|
+
current_class_indent: Optional[int] = None
|
|
111
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
112
|
+
class_match = _PY_CLASS_RE.match(line)
|
|
113
|
+
if class_match:
|
|
114
|
+
current_class_indent = len(line) - len(line.lstrip(" "))
|
|
115
|
+
symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
|
|
116
|
+
continue
|
|
117
|
+
def_match = _PY_DEF_RE.match(line)
|
|
118
|
+
if def_match:
|
|
119
|
+
indent = len(line) - len(line.lstrip(" "))
|
|
120
|
+
kind = "method" if current_class_indent is not None and indent > current_class_indent else "function"
|
|
121
|
+
symbols.append(Symbol(name=def_match.group(1), kind=kind, range=(i, i)))
|
|
122
|
+
continue
|
|
123
|
+
if current_class_indent is not None:
|
|
124
|
+
indent = len(line) - len(line.lstrip(" "))
|
|
125
|
+
if line.strip() and indent <= current_class_indent:
|
|
126
|
+
current_class_indent = None
|
|
127
|
+
return symbols
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
_JS_FUNC_RE = re.compile(r"^\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(")
|
|
131
|
+
_JS_CLASS_RE = re.compile(r"^\s*(?:export\s+)?class\s+([A-Za-z_$][\w$]*)\b")
|
|
132
|
+
_JS_ARROW_RE = re.compile(
|
|
133
|
+
r"^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s*)?\(?[^)]*\)?\s*=>"
|
|
134
|
+
)
|
|
135
|
+
_JS_METHOD_RE = re.compile(r"^\s+(?:async\s+)?([A-Za-z_$][\w$]*)\s*\([^)]*\)\s*\{")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _parse_js_ts_symbols_regex(text: str) -> List[Symbol]:
|
|
139
|
+
symbols: List[Symbol] = []
|
|
140
|
+
in_class = False
|
|
141
|
+
class_brace_depth = 0
|
|
142
|
+
brace_depth = 0
|
|
143
|
+
|
|
144
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
145
|
+
brace_depth += line.count("{") - line.count("}")
|
|
146
|
+
|
|
147
|
+
class_match = _JS_CLASS_RE.match(line)
|
|
148
|
+
if class_match:
|
|
149
|
+
symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
|
|
150
|
+
in_class = True
|
|
151
|
+
class_brace_depth = brace_depth
|
|
152
|
+
continue
|
|
153
|
+
|
|
154
|
+
if in_class and brace_depth < class_brace_depth:
|
|
155
|
+
in_class = False
|
|
156
|
+
|
|
157
|
+
func_match = _JS_FUNC_RE.match(line)
|
|
158
|
+
if func_match:
|
|
159
|
+
symbols.append(Symbol(name=func_match.group(1), kind="function", range=(i, i)))
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
arrow_match = _JS_ARROW_RE.match(line)
|
|
163
|
+
if arrow_match:
|
|
164
|
+
symbols.append(Symbol(name=arrow_match.group(1), kind="function", range=(i, i)))
|
|
165
|
+
continue
|
|
166
|
+
|
|
167
|
+
if in_class:
|
|
168
|
+
method_match = _JS_METHOD_RE.match(line)
|
|
169
|
+
if method_match:
|
|
170
|
+
name = method_match.group(1)
|
|
171
|
+
if name != "constructor":
|
|
172
|
+
symbols.append(Symbol(name=name, kind="method", range=(i, i)))
|
|
173
|
+
|
|
174
|
+
return symbols
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
_JAVA_CLASS_RE = re.compile(r"^\s*(?:public\s+)?class\s+([A-Za-z_]\w*)\b")
|
|
178
|
+
_JAVA_METHOD_RE = re.compile(
|
|
179
|
+
r"^\s*(?:public|private|protected|static|\s)+[\w<>\[\]]+\s+([A-Za-z_]\w*)\s*\("
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _parse_java_symbols(text: str) -> List[Symbol]:
|
|
184
|
+
symbols: List[Symbol] = []
|
|
185
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
186
|
+
class_match = _JAVA_CLASS_RE.match(line)
|
|
187
|
+
if class_match:
|
|
188
|
+
symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
|
|
189
|
+
continue
|
|
190
|
+
method_match = _JAVA_METHOD_RE.match(line)
|
|
191
|
+
if method_match:
|
|
192
|
+
symbols.append(Symbol(name=method_match.group(1), kind="method", range=(i, i)))
|
|
193
|
+
return symbols
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
_GO_FUNC_RE = re.compile(r"^\s*func\s+(?:\([^)]+\)\s+)?([A-Za-z_]\w*)\s*\(")
|
|
197
|
+
_GO_TYPE_RE = re.compile(r"^\s*type\s+([A-Za-z_]\w*)\s+(?:struct|interface)\b")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _parse_go_symbols(text: str) -> List[Symbol]:
|
|
201
|
+
symbols: List[Symbol] = []
|
|
202
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
203
|
+
type_match = _GO_TYPE_RE.match(line)
|
|
204
|
+
if type_match:
|
|
205
|
+
symbols.append(Symbol(name=type_match.group(1), kind="class", range=(i, i)))
|
|
206
|
+
continue
|
|
207
|
+
func_match = _GO_FUNC_RE.match(line)
|
|
208
|
+
if func_match:
|
|
209
|
+
symbols.append(Symbol(name=func_match.group(1), kind="function", range=(i, i)))
|
|
210
|
+
return symbols
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
_GENERIC_DEF_RE = re.compile(r"^\s*(?:def|function|func)\s+([A-Za-z_]\w*)\b")
|
|
214
|
+
_GENERIC_CLASS_RE = re.compile(r"^\s*(?:class|struct|interface)\s+([A-Za-z_]\w*)\b")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _parse_generic_symbols(text: str) -> List[Symbol]:
|
|
218
|
+
symbols: List[Symbol] = []
|
|
219
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
220
|
+
class_match = _GENERIC_CLASS_RE.match(line)
|
|
221
|
+
if class_match:
|
|
222
|
+
symbols.append(Symbol(name=class_match.group(1), kind="class", range=(i, i)))
|
|
223
|
+
continue
|
|
224
|
+
def_match = _GENERIC_DEF_RE.match(line)
|
|
225
|
+
if def_match:
|
|
226
|
+
symbols.append(Symbol(name=def_match.group(1), kind="function", range=(i, i)))
|
|
227
|
+
return symbols
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# Markdown heading regex: # Heading, ## Heading, etc.
|
|
231
|
+
_MD_HEADING_RE = re.compile(r"^(#{1,6})\s+(.+)$")
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _parse_markdown_symbols(text: str) -> List[Symbol]:
|
|
235
|
+
"""Parse Markdown headings as symbols.
|
|
236
|
+
|
|
237
|
+
Extracts # headings as 'section' symbols with heading level as kind suffix.
|
|
238
|
+
"""
|
|
239
|
+
symbols: List[Symbol] = []
|
|
240
|
+
for i, line in enumerate(text.splitlines(), start=1):
|
|
241
|
+
heading_match = _MD_HEADING_RE.match(line)
|
|
242
|
+
if heading_match:
|
|
243
|
+
level = len(heading_match.group(1))
|
|
244
|
+
title = heading_match.group(2).strip()
|
|
245
|
+
# Use 'section' kind with level indicator
|
|
246
|
+
kind = f"h{level}"
|
|
247
|
+
symbols.append(Symbol(name=title, kind=kind, range=(i, i)))
|
|
248
|
+
return symbols
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _parse_text_symbols(text: str) -> List[Symbol]:
|
|
252
|
+
"""Parse plain text files - no symbols, just index content."""
|
|
253
|
+
# Text files don't have structured symbols, return empty list
|
|
254
|
+
# The file content will still be indexed for FTS search
|
|
255
|
+
return []
|
|
256
|
+
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Token counting utilities for CodexLens.
|
|
2
|
+
|
|
3
|
+
Provides accurate token counting using tiktoken with character count fallback.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import tiktoken
|
|
12
|
+
TIKTOKEN_AVAILABLE = True
|
|
13
|
+
except ImportError:
|
|
14
|
+
TIKTOKEN_AVAILABLE = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Tokenizer:
|
|
18
|
+
"""Token counter with tiktoken primary and character count fallback."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, encoding_name: str = "cl100k_base") -> None:
|
|
21
|
+
"""Initialize tokenizer.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
encoding_name: Tiktoken encoding name (default: cl100k_base for GPT-4)
|
|
25
|
+
"""
|
|
26
|
+
self._encoding: Optional[object] = None
|
|
27
|
+
self._encoding_name = encoding_name
|
|
28
|
+
|
|
29
|
+
if TIKTOKEN_AVAILABLE:
|
|
30
|
+
try:
|
|
31
|
+
self._encoding = tiktoken.get_encoding(encoding_name)
|
|
32
|
+
except Exception:
|
|
33
|
+
# Fallback to character counting if encoding fails
|
|
34
|
+
self._encoding = None
|
|
35
|
+
|
|
36
|
+
def count_tokens(self, text: str) -> int:
|
|
37
|
+
"""Count tokens in text.
|
|
38
|
+
|
|
39
|
+
Uses tiktoken if available, otherwise falls back to character count / 4.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
text: Text to count tokens for
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Estimated token count
|
|
46
|
+
"""
|
|
47
|
+
if not text:
|
|
48
|
+
return 0
|
|
49
|
+
|
|
50
|
+
if self._encoding is not None:
|
|
51
|
+
try:
|
|
52
|
+
return len(self._encoding.encode(text)) # type: ignore[attr-defined]
|
|
53
|
+
except Exception:
|
|
54
|
+
# Fall through to character count fallback
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
# Fallback: rough estimate using character count
|
|
58
|
+
# Average of ~4 characters per token for English text
|
|
59
|
+
return max(1, len(text) // 4)
|
|
60
|
+
|
|
61
|
+
def is_using_tiktoken(self) -> bool:
|
|
62
|
+
"""Check if tiktoken is being used.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
True if tiktoken is available and initialized
|
|
66
|
+
"""
|
|
67
|
+
return self._encoding is not None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# Global default tokenizer instance
|
|
71
|
+
_default_tokenizer: Optional[Tokenizer] = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_default_tokenizer() -> Tokenizer:
|
|
75
|
+
"""Get the global default tokenizer instance.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Shared Tokenizer instance
|
|
79
|
+
"""
|
|
80
|
+
global _default_tokenizer
|
|
81
|
+
if _default_tokenizer is None:
|
|
82
|
+
_default_tokenizer = Tokenizer()
|
|
83
|
+
return _default_tokenizer
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def count_tokens(text: str, tokenizer: Optional[Tokenizer] = None) -> int:
|
|
87
|
+
"""Count tokens in text using default or provided tokenizer.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
text: Text to count tokens for
|
|
91
|
+
tokenizer: Optional tokenizer instance (uses default if None)
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Estimated token count
|
|
95
|
+
"""
|
|
96
|
+
if tokenizer is None:
|
|
97
|
+
tokenizer = get_default_tokenizer()
|
|
98
|
+
return tokenizer.count_tokens(text)
|