jarvis-ai-assistant 0.3.30__py3-none-any.whl → 0.7.6__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 (181) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +458 -152
  3. jarvis/jarvis_agent/agent_manager.py +17 -13
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +329 -0
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +628 -55
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +34 -10
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +105 -9
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +20 -22
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  31. jarvis/jarvis_agent/task_analyzer.py +31 -6
  32. jarvis/jarvis_agent/task_manager.py +11 -27
  33. jarvis/jarvis_agent/tool_executor.py +2 -3
  34. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  35. jarvis/jarvis_agent/utils.py +5 -1
  36. jarvis/jarvis_agent/web_bridge.py +189 -0
  37. jarvis/jarvis_agent/web_output_sink.py +53 -0
  38. jarvis/jarvis_agent/web_server.py +786 -0
  39. jarvis/jarvis_c2rust/__init__.py +26 -0
  40. jarvis/jarvis_c2rust/cli.py +575 -0
  41. jarvis/jarvis_c2rust/collector.py +250 -0
  42. jarvis/jarvis_c2rust/constants.py +26 -0
  43. jarvis/jarvis_c2rust/library_replacer.py +1254 -0
  44. jarvis/jarvis_c2rust/llm_module_agent.py +1272 -0
  45. jarvis/jarvis_c2rust/loaders.py +207 -0
  46. jarvis/jarvis_c2rust/models.py +28 -0
  47. jarvis/jarvis_c2rust/optimizer.py +2157 -0
  48. jarvis/jarvis_c2rust/scanner.py +1681 -0
  49. jarvis/jarvis_c2rust/transpiler.py +2983 -0
  50. jarvis/jarvis_c2rust/utils.py +385 -0
  51. jarvis/jarvis_code_agent/build_validation_config.py +132 -0
  52. jarvis/jarvis_code_agent/code_agent.py +1371 -220
  53. jarvis/jarvis_code_agent/code_analyzer/__init__.py +65 -0
  54. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +106 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +74 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +72 -0
  60. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +70 -0
  61. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +53 -0
  62. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +47 -0
  63. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +61 -0
  64. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +110 -0
  65. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +154 -0
  66. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +110 -0
  67. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +153 -0
  68. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  69. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +648 -0
  70. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  71. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  72. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  73. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  74. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  75. jarvis/jarvis_code_agent/code_analyzer/language_support.py +110 -0
  76. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +49 -0
  77. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +299 -0
  78. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +215 -0
  79. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  80. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  81. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +269 -0
  82. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +281 -0
  83. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  84. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +605 -0
  85. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  86. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +252 -0
  87. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +58 -0
  88. jarvis/jarvis_code_agent/lint.py +501 -8
  89. jarvis/jarvis_code_agent/utils.py +141 -0
  90. jarvis/jarvis_code_analysis/code_review.py +493 -584
  91. jarvis/jarvis_data/config_schema.json +128 -12
  92. jarvis/jarvis_git_squash/main.py +4 -5
  93. jarvis/jarvis_git_utils/git_commiter.py +82 -75
  94. jarvis/jarvis_mcp/sse_mcp_client.py +22 -29
  95. jarvis/jarvis_mcp/stdio_mcp_client.py +12 -13
  96. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  97. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  98. jarvis/jarvis_methodology/main.py +32 -48
  99. jarvis/jarvis_multi_agent/__init__.py +287 -55
  100. jarvis/jarvis_multi_agent/main.py +36 -4
  101. jarvis/jarvis_platform/base.py +524 -202
  102. jarvis/jarvis_platform/human.py +7 -8
  103. jarvis/jarvis_platform/kimi.py +30 -36
  104. jarvis/jarvis_platform/openai.py +88 -25
  105. jarvis/jarvis_platform/registry.py +26 -10
  106. jarvis/jarvis_platform/tongyi.py +24 -25
  107. jarvis/jarvis_platform/yuanbao.py +32 -43
  108. jarvis/jarvis_platform_manager/main.py +66 -77
  109. jarvis/jarvis_platform_manager/service.py +8 -13
  110. jarvis/jarvis_rag/cli.py +53 -55
  111. jarvis/jarvis_rag/embedding_manager.py +13 -18
  112. jarvis/jarvis_rag/llm_interface.py +8 -9
  113. jarvis/jarvis_rag/query_rewriter.py +10 -21
  114. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  115. jarvis/jarvis_rag/reranker.py +4 -5
  116. jarvis/jarvis_rag/retriever.py +28 -30
  117. jarvis/jarvis_sec/__init__.py +305 -0
  118. jarvis/jarvis_sec/agents.py +143 -0
  119. jarvis/jarvis_sec/analysis.py +276 -0
  120. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  121. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  122. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  123. jarvis/jarvis_sec/cli.py +139 -0
  124. jarvis/jarvis_sec/clustering.py +1439 -0
  125. jarvis/jarvis_sec/file_manager.py +427 -0
  126. jarvis/jarvis_sec/parsers.py +73 -0
  127. jarvis/jarvis_sec/prompts.py +268 -0
  128. jarvis/jarvis_sec/report.py +336 -0
  129. jarvis/jarvis_sec/review.py +453 -0
  130. jarvis/jarvis_sec/status.py +264 -0
  131. jarvis/jarvis_sec/types.py +20 -0
  132. jarvis/jarvis_sec/utils.py +499 -0
  133. jarvis/jarvis_sec/verification.py +848 -0
  134. jarvis/jarvis_sec/workflow.py +226 -0
  135. jarvis/jarvis_smart_shell/main.py +38 -87
  136. jarvis/jarvis_stats/cli.py +2 -2
  137. jarvis/jarvis_stats/stats.py +8 -8
  138. jarvis/jarvis_stats/storage.py +15 -21
  139. jarvis/jarvis_stats/visualizer.py +1 -1
  140. jarvis/jarvis_tools/clear_memory.py +3 -20
  141. jarvis/jarvis_tools/cli/main.py +21 -23
  142. jarvis/jarvis_tools/edit_file.py +1019 -132
  143. jarvis/jarvis_tools/execute_script.py +83 -25
  144. jarvis/jarvis_tools/file_analyzer.py +6 -9
  145. jarvis/jarvis_tools/generate_new_tool.py +14 -21
  146. jarvis/jarvis_tools/lsp_client.py +1552 -0
  147. jarvis/jarvis_tools/methodology.py +2 -3
  148. jarvis/jarvis_tools/read_code.py +1736 -35
  149. jarvis/jarvis_tools/read_symbols.py +140 -0
  150. jarvis/jarvis_tools/read_webpage.py +12 -13
  151. jarvis/jarvis_tools/registry.py +427 -200
  152. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  153. jarvis/jarvis_tools/rewrite_file.py +72 -158
  154. jarvis/jarvis_tools/save_memory.py +3 -15
  155. jarvis/jarvis_tools/search_web.py +18 -18
  156. jarvis/jarvis_tools/sub_agent.py +36 -43
  157. jarvis/jarvis_tools/sub_code_agent.py +25 -26
  158. jarvis/jarvis_tools/virtual_tty.py +55 -33
  159. jarvis/jarvis_utils/clipboard.py +7 -10
  160. jarvis/jarvis_utils/config.py +232 -45
  161. jarvis/jarvis_utils/embedding.py +8 -5
  162. jarvis/jarvis_utils/fzf.py +8 -8
  163. jarvis/jarvis_utils/git_utils.py +225 -36
  164. jarvis/jarvis_utils/globals.py +3 -3
  165. jarvis/jarvis_utils/http.py +1 -1
  166. jarvis/jarvis_utils/input.py +99 -48
  167. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  168. jarvis/jarvis_utils/methodology.py +52 -48
  169. jarvis/jarvis_utils/utils.py +819 -491
  170. jarvis_ai_assistant-0.7.6.dist-info/METADATA +600 -0
  171. jarvis_ai_assistant-0.7.6.dist-info/RECORD +218 -0
  172. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/entry_points.txt +4 -0
  173. jarvis/jarvis_agent/config.py +0 -92
  174. jarvis/jarvis_agent/edit_file_handler.py +0 -296
  175. jarvis/jarvis_platform/ai8.py +0 -332
  176. jarvis/jarvis_tools/ask_user.py +0 -54
  177. jarvis_ai_assistant-0.3.30.dist-info/METADATA +0 -381
  178. jarvis_ai_assistant-0.3.30.dist-info/RECORD +0 -137
  179. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/WHEEL +0 -0
  180. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/licenses/LICENSE +0 -0
  181. {jarvis_ai_assistant-0.3.30.dist-info → jarvis_ai_assistant-0.7.6.dist-info}/top_level.txt +0 -0
