codexa 0.4.0__py3-none-any.whl

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.
Files changed (189) hide show
  1. codexa-0.4.0.dist-info/METADATA +650 -0
  2. codexa-0.4.0.dist-info/RECORD +189 -0
  3. codexa-0.4.0.dist-info/WHEEL +5 -0
  4. codexa-0.4.0.dist-info/entry_points.txt +2 -0
  5. codexa-0.4.0.dist-info/licenses/LICENSE +21 -0
  6. codexa-0.4.0.dist-info/top_level.txt +1 -0
  7. semantic_code_intelligence/__init__.py +5 -0
  8. semantic_code_intelligence/analysis/__init__.py +21 -0
  9. semantic_code_intelligence/analysis/ai_features.py +351 -0
  10. semantic_code_intelligence/bridge/__init__.py +28 -0
  11. semantic_code_intelligence/bridge/context_provider.py +245 -0
  12. semantic_code_intelligence/bridge/protocol.py +167 -0
  13. semantic_code_intelligence/bridge/server.py +348 -0
  14. semantic_code_intelligence/bridge/vscode.py +271 -0
  15. semantic_code_intelligence/ci/__init__.py +13 -0
  16. semantic_code_intelligence/ci/hooks.py +98 -0
  17. semantic_code_intelligence/ci/hotspots.py +272 -0
  18. semantic_code_intelligence/ci/impact.py +246 -0
  19. semantic_code_intelligence/ci/metrics.py +591 -0
  20. semantic_code_intelligence/ci/pr.py +412 -0
  21. semantic_code_intelligence/ci/quality.py +557 -0
  22. semantic_code_intelligence/ci/templates.py +164 -0
  23. semantic_code_intelligence/ci/trace.py +224 -0
  24. semantic_code_intelligence/cli/__init__.py +0 -0
  25. semantic_code_intelligence/cli/commands/__init__.py +0 -0
  26. semantic_code_intelligence/cli/commands/ask_cmd.py +153 -0
  27. semantic_code_intelligence/cli/commands/benchmark_cmd.py +303 -0
  28. semantic_code_intelligence/cli/commands/chat_cmd.py +252 -0
  29. semantic_code_intelligence/cli/commands/ci_gen_cmd.py +74 -0
  30. semantic_code_intelligence/cli/commands/context_cmd.py +120 -0
  31. semantic_code_intelligence/cli/commands/cross_refactor_cmd.py +113 -0
  32. semantic_code_intelligence/cli/commands/deps_cmd.py +91 -0
  33. semantic_code_intelligence/cli/commands/docs_cmd.py +101 -0
  34. semantic_code_intelligence/cli/commands/doctor_cmd.py +147 -0
  35. semantic_code_intelligence/cli/commands/evolve_cmd.py +171 -0
  36. semantic_code_intelligence/cli/commands/explain_cmd.py +112 -0
  37. semantic_code_intelligence/cli/commands/gate_cmd.py +135 -0
  38. semantic_code_intelligence/cli/commands/grep_cmd.py +234 -0
  39. semantic_code_intelligence/cli/commands/hotspots_cmd.py +119 -0
  40. semantic_code_intelligence/cli/commands/impact_cmd.py +131 -0
  41. semantic_code_intelligence/cli/commands/index_cmd.py +138 -0
  42. semantic_code_intelligence/cli/commands/init_cmd.py +152 -0
  43. semantic_code_intelligence/cli/commands/investigate_cmd.py +163 -0
  44. semantic_code_intelligence/cli/commands/languages_cmd.py +101 -0
  45. semantic_code_intelligence/cli/commands/lsp_cmd.py +49 -0
  46. semantic_code_intelligence/cli/commands/mcp_cmd.py +50 -0
  47. semantic_code_intelligence/cli/commands/metrics_cmd.py +264 -0
  48. semantic_code_intelligence/cli/commands/models_cmd.py +157 -0
  49. semantic_code_intelligence/cli/commands/plugin_cmd.py +275 -0
  50. semantic_code_intelligence/cli/commands/pr_summary_cmd.py +178 -0
  51. semantic_code_intelligence/cli/commands/quality_cmd.py +208 -0
  52. semantic_code_intelligence/cli/commands/refactor_cmd.py +103 -0
  53. semantic_code_intelligence/cli/commands/review_cmd.py +88 -0
  54. semantic_code_intelligence/cli/commands/search_cmd.py +236 -0
  55. semantic_code_intelligence/cli/commands/serve_cmd.py +117 -0
  56. semantic_code_intelligence/cli/commands/suggest_cmd.py +100 -0
  57. semantic_code_intelligence/cli/commands/summary_cmd.py +78 -0
  58. semantic_code_intelligence/cli/commands/tool_cmd.py +282 -0
  59. semantic_code_intelligence/cli/commands/trace_cmd.py +123 -0
  60. semantic_code_intelligence/cli/commands/tui_cmd.py +58 -0
  61. semantic_code_intelligence/cli/commands/viz_cmd.py +127 -0
  62. semantic_code_intelligence/cli/commands/watch_cmd.py +72 -0
  63. semantic_code_intelligence/cli/commands/web_cmd.py +61 -0
  64. semantic_code_intelligence/cli/commands/workspace_cmd.py +250 -0
  65. semantic_code_intelligence/cli/main.py +65 -0
  66. semantic_code_intelligence/cli/router.py +92 -0
  67. semantic_code_intelligence/config/__init__.py +0 -0
  68. semantic_code_intelligence/config/settings.py +260 -0
  69. semantic_code_intelligence/context/__init__.py +19 -0
  70. semantic_code_intelligence/context/engine.py +429 -0
  71. semantic_code_intelligence/context/memory.py +253 -0
  72. semantic_code_intelligence/daemon/__init__.py +1 -0
  73. semantic_code_intelligence/daemon/watcher.py +515 -0
  74. semantic_code_intelligence/docs/__init__.py +1080 -0
  75. semantic_code_intelligence/embeddings/__init__.py +0 -0
  76. semantic_code_intelligence/embeddings/enhanced.py +131 -0
  77. semantic_code_intelligence/embeddings/generator.py +149 -0
  78. semantic_code_intelligence/embeddings/model_registry.py +100 -0
  79. semantic_code_intelligence/evolution/__init__.py +1 -0
  80. semantic_code_intelligence/evolution/budget_guard.py +111 -0
  81. semantic_code_intelligence/evolution/commit_manager.py +88 -0
  82. semantic_code_intelligence/evolution/context_builder.py +131 -0
  83. semantic_code_intelligence/evolution/engine.py +249 -0
  84. semantic_code_intelligence/evolution/patch_generator.py +229 -0
  85. semantic_code_intelligence/evolution/task_selector.py +214 -0
  86. semantic_code_intelligence/evolution/test_runner.py +111 -0
  87. semantic_code_intelligence/indexing/__init__.py +0 -0
  88. semantic_code_intelligence/indexing/chunker.py +174 -0
  89. semantic_code_intelligence/indexing/parallel.py +86 -0
  90. semantic_code_intelligence/indexing/scanner.py +146 -0
  91. semantic_code_intelligence/indexing/semantic_chunker.py +337 -0
  92. semantic_code_intelligence/llm/__init__.py +62 -0
  93. semantic_code_intelligence/llm/cache.py +219 -0
  94. semantic_code_intelligence/llm/cached_provider.py +145 -0
  95. semantic_code_intelligence/llm/conversation.py +190 -0
  96. semantic_code_intelligence/llm/cross_refactor.py +272 -0
  97. semantic_code_intelligence/llm/investigation.py +274 -0
  98. semantic_code_intelligence/llm/mock_provider.py +77 -0
  99. semantic_code_intelligence/llm/ollama_provider.py +122 -0
  100. semantic_code_intelligence/llm/openai_provider.py +100 -0
  101. semantic_code_intelligence/llm/provider.py +92 -0
  102. semantic_code_intelligence/llm/rate_limiter.py +164 -0
  103. semantic_code_intelligence/llm/reasoning.py +438 -0
  104. semantic_code_intelligence/llm/safety.py +110 -0
  105. semantic_code_intelligence/llm/streaming.py +251 -0
  106. semantic_code_intelligence/lsp/__init__.py +609 -0
  107. semantic_code_intelligence/mcp/__init__.py +393 -0
  108. semantic_code_intelligence/parsing/__init__.py +19 -0
  109. semantic_code_intelligence/parsing/parser.py +375 -0
  110. semantic_code_intelligence/plugins/__init__.py +255 -0
  111. semantic_code_intelligence/plugins/examples/__init__.py +1 -0
  112. semantic_code_intelligence/plugins/examples/code_quality.py +73 -0
  113. semantic_code_intelligence/plugins/examples/search_annotator.py +56 -0
  114. semantic_code_intelligence/scalability/__init__.py +205 -0
  115. semantic_code_intelligence/search/__init__.py +0 -0
  116. semantic_code_intelligence/search/formatter.py +123 -0
  117. semantic_code_intelligence/search/grep.py +361 -0
  118. semantic_code_intelligence/search/hybrid_search.py +170 -0
  119. semantic_code_intelligence/search/keyword_search.py +311 -0
  120. semantic_code_intelligence/search/section_expander.py +103 -0
  121. semantic_code_intelligence/services/__init__.py +0 -0
  122. semantic_code_intelligence/services/indexing_service.py +630 -0
  123. semantic_code_intelligence/services/search_service.py +269 -0
  124. semantic_code_intelligence/storage/__init__.py +0 -0
  125. semantic_code_intelligence/storage/chunk_hash_store.py +86 -0
  126. semantic_code_intelligence/storage/hash_store.py +66 -0
  127. semantic_code_intelligence/storage/index_manifest.py +85 -0
  128. semantic_code_intelligence/storage/index_stats.py +138 -0
  129. semantic_code_intelligence/storage/query_history.py +160 -0
  130. semantic_code_intelligence/storage/symbol_registry.py +209 -0
  131. semantic_code_intelligence/storage/vector_store.py +297 -0
  132. semantic_code_intelligence/tests/__init__.py +0 -0
  133. semantic_code_intelligence/tests/test_ai_features.py +351 -0
  134. semantic_code_intelligence/tests/test_chunker.py +119 -0
  135. semantic_code_intelligence/tests/test_cli.py +188 -0
  136. semantic_code_intelligence/tests/test_config.py +154 -0
  137. semantic_code_intelligence/tests/test_context.py +381 -0
  138. semantic_code_intelligence/tests/test_embeddings.py +73 -0
  139. semantic_code_intelligence/tests/test_endtoend.py +1142 -0
  140. semantic_code_intelligence/tests/test_enhanced_embeddings.py +92 -0
  141. semantic_code_intelligence/tests/test_hash_store.py +79 -0
  142. semantic_code_intelligence/tests/test_logging.py +55 -0
  143. semantic_code_intelligence/tests/test_new_cli.py +138 -0
  144. semantic_code_intelligence/tests/test_parser.py +495 -0
  145. semantic_code_intelligence/tests/test_phase10.py +355 -0
  146. semantic_code_intelligence/tests/test_phase11.py +593 -0
  147. semantic_code_intelligence/tests/test_phase12.py +375 -0
  148. semantic_code_intelligence/tests/test_phase13.py +663 -0
  149. semantic_code_intelligence/tests/test_phase14.py +568 -0
  150. semantic_code_intelligence/tests/test_phase15.py +814 -0
  151. semantic_code_intelligence/tests/test_phase16.py +792 -0
  152. semantic_code_intelligence/tests/test_phase17.py +815 -0
  153. semantic_code_intelligence/tests/test_phase18.py +934 -0
  154. semantic_code_intelligence/tests/test_phase19.py +986 -0
  155. semantic_code_intelligence/tests/test_phase20.py +2753 -0
  156. semantic_code_intelligence/tests/test_phase20b.py +2058 -0
  157. semantic_code_intelligence/tests/test_phase20c.py +962 -0
  158. semantic_code_intelligence/tests/test_phase21.py +428 -0
  159. semantic_code_intelligence/tests/test_phase22.py +799 -0
  160. semantic_code_intelligence/tests/test_phase23.py +783 -0
  161. semantic_code_intelligence/tests/test_phase24.py +715 -0
  162. semantic_code_intelligence/tests/test_phase25.py +496 -0
  163. semantic_code_intelligence/tests/test_phase26.py +251 -0
  164. semantic_code_intelligence/tests/test_phase27.py +531 -0
  165. semantic_code_intelligence/tests/test_phase8.py +592 -0
  166. semantic_code_intelligence/tests/test_phase9.py +643 -0
  167. semantic_code_intelligence/tests/test_plugins.py +293 -0
  168. semantic_code_intelligence/tests/test_priority_features.py +727 -0
  169. semantic_code_intelligence/tests/test_router.py +41 -0
  170. semantic_code_intelligence/tests/test_scalability.py +138 -0
  171. semantic_code_intelligence/tests/test_scanner.py +125 -0
  172. semantic_code_intelligence/tests/test_search.py +160 -0
  173. semantic_code_intelligence/tests/test_semantic_chunker.py +255 -0
  174. semantic_code_intelligence/tests/test_tools.py +182 -0
  175. semantic_code_intelligence/tests/test_vector_store.py +151 -0
  176. semantic_code_intelligence/tests/test_watcher.py +211 -0
  177. semantic_code_intelligence/tools/__init__.py +442 -0
  178. semantic_code_intelligence/tools/executor.py +232 -0
  179. semantic_code_intelligence/tools/protocol.py +200 -0
  180. semantic_code_intelligence/tui/__init__.py +454 -0
  181. semantic_code_intelligence/utils/__init__.py +0 -0
  182. semantic_code_intelligence/utils/logging.py +112 -0
  183. semantic_code_intelligence/version.py +3 -0
  184. semantic_code_intelligence/web/__init__.py +11 -0
  185. semantic_code_intelligence/web/api.py +289 -0
  186. semantic_code_intelligence/web/server.py +397 -0
  187. semantic_code_intelligence/web/ui.py +659 -0
  188. semantic_code_intelligence/web/visualize.py +226 -0
  189. semantic_code_intelligence/workspace/__init__.py +427 -0