@@ -9,455 +9,408 @@ import typer
9
9
 
10
10
  from jarvis.jarvis_agent import Agent
11
11
  from jarvis.jarvis_code_analysis.checklists.loader import get_language_checklist
12
- from jarvis.jarvis_platform.registry import PlatformRegistry
12
+
13
13
  from jarvis.jarvis_tools.read_code import ReadCodeTool
14
- from jarvis.jarvis_utils.globals import get_agent, current_agent_name
15
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
+
15
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput # 保留用于语法高亮
16
16
  from jarvis.jarvis_utils.tag import ct, ot
17
17
  from jarvis.jarvis_utils.utils import init_env, is_context_overflow
18
18
 
19
19
  app = typer.Typer(help="自动代码审查工具")
20
20
 
21
21
 
22
- class CodeReviewTool:
23
- name = "code_review"
24
- description = "自动代码审查工具,用于分析代码变更"
25
- labels = ["code", "analysis", "review"]
26
- parameters = {
27
- "type": "object",
28
- "properties": {
29
- "review_type": {
30
- "type": "string",
31
- "description": "审查类型:'commit' 审查特定提交,'current' 审查当前变更,'range' 审查提交范围,'file' 审查特定文件",
32
- "enum": ["commit", "current", "range", "file"],
33
- "default": "current",
34
- },
35
- "commit_sha": {
36
- "type": "string",
37
- "description": "要分析的提交SHA(review_type='commit'时必填)",
38
- },
39
- "start_commit": {
40
- "type": "string",
41
- "description": "起始提交SHA(review_type='range'时必填)",
42
- },
43
- "end_commit": {
44
- "type": "string",
45
- "description": "结束提交SHA(review_type='range'时必填)",
46
- },
47
- "file_path": {
48
- "type": "string",
49
- "description": "要审查的文件路径(review_type='file'时必填)",
50
- },
51
- "root_dir": {
52
- "type": "string",
53
- "description": "代码库根目录路径(可选)",
54
- "default": ".",
55
- },
56
- },
57
- "required": [],
22
+ def _detect_languages_from_files(file_paths: List[str]) -> List[str]:
23
+ """
24
+ Detect programming languages from a list of file paths using file extensions.
25
+ Returns a list of detected languages ('c_cpp', 'go', 'python', 'rust', 'java', 'javascript', 'typescript', etc.).
26
+ """
27
+ if not file_paths:
28
+ return []
29
+
30
+ # Extension-based language detection
31
+ languages = set()
32
+ for file_path in file_paths:
33
+ file_path = file_path.lower()
34
+ _, ext = os.path.splitext(file_path)
35
+
36
+ # Get base name for special files without extensions
37
+ base_name = os.path.basename(file_path)
38
+
39
+ # C/C++
40
+ if ext in [
41
+ ".c",
42
+ ".cpp",
43
+ ".cc",
44
+ ".cxx",
45
+ ".h",
46
+ ".hpp",
47
+ ".hxx",
48
+ ".inl",
49
+ ".ipp",
50
+ ]:
51
+ languages.add("c_cpp")
52
+
53
+ # Go
54
+ elif ext in [".go"]:
55
+ languages.add("go")
56
+
57
+ # Python
58
+ elif ext in [".py", ".pyw", ".pyi", ".pyx", ".pxd"] or base_name in [
59
+ "requirements.txt",
60
+ "setup.py",
61
+ "pyproject.toml",
62
+ ]:
63
+ languages.add("python")
64
+
65
+ # Rust
66
+ elif ext in [".rs", ".rlib"] or base_name in ["Cargo.toml", "Cargo.lock"]:
67
+ languages.add("rust")
68
+
69
+ # Java
70
+ elif ext in [".java", ".class", ".jar"] or base_name in [
71
+ "pom.xml",
72
+ "build.gradle",
73
+ ]:
74
+ languages.add("java")
75
+
76
+ # JavaScript
77
+ elif ext in [".js", ".mjs", ".cjs", ".jsx"]:
78
+ languages.add("javascript")
79
+
80
+ # TypeScript
81
+ elif ext in [".ts", ".tsx", ".cts", ".mts"]:
82
+ languages.add("typescript")
83
+
84
+ # PHP
85
+ elif ext in [".php", ".phtml", ".php5", ".php7", ".phps"]:
86
+ languages.add("php")
87
+
88
+ # Ruby
89
+ elif ext in [".rb", ".rake", ".gemspec"] or base_name in [
90
+ "Gemfile",
91
+ "Rakefile",
92
+ ]:
93
+ languages.add("ruby")
94
+
95
+ # Swift
96
+ elif ext in [".swift"]:
97
+ languages.add("swift")
98
+
99
+ # Kotlin
100
+ elif ext in [".kt", ".kts"]:
101
+ languages.add("kotlin")
102
+
103
+ # C#
104
+ elif ext in [".cs", ".csx"]:
105
+ languages.add("csharp")
106
+
107
+ # SQL
108
+ elif ext in [".sql"]:
109
+ languages.add("sql")
110
+
111
+ # Shell/Bash
112
+ elif (
113
+ ext in [".sh", ".bash"]
114
+ or base_name.startswith(".bash")
115
+ or base_name.startswith(".zsh")
116
+ ):
117
+ languages.add("shell")
118
+
119
+ # HTML/CSS
120
+ elif ext in [".html", ".htm", ".xhtml"]:
121
+ languages.add("html")
122
+ elif ext in [".css", ".scss", ".sass", ".less"]:
123
+ languages.add("css")
124
+
125
+ # XML/JSON/YAML (config files)
126
+ elif ext in [
127
+ ".xml",
128
+ ".xsd",
129
+ ".dtd",
130
+ ".tld",
131
+ ".jsp",
132
+ ".jspx",
133
+ ".tag",
134
+ ".tagx",
135
+ ]:
136
+ languages.add("xml")
137
+ elif ext in [".json", ".jsonl", ".json5"]:
138
+ languages.add("json")
139
+ elif ext in [".yaml", ".yml"]:
140
+ languages.add("yaml")
141
+
142
+ # Markdown/Documentation
143
+ elif ext in [".md", ".markdown", ".rst", ".adoc"]:
144
+ languages.add("markdown")
145
+
146
+ # Docker
147
+ elif ext in [".dockerfile"] or base_name in [
148
+ "Dockerfile",
149
+ "docker-compose.yml",
150
+ "docker-compose.yaml",
151
+ ]:
152
+ languages.add("docker")
153
+
154
+ # Terraform
155
+ elif ext in [".tf", ".tfvars"]:
156
+ languages.add("terraform")
157
+
158
+ # Makefile
159
+ elif ext in [".mk"] or base_name == "Makefile":
160
+ languages.add("makefile")
161
+
162
+ # Map to our primary language groups for checklist purposes
163
+ primary_languages = set()
164
+ language_mapping = {
165
+ "c_cpp": "c_cpp",
166
+ "go": "go",
167
+ "python": "python",
168
+ "rust": "rust",
169
+ "java": "java",
170
+ "javascript": "javascript",
171
+ "typescript": "typescript",
172
+ "php": "php",
173
+ "ruby": "ruby",
174
+ "swift": "swift",
175
+ "kotlin": "kotlin",
176
+ "csharp": "csharp",
177
+ "sql": "sql",
178
+ "shell": "shell",
179
+ "html": "html",
180
+ "css": "css",
181
+ "xml": "xml",
182
+ "json": "json",
183
+ "yaml": "yaml",
184
+ "markdown": "docs",
185
+ "docker": "docker",
186
+ "terraform": "terraform",
187
+ "makefile": "devops",
58
188
  }
59
189
 
60
- def _detect_languages_from_files(self, file_paths: List[str]) -> List[str]:
61
- """
62
- Detect programming languages from a list of file paths using file extensions.
63
- Returns a list of detected languages ('c_cpp', 'go', 'python', 'rust', 'java', 'javascript', 'typescript', etc.).
64
- """
65
- if not file_paths:
66
- return []
67
-
68
- # Extension-based language detection
69
- languages = set()
70
- for file_path in file_paths:
71
- file_path = file_path.lower()
72
- _, ext = os.path.splitext(file_path)
73
-
74
- # Get base name for special files without extensions
75
- base_name = os.path.basename(file_path)
76
-
77
- # C/C++
78
- if ext in [
79
- ".c",
80
- ".cpp",
81
- ".cc",
82
- ".cxx",
83
- ".h",
84
- ".hpp",
85
- ".hxx",
86
- ".inl",
87
- ".ipp",
190
+ # Map detected languages to primary language groups
191
+ for lang in languages:
192
+ primary_lang = language_mapping.get(lang)
193
+ if primary_lang:
194
+ # Only keep languages we have checklists for
195
+ if primary_lang in [
196
+ "c_cpp",
197
+ "go",
198
+ "python",
199
+ "rust",
200
+ "java",
201
+ "javascript",
202
+ "typescript",
203
+ "csharp",
204
+ "swift",
205
+ "php",
206
+ "shell",
207
+ "sql",
208
+ "ruby",
209
+ "kotlin",
210
+ "html",
211
+ "css",
212
+ "xml",
213
+ "json",
214
+ "yaml",
215
+ "docker",
216
+ "terraform",
217
+ "docs",
218
+ "markdown",
219
+ "devops",
220
+ "makefile",
88
221
  ]:
89
- languages.add("c_cpp")
90
-
91
- # Go
92
- elif ext in [".go"]:
93
- languages.add("go")
222
+ primary_languages.add(primary_lang)
94
223
 
95
- # Python
96
- elif ext in [".py", ".pyw", ".pyi", ".pyx", ".pxd"] or base_name in [
97
- "requirements.txt",
98
- "setup.py",
99
- "pyproject.toml",
100
- ]:
101
- languages.add("python")
224
+ return list(primary_languages)
102
225
 
103
- # Rust
104
- elif ext in [".rs", ".rlib"] or base_name in ["Cargo.toml", "Cargo.lock"]:
105
- languages.add("rust")
106
226
 
107
- # Java
108
- elif ext in [".java", ".class", ".jar"] or base_name in [
109
- "pom.xml",
110
- "build.gradle",
111
- ]:
112
- languages.add("java")
227
+ def _get_language_checklist(language: str) -> str:
228
+ """Get the checklist for a specific language."""
229
+ checklist = get_language_checklist(language)
230
+ return checklist if checklist else ""
113
231
 
114
- # JavaScript
115
- elif ext in [".js", ".mjs", ".cjs", ".jsx"]:
116
- languages.add("javascript")
117
232
 
118
- # TypeScript
119
- elif ext in [".ts", ".tsx", ".cts", ".mts"]:
120
- languages.add("typescript")
233
+ def execute_code_review(
234
+ args: Dict[str, Any], agent: Optional["Agent"] = None
235
+ ) -> Dict[str, Any]:
236
+ """
237
+ 纯CLI Agent执行入口:根据审查类型获取差异、构建审查上下文并通过Agent生成报告。
238
+ 不注册为Tool,不通过ToolRegistry。
239
+ """
240
+ try:
241
+ review_type = args.get("review_type", "current").strip()
242
+ root_dir = args.get("root_dir", ".")
121
243
 
122
- # PHP
123
- elif ext in [".php", ".phtml", ".php5", ".php7", ".phps"]:
124
- languages.add("php")
244
+ # Store current directory
245
+ original_dir = os.getcwd()
125
246
 
126
- # Ruby
127
- elif ext in [".rb", ".rake", ".gemspec"] or base_name in [
128
- "Gemfile",
129
- "Rakefile",
130
- ]:
131
- languages.add("ruby")
132
-
133
- # Swift
134
- elif ext in [".swift"]:
135
- languages.add("swift")
136
-
137
- # Kotlin
138
- elif ext in [".kt", ".kts"]:
139
- languages.add("kotlin")
140
-
141
- # C#
142
- elif ext in [".cs", ".csx"]:
143
- languages.add("csharp")
144
-
145
- # SQL
146
- elif ext in [".sql"]:
147
- languages.add("sql")
148
-
149
- # Shell/Bash
150
- elif (
151
- ext in [".sh", ".bash"]
152
- or base_name.startswith(".bash")
153
- or base_name.startswith(".zsh")
154
- ):
155
- languages.add("shell")
156
-
157
- # HTML/CSS
158
- elif ext in [".html", ".htm", ".xhtml"]:
159
- languages.add("html")
160
- elif ext in [".css", ".scss", ".sass", ".less"]:
161
- languages.add("css")
162
-
163
- # XML/JSON/YAML (config files)
164
- elif ext in [
165
- ".xml",
166
- ".xsd",
167
- ".dtd",
168
- ".tld",
169
- ".jsp",
170
- ".jspx",
171
- ".tag",
172
- ".tagx",
173
- ]:
174
- languages.add("xml")
175
- elif ext in [".json", ".jsonl", ".json5"]:
176
- languages.add("json")
177
- elif ext in [".yaml", ".yml"]:
178
- languages.add("yaml")
179
-
180
- # Markdown/Documentation
181
- elif ext in [".md", ".markdown", ".rst", ".adoc"]:
182
- languages.add("markdown")
183
-
184
- # Docker
185
- elif ext in [".dockerfile"] or base_name in [
186
- "Dockerfile",
187
- "docker-compose.yml",
188
- "docker-compose.yaml",
189
- ]:
190
- languages.add("docker")
191
-
192
- # Terraform
193
- elif ext in [".tf", ".tfvars"]:
194
- languages.add("terraform")
195
-
196
- # Makefile
197
- elif ext in [".mk"] or base_name == "Makefile":
198
- languages.add("makefile")
199
-
200
- # Map to our primary language groups for checklist purposes
201
- primary_languages = set()
202
- language_mapping = {
203
- "c_cpp": "c_cpp",
204
- "go": "go",
205
- "python": "python",
206
- "rust": "rust",
207
- "java": "java",
208
- "javascript": "javascript",
209
- "typescript": "typescript",
210
- "php": "php",
211
- "ruby": "ruby",
212
- "swift": "swift",
213
- "kotlin": "kotlin",
214
- "csharp": "csharp",
215
- "sql": "sql",
216
- "shell": "shell",
217
- "html": "html",
218
- "css": "css",
219
- "xml": "xml",
220
- "json": "json",
221
- "yaml": "yaml",
222
- "markdown": "docs",
223
- "docker": "docker",
224
- "terraform": "terraform",
225
- "makefile": "devops",
226
- }
227
-
228
- # Map detected languages to primary language groups
229
- for lang in languages:
230
- primary_lang = language_mapping.get(lang)
231
- if primary_lang:
232
- # Only keep languages we have checklists for
233
- if primary_lang in [
234
- "c_cpp",
235
- "go",
236
- "python",
237
- "rust",
238
- "java",
239
- "javascript",
240
- "typescript",
241
- "csharp",
242
- "swift",
243
- "php",
244
- "shell",
245
- "sql",
246
- "ruby",
247
- "kotlin",
248
- "html",
249
- "css",
250
- "xml",
251
- "json",
252
- "yaml",
253
- "docker",
254
- "terraform",
255
- "docs",
256
- "markdown",
257
- "devops",
258
- "makefile",
259
- ]:
260
- primary_languages.add(primary_lang)
261
-
262
- return list(primary_languages)
263
-
264
- def _get_language_checklist(self, language: str) -> str:
265
- """Get the checklist for a specific language."""
266
- checklist = get_language_checklist(language)
267
- return checklist if checklist else ""
268
-
269
- def execute(
270
- self, args: Dict[str, Any], agent: Optional["Agent"] = None
271
- ) -> Dict[str, Any]:
272
247
  try:
273
- review_type = args.get("review_type", "current").strip()
274
- root_dir = args.get("root_dir", ".")
275
-
276
- # Store current directory
277
- original_dir = os.getcwd()
278
-
279
- try:
280
- # Change to root_dir
281
- os.chdir(root_dir)
282
-
283
- # Variables to store file paths and diff output
284
- file_paths = []
285
- diff_output = ""
286
-
287
- # Build git diff command based on review type
288
-
289
- if review_type == "commit":
290
- if "commit_sha" not in args:
291
- return {
292
- "success": False,
293
- "stdout": {},
294
- "stderr": "commit_sha is required for commit review type",
295
- }
296
- commit_sha = args["commit_sha"].strip()
297
- diff_cmd = f"git show {commit_sha} | cat -"
298
-
299
- # Execute git command and get diff output
300
- diff_output = subprocess.check_output(
301
- diff_cmd,
302
- shell=True,
303
- text=True,
304
- encoding="utf-8",
305
- errors="replace",
306
- )
307
- if not diff_output:
308
- return {
309
- "success": False,
310
- "stdout": {},
311
- "stderr": "No changes to review",
312
- }
313
-
314
- # Extract changed files using git command
315
- # Use git show with proper formatting to avoid needing grep
316
- files_cmd = f"git show --name-only --pretty=format: {commit_sha}"
317
- try:
318
- files_output = subprocess.check_output(
319
- files_cmd, shell=True, text=True
320
- )
321
- # Filter out empty lines without using grep
322
- file_paths = [
323
- f.strip() for f in files_output.split("\n") if f.strip()
324
- ]
325
- except subprocess.CalledProcessError:
326
- # Fallback to regex extraction if git command fails
327
- file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
328
- files = re.findall(file_pattern, diff_output)
329
- file_paths = [match[0] for match in files]
330
-
331
- elif review_type == "range":
332
- if "start_commit" not in args or "end_commit" not in args:
333
- return {
334
- "success": False,
335
- "stdout": {},
336
- "stderr": "start_commit and end_commit are required for range review type",
337
- }
338
- start_commit = args["start_commit"].strip()
339
- end_commit = args["end_commit"].strip()
340
- diff_cmd = f"git diff {start_commit}..{end_commit} | cat -"
341
-
342
- # Execute git command and get diff output
343
- diff_output = subprocess.check_output(
344
- diff_cmd,
345
- shell=True,
346
- text=True,
347
- encoding="utf-8",
348
- errors="replace",
349
- )
350
- if not diff_output:
351
- return {
352
- "success": False,
353
- "stdout": {},
354
- "stderr": "No changes to review",
355
- }
356
-
357
- # Extract changed files using git command
358
- files_cmd = f"git diff --name-only {start_commit}..{end_commit}"
359
- try:
360
- files_output = subprocess.check_output(
361
- files_cmd, shell=True, text=True
362
- )
363
- file_paths = [
364
- f.strip() for f in files_output.split("\n") if f.strip()
365
- ]
366
- except subprocess.CalledProcessError:
367
- # Fallback to regex extraction if git command fails
368
- file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
369
- files = re.findall(file_pattern, diff_output)
370
- file_paths = [match[0] for match in files]
371
-
372
- elif review_type == "file":
373
- if "file_path" not in args:
374
- return {
375
- "success": False,
376
- "stdout": {},
377
- "stderr": "file_path is required for file review type",
378
- }
379
- file_path = args["file_path"].strip()
380
- file_paths = [file_path]
381
- diff_output = ReadCodeTool().execute(
382
- {"files": [{"path": file_path}]}
383
- )["stdout"]
384
-
385
- else: # current changes
386
- diff_cmd = "git diff HEAD | cat -"
387
-
388
- # Execute git command and get diff output
389
- diff_output = subprocess.check_output(
390
- diff_cmd,
391
- shell=True,
392
- text=True,
393
- encoding="utf-8",
394
- errors="replace",
395
- )
396
- if not diff_output:
397
- return {
398
- "success": False,
399
- "stdout": {},
400
- "stderr": "No changes to review",
401
- }
402
-
403
- # Extract changed files using git command
404
- files_cmd = "git diff --name-only HEAD"
405
- try:
406
- files_output = subprocess.check_output(
407
- files_cmd, shell=True, text=True
408
- )
409
- file_paths = [
410
- f.strip() for f in files_output.split("\n") if f.strip()
411
- ]
412
- except subprocess.CalledProcessError:
413
- # Fallback to regex extraction if git command fails
414
- file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
415
- files = re.findall(file_pattern, diff_output)
416
- file_paths = [match[0] for match in files]
417
-
418
- # Detect languages from the file paths
419
- detected_languages = self._detect_languages_from_files(file_paths)
420
-
421
- # Add review type and related information to the diff output
422
- review_info = f"""
248
+ # Change to root_dir
249
+ os.chdir(root_dir)
250
+
251
+ # Variables to store file paths and diff output
252
+ file_paths: List[str] = []
253
+ diff_output = ""
254
+
255
+ # Build git diff command based on review type
256
+
257
+ if review_type == "commit":
258
+ if "commit_sha" not in args:
259
+ return {
260
+ "success": False,
261
+ "stdout": {},
262
+ "stderr": "commit_sha is required for commit review type",
263
+ }
264
+ commit_sha = args["commit_sha"].strip()
265
+ diff_cmd = f"git show {commit_sha} | cat -"
266
+
267
+ # Execute git command and get diff output
268
+ diff_output = subprocess.check_output(
269
+ diff_cmd,
270
+ shell=True,
271
+ text=True,
272
+ encoding="utf-8",
273
+ errors="replace",
274
+ )
275
+ if not diff_output:
276
+ return {
277
+ "success": False,
278
+ "stdout": {},
279
+ "stderr": "No changes to review",
280
+ }
281
+
282
+ # Extract changed files using git command
283
+ files_cmd = f"git show --name-only --pretty=format: {commit_sha}"
284
+ try:
285
+ files_output = subprocess.check_output(files_cmd, shell=True, text=True)
286
+ # Filter out empty lines without using grep
287
+ file_paths = [f.strip() for f in files_output.split("\n") if f.strip()]
288
+ except subprocess.CalledProcessError:
289
+ # Fallback to regex extraction if git command fails
290
+ file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
291
+ files = re.findall(file_pattern, diff_output)
292
+ file_paths = [match[0] for match in files]
293
+
294
+ elif review_type == "range":
295
+ if "start_commit" not in args or "end_commit" not in args:
296
+ return {
297
+ "success": False,
298
+ "stdout": {},
299
+ "stderr": "start_commit and end_commit are required for range review type",
300
+ }
301
+ start_commit = args["start_commit"].strip()
302
+ end_commit = args["end_commit"].strip()
303
+ diff_cmd = f"git diff {start_commit}..{end_commit} | cat -"
304
+
305
+ # Execute git command and get diff output
306
+ diff_output = subprocess.check_output(
307
+ diff_cmd,
308
+ shell=True,
309
+ text=True,
310
+ encoding="utf-8",
311
+ errors="replace",
312
+ )
313
+ if not diff_output:
314
+ return {
315
+ "success": False,
316
+ "stdout": {},
317
+ "stderr": "No changes to review",
318
+ }
319
+
320
+ # Extract changed files using git command
321
+ files_cmd = f"git diff --name-only {start_commit}..{end_commit}"
322
+ try:
323
+ files_output = subprocess.check_output(files_cmd, shell=True, text=True)
324
+ file_paths = [f.strip() for f in files_output.split("\n") if f.strip()]
325
+ except subprocess.CalledProcessError:
326
+ # Fallback to regex extraction if git command fails
327
+ file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
328
+ files = re.findall(file_pattern, diff_output)
329
+ file_paths = [match[0] for match in files]
330
+
331
+ elif review_type == "file":
332
+ if "file_path" not in args:
333
+ return {
334
+ "success": False,
335
+ "stdout": {},
336
+ "stderr": "file_path is required for file review type",
337
+ }
338
+ file_path = args["file_path"].strip()
339
+ file_paths = [file_path]
340
+ diff_output = ReadCodeTool().execute({"files": [{"path": file_path}]})["stdout"]
341
+
342
+ else: # current changes
343
+ diff_cmd = "git diff HEAD | cat -"
344
+
345
+ # Execute git command and get diff output
346
+ diff_output = subprocess.check_output(
347
+ diff_cmd,
348
+ shell=True,
349
+ text=True,
350
+ encoding="utf-8",
351
+ errors="replace",
352
+ )
353
+ if not diff_output:
354
+ return {
355
+ "success": False,
356
+ "stdout": {},
357
+ "stderr": "No changes to review",
358
+ }
359
+
360
+ # Extract changed files using git command
361
+ files_cmd = "git diff --name-only HEAD"
362
+ try:
363
+ files_output = subprocess.check_output(files_cmd, shell=True, text=True)
364
+ file_paths = [f.strip() for f in files_output.split("\n") if f.strip()]
365
+ except subprocess.CalledProcessError:
366
+ # Fallback to regex extraction if git command fails
367
+ file_pattern = r"diff --git a/.*?\s+b/(.*?)(\n|$)"
368
+ files = re.findall(file_pattern, diff_output)
369
+ file_paths = [match[0] for match in files]
370
+
371
+ # Detect languages from the file paths
372
+ detected_languages = _detect_languages_from_files(file_paths)
373
+
374
+ # Add review type and related information to the diff output
375
+ review_info = f"""
423
376
  ----- 代码审查信息 -----
424
377
  审查类型: {review_type}"""
425
378
 
426
- # Add specific information based on review type
427
- if review_type == "commit":
428
- review_info += f"\n提交SHA: {args['commit_sha']}"
429
- elif review_type == "range":
430
- review_info += f"\n起始提交: {args['start_commit']}\n结束提交: {args['end_commit']}"
431
- elif review_type == "file":
432
- review_info += f"\n文件路径: {args['file_path']}"
433
- else: # current changes
434
- review_info += "\n当前未提交修改"
435
-
436
- # Add file list
437
- if file_paths:
438
- review_info += "\n\n----- 变更文件列表 -----"
439
- for i, path in enumerate(file_paths, 1):
440
- review_info += f"\n{i}. {path}"
441
-
442
- # Add language-specific checklists
443
- if detected_languages:
444
- review_info += "\n\n----- 检测到的编程语言 -----"
445
- review_info += f"\n检测到的语言: {', '.join(detected_languages)}"
446
-
447
- review_info += "\n\n----- 语言特定审查清单 -----"
448
- for lang in detected_languages:
449
- checklist = self._get_language_checklist(lang)
450
- if checklist:
451
- review_info += f"\n{checklist}"
452
-
453
- review_info += "\n------------------------\n\n"
454
-
455
- # Combine review info with diff output
456
- diff_output = review_info + diff_output
457
-
458
- PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
459
-
460
- system_prompt = """<code_review_guide>
379
+ # Add specific information based on review type
380
+ if review_type == "commit":
381
+ review_info += f"\n提交SHA: {args['commit_sha']}"
382
+ elif review_type == "range":
383
+ review_info += f"\n起始提交: {args['start_commit']}\n结束提交: {args['end_commit']}"
384
+ elif review_type == "file":
385
+ review_info += f"\n文件路径: {args['file_path']}"
386
+ else: # current changes
387
+ review_info += "\n当前未提交修改"
388
+
389
+ # Add file list
390
+ if file_paths:
391
+ review_info += "\n\n----- 变更文件列表 -----"
392
+ for i, path in enumerate(file_paths, 1):
393
+ review_info += f"\n{i}. {path}"
394
+
395
+ # Add language-specific checklists
396
+ if detected_languages:
397
+ review_info += "\n\n----- 检测到的编程语言 -----"
398
+ review_info += f"\n检测到的语言: {', '.join(detected_languages)}"
399
+
400
+ review_info += "\n\n----- 语言特定审查清单 -----"
401
+ for lang in detected_languages:
402
+ checklist = _get_language_checklist(lang)
403
+ if checklist:
404
+ review_info += f"\n{checklist}"
405
+
406
+ review_info += "\n------------------------\n\n"
407
+
408
+ # Combine review info with diff output
409
+ diff_output = review_info + diff_output
410
+
411
+ PrettyOutput.print(diff_output, OutputType.CODE, lang="diff") # 保留语法高亮
412
+
413
+ system_prompt = """<code_review_guide>
461
414
  <role>
462
415
  你是一位精益求精的首席代码审查专家,拥有多年企业级代码审计经验。你需要对所有代码变更进行极其全面、严谨且深入的审查,确保代码质量达到最高标准。
463
416
  </role>
@@ -585,47 +538,17 @@ class CodeReviewTool:
585
538
 
586
539
  我将分析上传的代码差异文件,进行全面的代码审查。
587
540
  </code_review_guide>"""
588
- from jarvis.jarvis_tools.registry import ToolRegistry
589
541
 
590
- tool_registry = ToolRegistry()
591
- tool_registry.dont_use_tools(["code_review"])
542
+ # Get model_group from args (thinking mode removed)
543
+ model_group = args.get("model_group")
592
544
 
593
- # Get model_group from args (thinking mode removed)
594
- model_group = args.get("model_group")
595
545
 
596
- # Get platform and model from model_group
597
- from jarvis.jarvis_utils.config import (
598
- get_normal_platform_name,
599
- get_normal_model_name,
600
- )
601
-
602
- platform_name = get_normal_platform_name(model_group)
603
- model_name = get_normal_model_name(model_group)
604
-
605
- # If no explicit parameters, try to get from existing agent
606
- calling_agent = agent or get_agent(current_agent_name)
607
- if (
608
- not platform_name
609
- and calling_agent
610
- and hasattr(calling_agent, "model")
611
- and calling_agent.model
612
- ):
613
- platform_name = calling_agent.model.platform_name()
614
- model_name = calling_agent.model.name()
615
-
616
- # Create a new platform instance
617
- review_model = None
618
- if platform_name:
619
- review_model = PlatformRegistry().create_platform(platform_name)
620
- if review_model and model_name:
621
- review_model.set_model_name(model_name)
622
- if model_group:
623
- review_model.model_group = model_group
624
-
625
- agent = Agent(
626
- system_prompt=system_prompt,
627
- name="Code Review Agent",
628
- summary_prompt=f"""<code_review_report>
546
+ agent = Agent(
547
+ system_prompt=system_prompt,
548
+ name="Code Review Agent",
549
+ model_group=model_group,
550
+ use_methodology=False,
551
+ summary_prompt=f"""<code_review_report>
629
552
  <overview>
630
553
  # 整体评估
631
554
  [提供对整体代码质量、架构和主要关注点的简明概述,总结主要发现]
@@ -689,29 +612,23 @@ class CodeReviewTool:
689
612
  {ot("REPORT")}
690
613
  [在此处插入完整MARKDOWN格式的审查报告]
691
614
  {ct("REPORT")}""",
692
- output_handler=[tool_registry], # type: ignore
693
- auto_complete=False,
694
- )
615
+ auto_complete=args.get("auto_complete", False),
616
+ )
695
617
 
696
- # Replace the agent's model with our custom platform instance
697
- if review_model:
698
- agent.model = review_model
618
+ # Agent将基于传入的 model_group 自动初始化模型,无需手动注入
699
619
 
700
- # Determine if we need to split the diff due to size
701
- max_diff_size = 100 * 1024 * 1024 # Limit to 100MB
620
+ # Determine if we need to split the diff due to size
621
+ max_diff_size = 100 * 1024 * 1024 # Limit to 100MB
702
622
 
703
- if len(diff_output) > max_diff_size:
704
- PrettyOutput.print(
705
- f"代码差异内容总大小超过限制 ({len(diff_output)} > {max_diff_size} 字节),将截断内容",
706
- OutputType.WARNING,
707
- )
708
- diff_output = (
709
- diff_output[:max_diff_size]
710
- + "\n\n[diff content truncated due to size limitations...]"
711
- )
623
+ if len(diff_output) > max_diff_size:
624
+ print(f"⚠️ 代码差异内容总大小超过限制 ({len(diff_output)} > {max_diff_size} 字节),将截断内容")
625
+ diff_output = (
626
+ diff_output[:max_diff_size]
627
+ + "\n\n[diff content truncated due to size limitations...]"
628
+ )
712
629
 
713
- # Prepare the user prompt for code review
714
- user_prompt = f"""请对以下代码变更进行全面审查。
630
+ # Prepare the user prompt for code review
631
+ user_prompt = f"""请对以下代码变更进行全面审查。
715
632
 
716
633
  代码信息:
717
634
  - 审查类型: {review_type}
@@ -720,45 +637,44 @@ class CodeReviewTool:
720
637
 
721
638
  请根据SCRIPPPS框架和语言特定的审查清单进行分析,提供详细的代码审查报告。"""
722
639
 
723
- # Write the full diff output to a temporary file for uploading
724
- with tempfile.NamedTemporaryFile(
725
- mode="w", suffix=".diff", delete=False
726
- ) as temp_file:
727
- temp_file_path = temp_file.name
728
- temp_file.write(diff_output)
729
- temp_file.flush()
640
+ # Write the full diff output to a temporary file for uploading
641
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".diff", delete=False) as temp_file:
642
+ temp_file_path = temp_file.name
643
+ temp_file.write(diff_output)
644
+ temp_file.flush()
730
645
 
731
- try:
732
- # Check if content is too large
733
- is_large_content = is_context_overflow(
734
- diff_output, review_model.model_group if review_model else None
735
- )
646
+ try:
647
+ # Check if content is too large
648
+ platform = agent.model if agent and agent.model else None
649
+ is_large_content = is_context_overflow(
650
+ diff_output, model_group, platform
651
+ )
736
652
 
737
- # Upload the file to the agent's model
738
- if is_large_content:
739
- if not agent.model or not agent.model.support_upload_files():
740
- return {
741
- "success": False,
742
- "stdout": "",
743
- "stderr": "代码差异太大,无法处理",
744
- }
745
-
746
- upload_success = agent.model.upload_files([temp_file_path])
747
- if upload_success:
748
- pass
749
- else:
750
- return {
751
- "success": False,
752
- "stdout": "",
753
- "stderr": "上传代码差异文件失败",
754
- }
755
-
756
- # Prepare the prompt based on upload status
757
- if is_large_content:
758
- # When file is uploaded, reference it in the prompt
759
- complete_prompt = (
760
- user_prompt
761
- + f"""
653
+ # Upload the file to the agent's model
654
+ if is_large_content:
655
+ if not agent.model or not agent.model.support_upload_files():
656
+ return {
657
+ "success": False,
658
+ "stdout": "",
659
+ "stderr": "代码差异太大,无法处理",
660
+ }
661
+
662
+ upload_success = agent.model.upload_files([temp_file_path])
663
+ if upload_success:
664
+ pass
665
+ else:
666
+ return {
667
+ "success": False,
668
+ "stdout": "",
669
+ "stderr": "上传代码差异文件失败",
670
+ }
671
+
672
+ # Prepare the prompt based on upload status
673
+ if is_large_content:
674
+ # When file is uploaded, reference it in the prompt
675
+ complete_prompt = (
676
+ user_prompt
677
+ + f"""
762
678
 
763
679
  我已上传了一个包含代码差异的文件。该文件包含:
764
680
  - 审查类型: {review_type}
@@ -766,39 +682,36 @@ class CodeReviewTool:
766
682
  - 检测到的编程语言: {', '.join(detected_languages) if detected_languages else '未检测到特定语言'}
767
683
 
768
684
  请基于上传的代码差异文件进行全面审查,并生成详细的代码审查报告。"""
769
- )
770
- # Run the agent with the prompt
771
- result = agent.run(complete_prompt)
772
- else:
773
- complete_prompt = (
774
- user_prompt
775
- + "\n\n代码差异内容:\n```diff\n"
776
- + diff_output
777
- + "\n```"
778
- )
779
- result = agent.run(complete_prompt)
780
- finally:
781
- # Clean up the temporary file
782
- if os.path.exists(temp_file_path):
783
- try:
784
- os.unlink(temp_file_path)
785
- except Exception:
786
- PrettyOutput.print(
787
- f"临时文件 {temp_file_path} 未能删除",
788
- OutputType.WARNING,
789
- )
790
-
791
- return {"success": True, "stdout": result, "stderr": ""}
685
+ )
686
+ # Run the agent with the prompt
687
+ result = agent.run(complete_prompt)
688
+ else:
689
+ complete_prompt = (
690
+ user_prompt
691
+ + "\n\n代码差异内容:\n```diff\n"
692
+ + diff_output
693
+ + "\n```"
694
+ )
695
+ result = agent.run(complete_prompt)
792
696
  finally:
793
- # Always restore original directory
794
- os.chdir(original_dir)
795
-
796
- except Exception as e:
797
- return {
798
- "success": False,
799
- "stdout": {},
800
- "stderr": f"Review failed: {str(e)}",
801
- }
697
+ # Clean up the temporary file
698
+ if os.path.exists(temp_file_path):
699
+ try:
700
+ os.unlink(temp_file_path)
701
+ except Exception:
702
+ print(f"⚠️ 临时文件 {temp_file_path} 未能删除")
703
+
704
+ return {"success": True, "stdout": result, "stderr": ""}
705
+ finally:
706
+ # Always restore original directory
707
+ os.chdir(original_dir)
708
+
709
+ except Exception as e:
710
+ return {
711
+ "success": False,
712
+ "stdout": {},
713
+ "stderr": f"Review failed: {str(e)}",
714
+ }
802
715
 
803
716
 
804
717
  def extract_code_report(result: str) -> str:
@@ -812,52 +725,50 @@ def extract_code_report(result: str) -> str:
812
725
  def review_commit(
813
726
  commit: str = typer.Argument(..., help="要审查的提交SHA"),
814
727
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
815
-
816
728
  model_group: Optional[str] = typer.Option(
817
729
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
818
730
  ),
731
+ auto_complete: bool = typer.Option(False, "--auto-complete/--no-auto-complete", help="是否自动完成"),
819
732
  ):
820
733
  """审查指定的提交"""
821
- tool = CodeReviewTool()
822
734
  tool_args = {
823
735
  "review_type": "commit",
824
736
  "commit_sha": commit,
825
737
  "root_dir": root_dir,
826
-
827
738
  "model_group": model_group,
739
+ "auto_complete": auto_complete,
828
740
  }
829
- result = tool.execute(tool_args)
741
+ result = execute_code_review(tool_args)
830
742
  if result["success"]:
831
- PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
743
+ print("自动代码审查结果:")
832
744
  report = extract_code_report(result["stdout"])
833
- PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
745
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
834
746
  else:
835
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
747
+ print(f"⚠️ {result['stderr']}")
836
748
 
837
749
 
838
750
  @app.command("current")
839
751
  def review_current(
840
752
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
841
-
842
753
  model_group: Optional[str] = typer.Option(
843
754
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
844
755
  ),
756
+ auto_complete: bool = typer.Option(False, "--auto-complete/--no-auto-complete", help="是否自动完成"),
845
757
  ):
846
758
  """审查当前的变更"""
847
- tool = CodeReviewTool()
848
759
  tool_args = {
849
760
  "review_type": "current",
850
761
  "root_dir": root_dir,
851
-
852
762
  "model_group": model_group,
763
+ "auto_complete": auto_complete,
853
764
  }
854
- result = tool.execute(tool_args)
765
+ result = execute_code_review(tool_args)
855
766
  if result["success"]:
856
- PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
767
+ print("自动代码审查结果:")
857
768
  report = extract_code_report(result["stdout"])
858
- PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
769
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
859
770
  else:
860
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
771
+ print(f"⚠️ {result['stderr']}")
861
772
 
862
773
 
863
774
  @app.command("range")
@@ -865,60 +776,58 @@ def review_range(
865
776
  start_commit: str = typer.Argument(..., help="起始提交SHA"),
866
777
  end_commit: str = typer.Argument(..., help="结束提交SHA"),
867
778
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
868
-
869
779
  model_group: Optional[str] = typer.Option(
870
780
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
871
781
  ),
782
+ auto_complete: bool = typer.Option(False, "--auto-complete/--no-auto-complete", help="是否自动完成"),
872
783
  ):
873
784
  """审查提交范围"""
874
- tool = CodeReviewTool()
875
785
  tool_args = {
876
786
  "review_type": "range",
877
787
  "start_commit": start_commit,
878
788
  "end_commit": end_commit,
879
789
  "root_dir": root_dir,
880
-
881
790
  "model_group": model_group,
791
+ "auto_complete": auto_complete,
882
792
  }
883
- result = tool.execute(tool_args)
793
+ result = execute_code_review(tool_args)
884
794
  if result["success"]:
885
- PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
795
+ print("自动代码审查结果:")
886
796
  report = extract_code_report(result["stdout"])
887
- PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
797
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
888
798
  else:
889
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
799
+ print(f"⚠️ {result['stderr']}")
890
800
 
891
801
 
892
802
  @app.command("file")
893
803
  def review_file(
894
804
  file: str = typer.Argument(..., help="要审查的文件路径"),
895
805
  root_dir: str = typer.Option(".", "--root-dir", help="代码库根目录路径"),
896
-
897
806
  model_group: Optional[str] = typer.Option(
898
807
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
899
808
  ),
809
+ auto_complete: bool = typer.Option(False, "--auto-complete/--no-auto-complete", help="是否自动完成"),
900
810
  ):
901
811
  """审查指定的文件"""
902
- tool = CodeReviewTool()
903
812
  tool_args = {
904
813
  "review_type": "file",
905
814
  "file_path": file,
906
815
  "root_dir": root_dir,
907
-
908
816
  "model_group": model_group,
817
+ "auto_complete": auto_complete,
909
818
  }
910
- result = tool.execute(tool_args)
819
+ result = execute_code_review(tool_args)
911
820
  if result["success"]:
912
- PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
821
+ print("自动代码审查结果:")
913
822
  report = extract_code_report(result["stdout"])
914
- PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
823
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown") # 保留语法高亮
915
824
  else:
916
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
825
+ print(f"⚠️ {result['stderr']}")
917
826
 
918
827
 
919
828
  def cli():
920
829
  """Typer application entry point"""
921
- init_env("欢迎使用 Jarvis-CodeReview,您的代码审查助手已准备就绪!")
830
+ init_env("")
922
831
  app()
923
832
 
924
833
 
@@ -928,4 +837,4 @@ def main():
928
837
 
929
838
 
930
839
  if __name__ == "__main__":
931
- main()
840
+ main()