@@ -0,0 +1,103 @@
1
+ """CLI command: refactor — AI-powered refactoring suggestions for a file."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json as json_mod
6
+ from pathlib import Path
7
+
8
+ import click
9
+
10
+ from semantic_code_intelligence.config.settings import AppConfig, load_config
11
+ from semantic_code_intelligence.utils.logging import (
12
+ console,
13
+ get_logger,
14
+ print_error,
15
+ print_info,
16
+ )
17
+
18
+ logger = get_logger("cli.refactor")
19
+
20
+
21
+ @click.command("refactor")
22
+ @click.argument(
23
+ "file",
24
+ type=click.Path(exists=True, dir_okay=False, resolve_path=True),
25
+ )
26
+ @click.option(
27
+ "--instruction",
28
+ "-i",
29
+ default="Improve code quality, readability, and performance.",
30
+ help="Refactoring instruction for the AI.",
31
+ )
32
+ @click.option(
33
+ "--json-output",
34
+ "--json",
35
+ "json_mode",
36
+ is_flag=True,
37
+ default=False,
38
+ help="Output in JSON format.",
39
+ )
40
+ @click.option(
41
+ "--path",
42
+ "-p",
43
+ default=".",
44
+ type=click.Path(exists=True, file_okay=False, resolve_path=True),
45
+ help="Project root path.",
46
+ )
47
+ @click.pass_context
48
+ def refactor_cmd(
49
+ ctx: click.Context,
50
+ file: str,
51
+ instruction: str,
52
+ json_mode: bool,
53
+ path: str,
54
+ ) -> None:
55
+ """Suggest refactored code for a source file.
56
+
57
+ Uses structural analysis + LLM to propose improved code with explanations.
58
+
59
+ Examples:
60
+
61
+ codexa refactor src/main.py
62
+
63
+ codexa refactor src/utils.py -i "Extract duplicated logic into helpers"
64
+ """
65
+ root = Path(path).resolve()
66
+ config_dir = AppConfig.config_dir(root)
67
+
68
+ if not config_dir.exists():
69
+ print_error(f"Project not initialized at {root}. Run 'codexa init' first.")
70
+ ctx.exit(1)
71
+ return
72
+
73
+ config = load_config(root)
74
+
75
+ from semantic_code_intelligence.cli.commands.ask_cmd import _get_provider
76
+ from semantic_code_intelligence.llm.reasoning import ReasoningEngine
77
+ from semantic_code_intelligence.llm.safety import SafetyValidator
78
+
79
+ provider = _get_provider(config)
80
+ engine = ReasoningEngine(provider, root)
81
+ result = engine.refactor(file, instruction)
82
+
83
+ # Safety check on refactored code
84
+ if result.refactored_code:
85
+ validator = SafetyValidator()
86
+ report = validator.validate(result.refactored_code)
87
+ if not report.safe:
88
+ from semantic_code_intelligence.utils.logging import _ICON_WARNING
89
+ console.print(f"[bold red]{_ICON_WARNING} Safety issues detected in refactored code:[/bold red]")
90
+ for issue in report.issues:
91
+ console.print(f" L{issue.line_number}: {issue.description}")
92
+ console.print()
93
+
94
+ if json_mode:
95
+ click.echo(json_mod.dumps(result.to_dict(), indent=2))
96
+ else:
97
+ console.print(f"\n[bold cyan]Refactor:[/bold cyan] {result.file_path}\n")
98
+ console.print(f"[bold green]Explanation:[/bold green]\n{result.explanation}\n")
99
+ if result.refactored_code:
100
+ console.print("[bold]Refactored code:[/bold]")
101
+ console.print(result.refactored_code)
102
+ else:
103
+ print_info("No refactored code produced (check LLM configuration).")
@@ -0,0 +1,88 @@
1
+ """CLI command: review — AI-powered code review of a file."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json as json_mod
6
+ from pathlib import Path
7
+
8
+ import click
9
+
10
+ from semantic_code_intelligence.config.settings import AppConfig, load_config
11
+ from semantic_code_intelligence.utils.logging import (
12
+ console,
13
+ get_logger,
14
+ print_error,
15
+ )
16
+
17
+ logger = get_logger("cli.review")
18
+
19
+
20
+ @click.command("review")
21
+ @click.argument(
22
+ "file",
23
+ type=click.Path(exists=True, dir_okay=False, resolve_path=True),
24
+ )
25
+ @click.option(
26
+ "--json-output",
27
+ "--json",
28
+ "json_mode",
29
+ is_flag=True,
30
+ default=False,
31
+ help="Output in JSON format.",
32
+ )
33
+ @click.option(
34
+ "--path",
35
+ "-p",
36
+ default=".",
37
+ type=click.Path(exists=True, file_okay=False, resolve_path=True),
38
+ help="Project root path.",
39
+ )
40
+ @click.pass_context
41
+ def review_cmd(
42
+ ctx: click.Context,
43
+ file: str,
44
+ json_mode: bool,
45
+ path: str,
46
+ ) -> None:
47
+ """Review a source file for issues, bugs, and improvements.
48
+
49
+ Uses structural analysis + LLM to perform an AI-assisted code review.
50
+
51
+ Examples:
52
+
53
+ codexa review src/main.py
54
+
55
+ codexa review src/utils.py --json
56
+ """
57
+ root = Path(path).resolve()
58
+ config_dir = AppConfig.config_dir(root)
59
+
60
+ if not config_dir.exists():
61
+ print_error(f"Project not initialized at {root}. Run 'codexa init' first.")
62
+ ctx.exit(1)
63
+ return
64
+
65
+ config = load_config(root)
66
+
67
+ from semantic_code_intelligence.cli.commands.ask_cmd import _get_provider
68
+ from semantic_code_intelligence.llm.reasoning import ReasoningEngine
69
+
70
+ provider = _get_provider(config)
71
+ engine = ReasoningEngine(provider, root)
72
+ result = engine.review(file)
73
+
74
+ if json_mode:
75
+ click.echo(json_mod.dumps(result.to_dict(), indent=2))
76
+ else:
77
+ console.print(f"\n[bold cyan]Code Review:[/bold cyan] {result.file_path}\n")
78
+ if result.issues:
79
+ for issue in result.issues:
80
+ sev = issue.get("severity", "info")
81
+ line = issue.get("line", "?")
82
+ msg = issue.get("message", str(issue))
83
+ color = {"error": "red", "warning": "yellow"}.get(sev, "blue")
84
+ console.print(f" [{color}]{sev.upper()}[/{color}] L{line}: {msg}")
85
+ if issue.get("suggestion"):
86
+ console.print(f" [dim]Suggestion: {issue['suggestion']}[/dim]")
87
+ console.print()
88
+ console.print(f"[bold green]Summary:[/bold green]\n{result.summary}")
@@ -0,0 +1,236 @@
1
+ """CLI command: search - Perform semantic, keyword, regex, or hybrid search."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from pathlib import Path
7
+
8
+ import click
9
+
10
+ from semantic_code_intelligence.config.settings import AppConfig, load_config
11
+ from semantic_code_intelligence.services.search_service import SearchMode, search_codebase
12
+ from semantic_code_intelligence.search.formatter import (
13
+ format_results_json,
14
+ format_results_jsonl,
15
+ format_results_rich,
16
+ )
17
+ from semantic_code_intelligence.utils.logging import (
18
+ get_logger,
19
+ print_error,
20
+ print_info,
21
+ print_warning,
22
+ console,
23
+ )
24
+
25
+ logger = get_logger("cli.search")
26
+
27
+
28
+ @click.command("search")
29
+ @click.argument("query", type=str)
30
+ @click.option(
31
+ "--top-k",
32
+ "-k",
33
+ default=None,
34
+ type=int,
35
+ help="Number of results to return (overrides config).",
36
+ )
37
+ @click.option(
38
+ "--json-output",
39
+ "--json",
40
+ "json_mode",
41
+ is_flag=True,
42
+ default=False,
43
+ help="Output results in JSON format for AI integration.",
44
+ )
45
+ @click.option(
46
+ "--jsonl",
47
+ "jsonl_mode",
48
+ is_flag=True,
49
+ default=False,
50
+ help="Output one JSON object per line (JSONL), for piping into jq/fzf.",
51
+ )
52
+ @click.option(
53
+ "--path",
54
+ "-p",
55
+ default=".",
56
+ type=click.Path(exists=True, file_okay=False, resolve_path=True),
57
+ help="Project root path.",
58
+ )
59
+ @click.option(
60
+ "--mode",
61
+ "-m",
62
+ type=click.Choice(["semantic", "keyword", "regex", "hybrid"], case_sensitive=False),
63
+ default="semantic",
64
+ help="Search mode: semantic (default), keyword (BM25), regex, or hybrid (RRF).",
65
+ )
66
+ @click.option(
67
+ "--full-section",
68
+ "--full",
69
+ is_flag=True,
70
+ default=False,
71
+ help="Expand results to show the full enclosing function/class.",
72
+ )
73
+ @click.option(
74
+ "--no-auto-index",
75
+ is_flag=True,
76
+ default=False,
77
+ help="Disable automatic indexing on first search.",
78
+ )
79
+ @click.option(
80
+ "--case-sensitive",
81
+ "-s",
82
+ is_flag=True,
83
+ default=False,
84
+ help="Case-sensitive matching (regex mode only).",
85
+ )
86
+ @click.option(
87
+ "--context-lines",
88
+ "-C",
89
+ default=0,
90
+ type=int,
91
+ help="Show N context lines before/after each match (grep-style).",
92
+ )
93
+ @click.option(
94
+ "--files-only",
95
+ "-l",
96
+ is_flag=True,
97
+ default=False,
98
+ help="Print only file paths with matches (like grep -l).",
99
+ )
100
+ @click.option(
101
+ "--files-without-match",
102
+ "-L",
103
+ is_flag=True,
104
+ default=False,
105
+ help="Print file paths without any matches (like grep -L).",
106
+ )
107
+ @click.option(
108
+ "--line-numbers",
109
+ "-n",
110
+ is_flag=True,
111
+ default=False,
112
+ help="Prefix each output line with its line number (like grep -n).",
113
+ )
114
+ @click.pass_context
115
+ def search_cmd(
116
+ ctx: click.Context,
117
+ query: str,
118
+ top_k: int | None,
119
+ json_mode: bool,
120
+ jsonl_mode: bool,
121
+ path: str,
122
+ mode: str,
123
+ full_section: bool,
124
+ no_auto_index: bool,
125
+ case_sensitive: bool,
126
+ context_lines: int,
127
+ files_only: bool,
128
+ files_without_match: bool,
129
+ line_numbers: bool,
130
+ ) -> None:
131
+ """Search the indexed codebase using a natural language query.
132
+
133
+ Supports four search modes:
134
+
135
+ \b
136
+ semantic — vector similarity (default)
137
+ keyword — BM25 ranked keyword search
138
+ regex — grep-compatible regex pattern matching
139
+ hybrid — fused semantic + BM25 via Reciprocal Rank Fusion
140
+
141
+ Grep-compatible flags:
142
+
143
+ \b
144
+ -l show only file paths with matches
145
+ -L show only file paths without matches
146
+ -n prefix lines with line numbers
147
+ -C N show N context lines before/after each match
148
+
149
+ Examples:
150
+
151
+ \b
152
+ codexa search "jwt verification"
153
+ codexa search "database connection" --mode hybrid
154
+ codexa search "def\\s+authenticate" --mode regex -n
155
+ codexa search "error handling" --mode keyword --full-section
156
+ codexa search "error handling" -k 5 --json
157
+ codexa search "TODO" --mode regex -l
158
+ codexa search "pattern" --jsonl | jq .file_path
159
+ """
160
+ root = Path(path).resolve()
161
+ config_dir = AppConfig.config_dir(root)
162
+
163
+ if not config_dir.exists():
164
+ print_error(
165
+ f"Project not initialized at {root}. Run 'codexa init' first."
166
+ )
167
+ ctx.exit(1)
168
+ return
169
+
170
+ config = load_config(root)
171
+ result_count = top_k or config.search.top_k
172
+
173
+ try:
174
+ results = search_codebase(
175
+ query=query,
176
+ project_root=root,
177
+ top_k=result_count,
178
+ mode=mode, # type: ignore[arg-type]
179
+ full_section=full_section,
180
+ auto_index=not no_auto_index,
181
+ case_insensitive=not case_sensitive,
182
+ )
183
+ except FileNotFoundError:
184
+ if json_mode:
185
+ click.echo(format_results_json(query, [], result_count))
186
+ elif jsonl_mode:
187
+ pass # no output for JSONL with no results
188
+ else:
189
+ print_warning(
190
+ "Search index is empty. Run 'codexa index' to build the index."
191
+ )
192
+ return
193
+
194
+ # --- Grep-style output modes ---
195
+
196
+ if files_without_match:
197
+ # Show all indexed files NOT in the results
198
+ matched_files = {r.file_path for r in results}
199
+ from semantic_code_intelligence.storage.vector_store import VectorStore
200
+ index_dir = AppConfig.index_dir(root)
201
+ try:
202
+ store = VectorStore.load(index_dir)
203
+ all_files = sorted({m.file_path for m in store.metadata})
204
+ except FileNotFoundError:
205
+ all_files = []
206
+ for fp in all_files:
207
+ if fp not in matched_files:
208
+ click.echo(fp)
209
+ return
210
+
211
+ if files_only:
212
+ seen: set[str] = set()
213
+ for r in results:
214
+ if r.file_path not in seen:
215
+ seen.add(r.file_path)
216
+ click.echo(r.file_path)
217
+ return
218
+
219
+ # --- Machine-readable output ---
220
+
221
+ if jsonl_mode:
222
+ click.echo(format_results_jsonl(results))
223
+ return
224
+
225
+ if json_mode:
226
+ click.echo(format_results_json(query, results, result_count))
227
+ return
228
+
229
+ # --- Rich / grep-style human output ---
230
+
231
+ format_results_rich(
232
+ query,
233
+ results,
234
+ line_numbers=line_numbers,
235
+ context_lines=context_lines,
236
+ )
@@ -0,0 +1,117 @@
1
+ """CLI command: serve — start the CodexA bridge server.
2
+
3
+ Supports MCP-over-SSE via ``--mcp`` flag for AI agent integration.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from pathlib import Path
9
+
10
+ import click
11
+
12
+ from semantic_code_intelligence.utils.logging import (
13
+ get_logger,
14
+ print_info,
15
+ )
16
+
17
+ logger = get_logger("cli.serve")
18
+
19
+
20
+ @click.command("serve")
21
+ @click.option(
22
+ "--host",
23
+ "-h",
24
+ default="127.0.0.1",
25
+ type=str,
26
+ help="Host to bind the bridge server to.",
27
+ )
28
+ @click.option(
29
+ "--port",
30
+ "-p",
31
+ default=24842,
32
+ type=int,
33
+ help="Port to bind the bridge server to.",
34
+ )
35
+ @click.option(
36
+ "--path",
37
+ default=".",
38
+ type=click.Path(exists=True, file_okay=False, resolve_path=True),
39
+ help="Project root path.",
40
+ )
41
+ @click.option(
42
+ "--mcp",
43
+ "mcp_mode",
44
+ is_flag=True,
45
+ default=False,
46
+ help="Expose MCP tools over HTTP+SSE (for AI agent integration).",
47
+ )
48
+ @click.pass_context
49
+ def serve_cmd(
50
+ ctx: click.Context,
51
+ host: str,
52
+ port: int,
53
+ path: str,
54
+ mcp_mode: bool,
55
+ ) -> None:
56
+ """Start the CodexA bridge server for external AI integration.
57
+
58
+ Use --mcp to expose MCP-compliant tools over HTTP with SSE streaming.
59
+
60
+ \b
61
+ Examples:
62
+ codexa serve
63
+ codexa serve --port 8080
64
+ codexa serve --mcp
65
+ """
66
+ project_root = Path(path)
67
+
68
+ if mcp_mode:
69
+ _run_mcp_http(project_root, host, port)
70
+ return
71
+
72
+ from semantic_code_intelligence.bridge.server import BridgeServer
73
+
74
+ server = BridgeServer(project_root, host=host, port=port)
75
+
76
+ print_info(f"Starting CodexA bridge server on {server.url}")
77
+ print_info("Press Ctrl+C to stop.")
78
+
79
+ server.start()
80
+
81
+
82
+ def _run_mcp_http(project_root: Path, host: str, port: int) -> None:
83
+ """Run MCP tools over HTTP+SSE using the streamable-http transport."""
84
+ try:
85
+ from mcp.server.sse import SseServerTransport
86
+ from starlette.applications import Starlette
87
+ from starlette.routing import Route, Mount
88
+ import uvicorn
89
+ except ImportError:
90
+ # Fallback: just run MCP stdio server
91
+ print_info("SSE/Starlette not installed — falling back to stdio MCP.")
92
+ from semantic_code_intelligence.mcp import run_mcp_server
93
+ run_mcp_server(project_root)
94
+ return
95
+
96
+ from semantic_code_intelligence.mcp import _create_server
97
+
98
+ server = _create_server(project_root)
99
+ sse = SseServerTransport("/messages/")
100
+
101
+ async def handle_sse(request):
102
+ async with sse.connect_sse(request.scope, request.receive, request._send) as streams:
103
+ await server.run(
104
+ streams[0], streams[1],
105
+ server.create_initialization_options(),
106
+ )
107
+
108
+ app = Starlette(
109
+ routes=[
110
+ Route("/sse", endpoint=handle_sse),
111
+ Mount("/messages/", app=sse.handle_post_message),
112
+ ],
113
+ )
114
+
115
+ print_info(f"MCP-over-SSE server on http://{host}:{port}/sse")
116
+ print_info("Press Ctrl+C to stop.")
117
+ uvicorn.run(app, host=host, port=port, log_level="info")
@@ -0,0 +1,100 @@
1
+ """CLI command: suggest — AI-powered intelligent suggestions for a symbol/file."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json as json_mod
6
+ from pathlib import Path
7
+
8
+ import click
9
+
10
+ from semantic_code_intelligence.config.settings import AppConfig, load_config
11
+ from semantic_code_intelligence.utils.logging import (
12
+ console,
13
+ get_logger,
14
+ print_error,
15
+ )
16
+
17
+ logger = get_logger("cli.suggest")
18
+
19
+
20
+ @click.command("suggest")
21
+ @click.argument("target", type=str)
22
+ @click.option(
23
+ "--top-k",
24
+ "-k",
25
+ default=5,
26
+ type=int,
27
+ help="Number of context snippets to consider.",
28
+ )
29
+ @click.option(
30
+ "--json-output",
31
+ "--json",
32
+ "json_mode",
33
+ is_flag=True,
34
+ default=False,
35
+ help="Output in JSON format.",
36
+ )
37
+ @click.option(
38
+ "--path",
39
+ "-p",
40
+ default=".",
41
+ type=click.Path(exists=True, file_okay=False, resolve_path=True),
42
+ help="Project root path.",
43
+ )
44
+ @click.pass_context
45
+ def suggest_cmd(
46
+ ctx: click.Context,
47
+ target: str,
48
+ top_k: int,
49
+ json_mode: bool,
50
+ path: str,
51
+ ) -> None:
52
+ """Get intelligent suggestions for a symbol, file, or topic.
53
+
54
+ Combines call-graph, dependency, and semantic data with LLM reasoning
55
+ to produce actionable suggestions with "why" reasoning.
56
+
57
+ Examples:
58
+
59
+ codexa suggest search_codebase
60
+
61
+ codexa suggest "error handling patterns" --json
62
+ """
63
+ root = Path(path).resolve()
64
+ config_dir = AppConfig.config_dir(root)
65
+
66
+ if not config_dir.exists():
67
+ print_error(f"Project not initialized at {root}. Run 'codexa init' first.")
68
+ ctx.exit(1)
69
+ return
70
+
71
+ config = load_config(root)
72
+
73
+ from semantic_code_intelligence.cli.commands.ask_cmd import _get_provider
74
+ from semantic_code_intelligence.llm.reasoning import ReasoningEngine
75
+
76
+ provider = _get_provider(config)
77
+ engine = ReasoningEngine(provider, root)
78
+ result = engine.suggest(target, top_k=top_k)
79
+
80
+ if json_mode:
81
+ click.echo(json_mod.dumps(result.to_dict(), indent=2))
82
+ else:
83
+ console.print(f"\n[bold cyan]Suggestions for:[/bold cyan] {result.target}\n")
84
+ if result.suggestions:
85
+ for i, sug in enumerate(result.suggestions, 1):
86
+ title = sug.get("title", f"Suggestion {i}")
87
+ desc = sug.get("description", "")
88
+ reason = sug.get("reason", "")
89
+ priority = sug.get("priority", "medium")
90
+ color = {"high": "red", "medium": "yellow", "low": "green"}.get(
91
+ priority, "blue"
92
+ )
93
+ console.print(f" [{color}]{priority.upper()}[/{color}] {title}")
94
+ if desc:
95
+ console.print(f" {desc}")
96
+ if reason:
97
+ console.print(f" [dim]Why: {reason}[/dim]")
98
+ console.print()
99
+ else:
100
+ console.print("[dim]No suggestions generated.[/dim]")