jarvis-ai-assistant 0.7.8__py3-none-any.whl → 1.0.2__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 (279) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +567 -222
  3. jarvis/jarvis_agent/agent_manager.py +19 -12
  4. jarvis/jarvis_agent/builtin_input_handler.py +79 -11
  5. jarvis/jarvis_agent/config_editor.py +7 -2
  6. jarvis/jarvis_agent/event_bus.py +24 -13
  7. jarvis/jarvis_agent/events.py +19 -1
  8. jarvis/jarvis_agent/file_context_handler.py +67 -64
  9. jarvis/jarvis_agent/file_methodology_manager.py +38 -24
  10. jarvis/jarvis_agent/jarvis.py +186 -114
  11. jarvis/jarvis_agent/language_extractors/__init__.py +8 -1
  12. jarvis/jarvis_agent/language_extractors/c_extractor.py +7 -4
  13. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +9 -4
  14. jarvis/jarvis_agent/language_extractors/go_extractor.py +7 -4
  15. jarvis/jarvis_agent/language_extractors/java_extractor.py +27 -20
  16. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +22 -17
  17. jarvis/jarvis_agent/language_extractors/python_extractor.py +7 -4
  18. jarvis/jarvis_agent/language_extractors/rust_extractor.py +7 -4
  19. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +22 -17
  20. jarvis/jarvis_agent/language_support_info.py +250 -219
  21. jarvis/jarvis_agent/main.py +19 -23
  22. jarvis/jarvis_agent/memory_manager.py +9 -6
  23. jarvis/jarvis_agent/methodology_share_manager.py +21 -15
  24. jarvis/jarvis_agent/output_handler.py +4 -2
  25. jarvis/jarvis_agent/prompt_builder.py +7 -6
  26. jarvis/jarvis_agent/prompt_manager.py +113 -8
  27. jarvis/jarvis_agent/prompts.py +317 -85
  28. jarvis/jarvis_agent/protocols.py +5 -2
  29. jarvis/jarvis_agent/run_loop.py +192 -32
  30. jarvis/jarvis_agent/session_manager.py +7 -3
  31. jarvis/jarvis_agent/share_manager.py +23 -13
  32. jarvis/jarvis_agent/shell_input_handler.py +12 -8
  33. jarvis/jarvis_agent/stdio_redirect.py +25 -26
  34. jarvis/jarvis_agent/task_analyzer.py +29 -23
  35. jarvis/jarvis_agent/task_list.py +869 -0
  36. jarvis/jarvis_agent/task_manager.py +26 -23
  37. jarvis/jarvis_agent/tool_executor.py +6 -5
  38. jarvis/jarvis_agent/tool_share_manager.py +24 -14
  39. jarvis/jarvis_agent/user_interaction.py +3 -3
  40. jarvis/jarvis_agent/utils.py +9 -1
  41. jarvis/jarvis_agent/web_bridge.py +37 -17
  42. jarvis/jarvis_agent/web_output_sink.py +5 -2
  43. jarvis/jarvis_agent/web_server.py +165 -36
  44. jarvis/jarvis_c2rust/__init__.py +1 -1
  45. jarvis/jarvis_c2rust/cli.py +260 -141
  46. jarvis/jarvis_c2rust/collector.py +37 -18
  47. jarvis/jarvis_c2rust/constants.py +60 -0
  48. jarvis/jarvis_c2rust/library_replacer.py +242 -1010
  49. jarvis/jarvis_c2rust/library_replacer_checkpoint.py +133 -0
  50. jarvis/jarvis_c2rust/library_replacer_llm.py +287 -0
  51. jarvis/jarvis_c2rust/library_replacer_loader.py +191 -0
  52. jarvis/jarvis_c2rust/library_replacer_output.py +134 -0
  53. jarvis/jarvis_c2rust/library_replacer_prompts.py +124 -0
  54. jarvis/jarvis_c2rust/library_replacer_utils.py +188 -0
  55. jarvis/jarvis_c2rust/llm_module_agent.py +98 -1044
  56. jarvis/jarvis_c2rust/llm_module_agent_apply.py +170 -0
  57. jarvis/jarvis_c2rust/llm_module_agent_executor.py +288 -0
  58. jarvis/jarvis_c2rust/llm_module_agent_loader.py +170 -0
  59. jarvis/jarvis_c2rust/llm_module_agent_prompts.py +268 -0
  60. jarvis/jarvis_c2rust/llm_module_agent_types.py +57 -0
  61. jarvis/jarvis_c2rust/llm_module_agent_utils.py +150 -0
  62. jarvis/jarvis_c2rust/llm_module_agent_validator.py +119 -0
  63. jarvis/jarvis_c2rust/loaders.py +28 -10
  64. jarvis/jarvis_c2rust/models.py +5 -2
  65. jarvis/jarvis_c2rust/optimizer.py +192 -1974
  66. jarvis/jarvis_c2rust/optimizer_build_fix.py +286 -0
  67. jarvis/jarvis_c2rust/optimizer_clippy.py +766 -0
  68. jarvis/jarvis_c2rust/optimizer_config.py +49 -0
  69. jarvis/jarvis_c2rust/optimizer_docs.py +183 -0
  70. jarvis/jarvis_c2rust/optimizer_options.py +48 -0
  71. jarvis/jarvis_c2rust/optimizer_progress.py +469 -0
  72. jarvis/jarvis_c2rust/optimizer_report.py +52 -0
  73. jarvis/jarvis_c2rust/optimizer_unsafe.py +309 -0
  74. jarvis/jarvis_c2rust/optimizer_utils.py +469 -0
  75. jarvis/jarvis_c2rust/optimizer_visibility.py +185 -0
  76. jarvis/jarvis_c2rust/scanner.py +229 -166
  77. jarvis/jarvis_c2rust/transpiler.py +531 -2732
  78. jarvis/jarvis_c2rust/transpiler_agents.py +503 -0
  79. jarvis/jarvis_c2rust/transpiler_build.py +1294 -0
  80. jarvis/jarvis_c2rust/transpiler_codegen.py +204 -0
  81. jarvis/jarvis_c2rust/transpiler_compile.py +146 -0
  82. jarvis/jarvis_c2rust/transpiler_config.py +178 -0
  83. jarvis/jarvis_c2rust/transpiler_context.py +122 -0
  84. jarvis/jarvis_c2rust/transpiler_executor.py +516 -0
  85. jarvis/jarvis_c2rust/transpiler_generation.py +278 -0
  86. jarvis/jarvis_c2rust/transpiler_git.py +163 -0
  87. jarvis/jarvis_c2rust/transpiler_mod_utils.py +225 -0
  88. jarvis/jarvis_c2rust/transpiler_modules.py +336 -0
  89. jarvis/jarvis_c2rust/transpiler_planning.py +394 -0
  90. jarvis/jarvis_c2rust/transpiler_review.py +1196 -0
  91. jarvis/jarvis_c2rust/transpiler_symbols.py +176 -0
  92. jarvis/jarvis_c2rust/utils.py +269 -79
  93. jarvis/jarvis_code_agent/after_change.py +233 -0
  94. jarvis/jarvis_code_agent/build_validation_config.py +37 -30
  95. jarvis/jarvis_code_agent/builtin_rules.py +68 -0
  96. jarvis/jarvis_code_agent/code_agent.py +976 -1517
  97. jarvis/jarvis_code_agent/code_agent_build.py +227 -0
  98. jarvis/jarvis_code_agent/code_agent_diff.py +246 -0
  99. jarvis/jarvis_code_agent/code_agent_git.py +525 -0
  100. jarvis/jarvis_code_agent/code_agent_impact.py +177 -0
  101. jarvis/jarvis_code_agent/code_agent_lint.py +283 -0
  102. jarvis/jarvis_code_agent/code_agent_llm.py +159 -0
  103. jarvis/jarvis_code_agent/code_agent_postprocess.py +105 -0
  104. jarvis/jarvis_code_agent/code_agent_prompts.py +46 -0
  105. jarvis/jarvis_code_agent/code_agent_rules.py +305 -0
  106. jarvis/jarvis_code_agent/code_analyzer/__init__.py +52 -48
  107. jarvis/jarvis_code_agent/code_analyzer/base_language.py +12 -10
  108. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +12 -11
  109. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +16 -12
  110. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +26 -17
  111. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +558 -104
  112. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +27 -16
  113. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +22 -18
  114. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +21 -16
  115. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +20 -16
  116. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +27 -16
  117. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +47 -23
  118. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +71 -37
  119. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +162 -35
  120. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +111 -57
  121. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +18 -12
  122. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +185 -183
  123. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +2 -1
  124. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +24 -15
  125. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +227 -141
  126. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +321 -247
  127. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +37 -29
  128. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -13
  129. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +15 -9
  130. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +75 -45
  131. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +87 -52
  132. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +84 -51
  133. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +94 -64
  134. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +109 -71
  135. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +97 -63
  136. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +103 -69
  137. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +271 -268
  138. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +76 -64
  139. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +92 -19
  140. jarvis/jarvis_code_agent/diff_visualizer.py +998 -0
  141. jarvis/jarvis_code_agent/lint.py +223 -524
  142. jarvis/jarvis_code_agent/rule_share_manager.py +158 -0
  143. jarvis/jarvis_code_agent/rules/clean_code.md +144 -0
  144. jarvis/jarvis_code_agent/rules/code_review.md +115 -0
  145. jarvis/jarvis_code_agent/rules/documentation.md +165 -0
  146. jarvis/jarvis_code_agent/rules/generate_rules.md +52 -0
  147. jarvis/jarvis_code_agent/rules/performance.md +158 -0
  148. jarvis/jarvis_code_agent/rules/refactoring.md +139 -0
  149. jarvis/jarvis_code_agent/rules/security.md +160 -0
  150. jarvis/jarvis_code_agent/rules/tdd.md +78 -0
  151. jarvis/jarvis_code_agent/test_rules/cpp_test.md +118 -0
  152. jarvis/jarvis_code_agent/test_rules/go_test.md +98 -0
  153. jarvis/jarvis_code_agent/test_rules/java_test.md +99 -0
  154. jarvis/jarvis_code_agent/test_rules/javascript_test.md +113 -0
  155. jarvis/jarvis_code_agent/test_rules/php_test.md +117 -0
  156. jarvis/jarvis_code_agent/test_rules/python_test.md +91 -0
  157. jarvis/jarvis_code_agent/test_rules/ruby_test.md +102 -0
  158. jarvis/jarvis_code_agent/test_rules/rust_test.md +86 -0
  159. jarvis/jarvis_code_agent/utils.py +36 -26
  160. jarvis/jarvis_code_analysis/checklists/loader.py +21 -21
  161. jarvis/jarvis_code_analysis/code_review.py +64 -33
  162. jarvis/jarvis_data/config_schema.json +285 -192
  163. jarvis/jarvis_git_squash/main.py +8 -6
  164. jarvis/jarvis_git_utils/git_commiter.py +53 -76
  165. jarvis/jarvis_mcp/__init__.py +5 -2
  166. jarvis/jarvis_mcp/sse_mcp_client.py +40 -30
  167. jarvis/jarvis_mcp/stdio_mcp_client.py +27 -19
  168. jarvis/jarvis_mcp/streamable_mcp_client.py +35 -26
  169. jarvis/jarvis_memory_organizer/memory_organizer.py +78 -55
  170. jarvis/jarvis_methodology/main.py +48 -39
  171. jarvis/jarvis_multi_agent/__init__.py +56 -23
  172. jarvis/jarvis_multi_agent/main.py +15 -18
  173. jarvis/jarvis_platform/base.py +179 -111
  174. jarvis/jarvis_platform/human.py +27 -16
  175. jarvis/jarvis_platform/kimi.py +52 -45
  176. jarvis/jarvis_platform/openai.py +101 -40
  177. jarvis/jarvis_platform/registry.py +51 -33
  178. jarvis/jarvis_platform/tongyi.py +68 -38
  179. jarvis/jarvis_platform/yuanbao.py +59 -43
  180. jarvis/jarvis_platform_manager/main.py +68 -76
  181. jarvis/jarvis_platform_manager/service.py +24 -14
  182. jarvis/jarvis_rag/README_CONFIG.md +314 -0
  183. jarvis/jarvis_rag/README_DYNAMIC_LOADING.md +311 -0
  184. jarvis/jarvis_rag/README_ONLINE_MODELS.md +230 -0
  185. jarvis/jarvis_rag/__init__.py +57 -4
  186. jarvis/jarvis_rag/cache.py +3 -1
  187. jarvis/jarvis_rag/cli.py +48 -68
  188. jarvis/jarvis_rag/embedding_interface.py +39 -0
  189. jarvis/jarvis_rag/embedding_manager.py +7 -230
  190. jarvis/jarvis_rag/embeddings/__init__.py +41 -0
  191. jarvis/jarvis_rag/embeddings/base.py +114 -0
  192. jarvis/jarvis_rag/embeddings/cohere.py +66 -0
  193. jarvis/jarvis_rag/embeddings/edgefn.py +117 -0
  194. jarvis/jarvis_rag/embeddings/local.py +260 -0
  195. jarvis/jarvis_rag/embeddings/openai.py +62 -0
  196. jarvis/jarvis_rag/embeddings/registry.py +293 -0
  197. jarvis/jarvis_rag/llm_interface.py +8 -6
  198. jarvis/jarvis_rag/query_rewriter.py +8 -9
  199. jarvis/jarvis_rag/rag_pipeline.py +61 -52
  200. jarvis/jarvis_rag/reranker.py +7 -75
  201. jarvis/jarvis_rag/reranker_interface.py +32 -0
  202. jarvis/jarvis_rag/rerankers/__init__.py +41 -0
  203. jarvis/jarvis_rag/rerankers/base.py +109 -0
  204. jarvis/jarvis_rag/rerankers/cohere.py +67 -0
  205. jarvis/jarvis_rag/rerankers/edgefn.py +140 -0
  206. jarvis/jarvis_rag/rerankers/jina.py +79 -0
  207. jarvis/jarvis_rag/rerankers/local.py +89 -0
  208. jarvis/jarvis_rag/rerankers/registry.py +293 -0
  209. jarvis/jarvis_rag/retriever.py +58 -43
  210. jarvis/jarvis_sec/__init__.py +66 -141
  211. jarvis/jarvis_sec/agents.py +21 -17
  212. jarvis/jarvis_sec/analysis.py +80 -33
  213. jarvis/jarvis_sec/checkers/__init__.py +7 -13
  214. jarvis/jarvis_sec/checkers/c_checker.py +356 -164
  215. jarvis/jarvis_sec/checkers/rust_checker.py +47 -29
  216. jarvis/jarvis_sec/cli.py +43 -21
  217. jarvis/jarvis_sec/clustering.py +430 -272
  218. jarvis/jarvis_sec/file_manager.py +99 -55
  219. jarvis/jarvis_sec/parsers.py +9 -6
  220. jarvis/jarvis_sec/prompts.py +4 -3
  221. jarvis/jarvis_sec/report.py +44 -22
  222. jarvis/jarvis_sec/review.py +180 -107
  223. jarvis/jarvis_sec/status.py +50 -41
  224. jarvis/jarvis_sec/types.py +3 -0
  225. jarvis/jarvis_sec/utils.py +160 -83
  226. jarvis/jarvis_sec/verification.py +411 -181
  227. jarvis/jarvis_sec/workflow.py +132 -21
  228. jarvis/jarvis_smart_shell/main.py +28 -41
  229. jarvis/jarvis_stats/cli.py +14 -12
  230. jarvis/jarvis_stats/stats.py +28 -19
  231. jarvis/jarvis_stats/storage.py +14 -8
  232. jarvis/jarvis_stats/visualizer.py +12 -7
  233. jarvis/jarvis_tools/base.py +5 -2
  234. jarvis/jarvis_tools/clear_memory.py +13 -9
  235. jarvis/jarvis_tools/cli/main.py +23 -18
  236. jarvis/jarvis_tools/edit_file.py +572 -873
  237. jarvis/jarvis_tools/execute_script.py +10 -7
  238. jarvis/jarvis_tools/file_analyzer.py +7 -8
  239. jarvis/jarvis_tools/meta_agent.py +287 -0
  240. jarvis/jarvis_tools/methodology.py +5 -3
  241. jarvis/jarvis_tools/read_code.py +305 -1438
  242. jarvis/jarvis_tools/read_symbols.py +50 -17
  243. jarvis/jarvis_tools/read_webpage.py +19 -18
  244. jarvis/jarvis_tools/registry.py +435 -156
  245. jarvis/jarvis_tools/retrieve_memory.py +16 -11
  246. jarvis/jarvis_tools/save_memory.py +8 -6
  247. jarvis/jarvis_tools/search_web.py +31 -31
  248. jarvis/jarvis_tools/sub_agent.py +32 -28
  249. jarvis/jarvis_tools/sub_code_agent.py +44 -60
  250. jarvis/jarvis_tools/task_list_manager.py +1811 -0
  251. jarvis/jarvis_tools/virtual_tty.py +29 -19
  252. jarvis/jarvis_utils/__init__.py +4 -0
  253. jarvis/jarvis_utils/builtin_replace_map.py +2 -1
  254. jarvis/jarvis_utils/clipboard.py +9 -8
  255. jarvis/jarvis_utils/collections.py +331 -0
  256. jarvis/jarvis_utils/config.py +699 -194
  257. jarvis/jarvis_utils/dialogue_recorder.py +294 -0
  258. jarvis/jarvis_utils/embedding.py +6 -3
  259. jarvis/jarvis_utils/file_processors.py +7 -1
  260. jarvis/jarvis_utils/fzf.py +9 -3
  261. jarvis/jarvis_utils/git_utils.py +71 -42
  262. jarvis/jarvis_utils/globals.py +116 -32
  263. jarvis/jarvis_utils/http.py +6 -2
  264. jarvis/jarvis_utils/input.py +318 -83
  265. jarvis/jarvis_utils/jsonnet_compat.py +119 -104
  266. jarvis/jarvis_utils/methodology.py +37 -28
  267. jarvis/jarvis_utils/output.py +201 -44
  268. jarvis/jarvis_utils/utils.py +986 -628
  269. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/METADATA +49 -33
  270. jarvis_ai_assistant-1.0.2.dist-info/RECORD +304 -0
  271. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +0 -556
  272. jarvis/jarvis_tools/generate_new_tool.py +0 -205
  273. jarvis/jarvis_tools/lsp_client.py +0 -1552
  274. jarvis/jarvis_tools/rewrite_file.py +0 -105
  275. jarvis_ai_assistant-0.7.8.dist-info/RECORD +0 -218
  276. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/WHEEL +0 -0
  277. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/entry_points.txt +0 -0
  278. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/licenses/LICENSE +0 -0
  279. {jarvis_ai_assistant-0.7.8.dist-info → jarvis_ai_assistant-1.0.2.dist-info}/top_level.txt +0 -0
@@ -5,9 +5,11 @@ from typing import Dict
5
5
  import typer
6
6
 
7
7
  from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
8
- from jarvis.jarvis_utils.utils import init_env
8
+ from jarvis.jarvis_utils.globals import get_agent
9
+ from jarvis.jarvis_utils.globals import get_current_agent_name
9
10
  from jarvis.jarvis_utils.input import user_confirm
10
- from jarvis.jarvis_utils.globals import get_agent, current_agent_name
11
+ from jarvis.jarvis_utils.output import PrettyOutput
12
+ from jarvis.jarvis_utils.utils import init_env
11
13
 
12
14
  app = typer.Typer(help="Git压缩工具")
13
15
 
@@ -37,22 +39,22 @@ class GitSquashTool:
37
39
  """Execute the squash operation"""
38
40
  try:
39
41
  if not self._confirm_squash():
40
- print("⚠️ 操作已取消")
42
+ PrettyOutput.auto_print("⚠️ 操作已取消")
41
43
  return
42
44
 
43
45
  if not self._reset_to_commit(args["commit_hash"]):
44
- print("⚠️ 重置到指定提交失败")
46
+ PrettyOutput.auto_print("⚠️ 重置到指定提交失败")
45
47
  return
46
48
 
47
49
  # Use existing GitCommitTool for new commit
48
50
  commit_tool = GitCommitTool()
49
- agent = get_agent(current_agent_name)
51
+ agent = get_agent(get_current_agent_name())
50
52
  exec_args = {"lang": args.get("lang", "Chinese")}
51
53
  if agent:
52
54
  exec_args["agent"] = agent
53
55
  commit_tool.execute(exec_args)
54
56
  except Exception as e:
55
- print(f"⚠️ 压缩提交失败: {str(e)}")
57
+ PrettyOutput.auto_print(f"⚠️ 压缩提交失败: {str(e)}")
56
58
 
57
59
 
58
60
  @app.command()
@@ -3,27 +3,32 @@ import os
3
3
  import re
4
4
  import subprocess
5
5
  import tempfile
6
- from typing import Any, Dict, Optional
6
+ from typing import Any
7
+ from typing import Dict
8
+ from typing import Optional
7
9
 
8
10
  import typer
9
- import yaml # type: ignore
11
+ import yaml
12
+ from rich.console import Console
13
+ from rich.panel import Panel
10
14
 
11
15
  from jarvis.jarvis_platform.registry import PlatformRegistry
12
16
  from jarvis.jarvis_utils.config import get_git_commit_prompt
13
- from jarvis.jarvis_utils.git_utils import (
14
- confirm_add_new_files,
15
- find_git_root_and_cd,
16
- has_uncommitted_changes,
17
- )
18
- from jarvis.jarvis_utils.globals import get_agent, current_agent_name
19
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
- from jarvis.jarvis_utils.tag import ct, ot
21
- from jarvis.jarvis_utils.utils import init_env, is_context_overflow
17
+ from jarvis.jarvis_utils.git_utils import confirm_add_new_files
18
+ from jarvis.jarvis_utils.git_utils import find_git_root_and_cd
19
+ from jarvis.jarvis_utils.git_utils import has_uncommitted_changes
20
+ from jarvis.jarvis_utils.globals import get_global_model_group
21
+ from jarvis.jarvis_utils.output import PrettyOutput
22
+ from jarvis.jarvis_utils.tag import ct
23
+ from jarvis.jarvis_utils.tag import ot
24
+ from jarvis.jarvis_utils.utils import init_env
25
+ from jarvis.jarvis_utils.utils import is_context_overflow
22
26
 
23
27
  app = typer.Typer(help="Git提交工具")
24
28
 
25
29
 
26
30
  class GitCommitTool:
31
+ console = Console()
27
32
  name = "git_commit_agent"
28
33
  description = "根据代码变更自动生成并执行Git提交"
29
34
  labels = ["git", "version_control"]
@@ -75,7 +80,7 @@ class GitCommitTool:
75
80
  os.chdir(root_dir)
76
81
  find_git_root_and_cd()
77
82
  if not has_uncommitted_changes():
78
- print("✅ 没有未提交的更改")
83
+ PrettyOutput.auto_print("✅ 没有未提交的更改")
79
84
  return None
80
85
  return original_dir
81
86
 
@@ -129,67 +134,23 @@ class GitCommitTool:
129
134
 
130
135
  try:
131
136
  temp_diff_file_path = None
132
-
133
- # Get model_group from args
134
- model_group = args.get("model_group")
135
137
 
136
- # Get platform and model based on model_group (thinking mode removed)
137
- from jarvis.jarvis_utils.config import (
138
- get_normal_platform_name,
139
- get_normal_model_name,
140
- )
138
+ # 优先使用args中的model_group,否则使用全局模型组(不再从agent继承)
139
+ model_group = args.get("model_group") or get_global_model_group()
141
140
 
142
- platform_name = None
143
- model_name = None
141
+ # Get platform and model based on model_group (thinking mode removed)
142
+ from jarvis.jarvis_utils.config import get_normal_model_name
143
+ from jarvis.jarvis_utils.config import get_normal_platform_name
144
144
 
145
+ # 始终使用normal模型生成提交信息,不从agent.model获取(避免使用smart模型)
145
146
  # 优先根据 model_group 获取(确保配置一致性)
146
- # 如果 model_group 存在,强制使用它来解析,避免使用 agent.model 中可能不一致的值
147
147
  if model_group:
148
148
  platform_name = get_normal_platform_name(model_group)
149
149
  model_name = get_normal_model_name(model_group)
150
150
  else:
151
- # 如果没有提供 model_group,尝试从传入的 agent 获取
152
- agent_from_args = args.get("agent")
153
- if (
154
- agent_from_args
155
- and hasattr(agent_from_args, "model")
156
- and getattr(agent_from_args, "model", None)
157
- ):
158
- try:
159
- platform_name = agent_from_args.model.platform_name()
160
- model_name = agent_from_args.model.name()
161
- if hasattr(agent_from_args.model, "model_group"):
162
- model_group = agent_from_args.model.model_group
163
- except Exception:
164
- # 安全回退到后续逻辑
165
- platform_name = None
166
- model_name = None
167
-
168
- # 如果仍未获取到,使用配置文件中的默认值(传入 None 会读取默认配置)
169
- if not platform_name:
170
- platform_name = get_normal_platform_name(None)
171
- if not model_name:
172
- model_name = get_normal_model_name(None)
173
-
174
- # 最后的回退:尝试从全局 agent 获取(仅当仍未获取到时)
175
- if not platform_name:
176
- agent = get_agent(current_agent_name)
177
- if (
178
- agent
179
- and hasattr(agent, "model")
180
- and getattr(agent, "model", None)
181
- ):
182
- try:
183
- platform_name = agent.model.platform_name()
184
- model_name = agent.model.name()
185
- if not model_group and hasattr(agent.model, "model_group"):
186
- model_group = agent.model.model_group
187
- except Exception:
188
- # 如果全局 agent 也无法获取,使用配置文件默认值
189
- if not platform_name:
190
- platform_name = get_normal_platform_name(None)
191
- if not model_name:
192
- model_name = get_normal_model_name(None)
151
+ # 如果没有提供 model_group,直接使用配置文件中的默认normal模型
152
+ platform_name = get_normal_platform_name(None)
153
+ model_name = get_normal_model_name(None)
193
154
 
194
155
  # Create a new platform instance
195
156
  if platform_name:
@@ -201,13 +162,17 @@ class GitCommitTool:
201
162
  platform.set_model_group(model_group)
202
163
  except Exception:
203
164
  # 兼容早期实现
204
- platform.model_group = model_group # type: ignore
165
+ platform.model_group = model_group
205
166
  else:
206
167
  platform = PlatformRegistry().get_normal_platform()
207
168
 
208
169
  # 生成提交信息
209
- model_display_name = model_name or (platform.name() if platform else "AI")
210
- print(f"ℹ️ 正在使用{model_display_name}生成提交消息...")
170
+ model_display_name = model_name or (
171
+ platform.name() if platform else "AI"
172
+ )
173
+ PrettyOutput.auto_print(
174
+ f"ℹ️ 正在使用{model_display_name}生成提交消息..."
175
+ )
211
176
 
212
177
  # 准备提示信息
213
178
  custom_prompt = get_git_commit_prompt()
@@ -260,7 +225,7 @@ commit信息
260
225
 
261
226
  if is_large_content:
262
227
  if not platform.support_upload_files():
263
- print("❌ 差异文件太大,无法处理")
228
+ PrettyOutput.auto_print("❌ 差异文件太大,无法处理")
264
229
  return {
265
230
  "success": False,
266
231
  "stdout": "",
@@ -279,7 +244,7 @@ commit信息
279
244
  if upload_success:
280
245
  pass
281
246
  else:
282
- print("❌ 上传代码差异文件失败")
247
+ PrettyOutput.auto_print("❌ 上传代码差异文件失败")
283
248
  return {
284
249
  "success": False,
285
250
  "stdout": "",
@@ -378,9 +343,17 @@ commit信息
378
343
  try:
379
344
  os.unlink(temp_diff_file_path)
380
345
  except Exception as e:
381
- print(f"⚠️ 无法删除临时文件: {str(e)}")
382
-
383
- PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
346
+ PrettyOutput.auto_print(f"⚠️ 无法删除临时文件: {str(e)}")
347
+
348
+ self.console.print(
349
+ Panel(
350
+ f"[bold green]✅ 提交成功[/bold green]\n\n"
351
+ f"[bold]提交哈希:[/bold] {commit_hash}\n"
352
+ f"[bold]提交消息:[/bold]\n{commit_message}",
353
+ title="Git Commit Result",
354
+ border_style="green",
355
+ )
356
+ )
384
357
 
385
358
  return {
386
359
  "success": True,
@@ -391,7 +364,13 @@ commit信息
391
364
  "stderr": "",
392
365
  }
393
366
  except Exception as e:
394
- print(f"❌ 提交失败: {str(e)}")
367
+ self.console.print(
368
+ Panel(
369
+ f"[bold red]❌ 提交失败[/bold red]\n\n{str(e)}",
370
+ title="Git Commit Error",
371
+ border_style="red",
372
+ )
373
+ )
395
374
  return {
396
375
  "success": False,
397
376
  "stdout": "",
@@ -415,7 +394,6 @@ def cli(
415
394
  "--suffix",
416
395
  help="提交信息后缀(用换行分隔)",
417
396
  ),
418
-
419
397
  model_group: Optional[str] = typer.Option(
420
398
  None, "-g", "--llm-group", help="使用的模型组,覆盖配置文件中的设置"
421
399
  ),
@@ -427,7 +405,6 @@ def cli(
427
405
  "root_dir": root_dir,
428
406
  "prefix": prefix,
429
407
  "suffix": suffix,
430
-
431
408
  "model_group": model_group,
432
409
  }
433
410
  )
@@ -1,6 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
- from abc import ABC, abstractmethod
3
- from typing import Any, Dict, List
2
+ from abc import ABC
3
+ from abc import abstractmethod
4
+ from typing import Any
5
+ from typing import Dict
6
+ from typing import List
4
7
 
5
8
 
6
9
  class McpClient(ABC):
@@ -2,12 +2,20 @@
2
2
  import json
3
3
  import threading
4
4
  import time
5
- from typing import Any, Callable, Dict, List, Optional
6
- from urllib.parse import parse_qs, urlencode, urljoin
7
-
8
- import requests # type: ignore[import-untyped]
5
+ from typing import Any
6
+ from typing import Callable
7
+ from typing import Dict
8
+ from typing import List
9
+ from typing import Optional
10
+ from typing import cast
11
+ from urllib.parse import parse_qs
12
+ from urllib.parse import urlencode
13
+ from urllib.parse import urljoin
14
+
15
+ import requests
9
16
 
10
17
  from jarvis.jarvis_mcp import McpClient
18
+ from jarvis.jarvis_utils.output import PrettyOutput
11
19
 
12
20
 
13
21
  class SSEMcpClient(McpClient):
@@ -49,12 +57,12 @@ class SSEMcpClient(McpClient):
49
57
  self.sse_thread: Optional[threading.Thread] = None
50
58
  self.messages_endpoint: Optional[str] = None
51
59
  self.session_id: Optional[str] = None
52
- self.pending_requests: Dict[str, threading.Event] = (
53
- {}
54
- ) # 存储等待响应的请求 {id: Event}
55
- self.request_results: Dict[str, Dict[str, Any]] = (
56
- {}
57
- ) # 存储请求结果 {id: result}
60
+ self.pending_requests: Dict[
61
+ str, threading.Event
62
+ ] = {} # 存储等待响应的请求 {id: Event}
63
+ self.request_results: Dict[
64
+ str, Dict[str, Any]
65
+ ] = {} # 存储请求结果 {id: result}
58
66
  self.notification_handlers: Dict[str, List[Callable]] = {}
59
67
  self.event_lock = threading.Lock()
60
68
  self.request_id_counter = 0
@@ -77,10 +85,12 @@ class SSEMcpClient(McpClient):
77
85
 
78
86
  if not self.messages_endpoint:
79
87
  self.messages_endpoint = "/messages" # 默认端点
80
- print(f"⚠️ 未获取到消息端点,使用默认值: {self.messages_endpoint}")
88
+ PrettyOutput.auto_print(
89
+ f"⚠️ 未获取到消息端点,使用默认值: {self.messages_endpoint}"
90
+ )
81
91
 
82
92
  if not self.session_id:
83
- print("⚠️ 未获取到会话ID")
93
+ PrettyOutput.auto_print("⚠️ 未获取到会话ID")
84
94
 
85
95
  # 发送初始化请求
86
96
  response = self._send_request(
@@ -103,7 +113,7 @@ class SSEMcpClient(McpClient):
103
113
  self._send_notification("notifications/initialized", {})
104
114
 
105
115
  except Exception as e:
106
- print(f"❌ MCP初始化失败: {str(e)}")
116
+ PrettyOutput.auto_print(f"❌ MCP初始化失败: {str(e)}")
107
117
  raise
108
118
 
109
119
  def _start_sse_connection(self) -> None:
@@ -134,7 +144,7 @@ class SSEMcpClient(McpClient):
134
144
  self.sse_thread.start()
135
145
 
136
146
  except Exception as e:
137
- print(f"❌ SSE连接失败: {str(e)}")
147
+ PrettyOutput.auto_print(f"❌ SSE连接失败: {str(e)}")
138
148
  raise
139
149
 
140
150
  def _process_sse_events(self) -> None:
@@ -162,7 +172,7 @@ class SSEMcpClient(McpClient):
162
172
  if "session_id" in query_params:
163
173
  self.session_id = query_params["session_id"][0]
164
174
  except Exception as e:
165
- print(f"⚠️ 解析消息端点或会话ID失败: {e}")
175
+ PrettyOutput.auto_print(f"⚠️ 解析消息端点或会话ID失败: {e}")
166
176
  else:
167
177
  buffer += data
168
178
  elif line.startswith(":"): # 忽略注释行
@@ -178,10 +188,10 @@ class SSEMcpClient(McpClient):
178
188
  try:
179
189
  self._handle_sse_event(buffer)
180
190
  except Exception as e:
181
- print(f"❌ 处理SSE事件出错: {e}")
191
+ PrettyOutput.auto_print(f"❌ 处理SSE事件出错: {e}")
182
192
  buffer = ""
183
193
 
184
- print("⚠️ SSE连接已关闭")
194
+ PrettyOutput.auto_print("⚠️ SSE连接已关闭")
185
195
 
186
196
  def _handle_sse_event(self, data: str) -> None:
187
197
  """处理单个SSE事件数据"""
@@ -211,10 +221,10 @@ class SSEMcpClient(McpClient):
211
221
  except Exception as e:
212
222
  error_lines.append(f"处理通知时出错 ({method}): {e}")
213
223
  if error_lines:
214
- joined_errors = '\n'.join(error_lines)
215
- print(f"❌ {joined_errors}")
224
+ joined_errors = "\n".join(error_lines)
225
+ PrettyOutput.auto_print(f"❌ {joined_errors}")
216
226
  except Exception:
217
- print(f"⚠️ 无法解析SSE事件: {data}")
227
+ PrettyOutput.auto_print(f"⚠️ 无法解析SSE事件: {data}")
218
228
 
219
229
  def register_notification_handler(self, method: str, handler: Callable) -> None:
220
230
  """注册通知处理器
@@ -334,7 +344,7 @@ class SSEMcpClient(McpClient):
334
344
  self.pending_requests.pop(req_id, None)
335
345
  self.request_results.pop(req_id, None)
336
346
 
337
- print(f"❌ 发送请求失败: {str(e)}")
347
+ PrettyOutput.auto_print(f"❌ 发送请求失败: {str(e)}")
338
348
  raise
339
349
 
340
350
  def _send_notification(self, method: str, params: Dict[str, Any]) -> None:
@@ -389,7 +399,7 @@ class SSEMcpClient(McpClient):
389
399
  post_response.raise_for_status()
390
400
 
391
401
  except Exception as e:
392
- print(f"❌ 发送通知失败: {str(e)}")
402
+ PrettyOutput.auto_print(f"❌ 发送通知失败: {str(e)}")
393
403
  raise
394
404
 
395
405
  def get_tool_list(self) -> List[Dict[str, Any]]:
@@ -432,10 +442,10 @@ class SSEMcpClient(McpClient):
432
442
  else:
433
443
  error_msg += ": 未知错误"
434
444
 
435
- print(f"❌ {error_msg}")
445
+ PrettyOutput.auto_print(f"❌ {error_msg}")
436
446
  return []
437
447
  except Exception as e:
438
- print(f"❌ 获取工具列表失败: {str(e)}")
448
+ PrettyOutput.auto_print(f"❌ 获取工具列表失败: {str(e)}")
439
449
  return []
440
450
 
441
451
  def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
@@ -474,7 +484,7 @@ class SSEMcpClient(McpClient):
474
484
  "stderr": response.get("error", "Unknown error"),
475
485
  }
476
486
  except Exception as e:
477
- print(f"❌ 执行工具失败: {str(e)}")
487
+ PrettyOutput.auto_print(f"❌ 执行工具失败: {str(e)}")
478
488
  return {"success": False, "stdout": "", "stderr": str(e)}
479
489
 
480
490
  def get_resource_list(self) -> List[Dict[str, Any]]:
@@ -490,17 +500,17 @@ class SSEMcpClient(McpClient):
490
500
  try:
491
501
  response = self._send_request("resources/list", {})
492
502
  if "result" in response and "resources" in response["result"]:
493
- return response["result"]["resources"]
503
+ return cast(List[Dict[str, Any]], response["result"]["resources"])
494
504
  else:
495
505
  error_msg = "获取资源列表失败"
496
506
  if "error" in response:
497
507
  error_msg += f": {response['error']}"
498
508
  else:
499
509
  error_msg += ": 未知错误"
500
- print(f"❌ {error_msg}")
510
+ PrettyOutput.auto_print(f"❌ {error_msg}")
501
511
  return []
502
512
  except Exception as e:
503
- print(f"❌ 获取资源列表失败: {str(e)}")
513
+ PrettyOutput.auto_print(f"❌ 获取资源列表失败: {str(e)}")
504
514
  return []
505
515
 
506
516
  def get_resource(self, uri: str) -> Dict[str, Any]:
@@ -541,11 +551,11 @@ class SSEMcpClient(McpClient):
541
551
  error_msg += f": {response['error']}"
542
552
  else:
543
553
  error_msg += ": 未知错误"
544
- print(f"❌ {error_msg}")
554
+ PrettyOutput.auto_print(f"❌ {error_msg}")
545
555
  return {"success": False, "stdout": "", "stderr": error_msg}
546
556
  except Exception as e:
547
557
  error_msg = f"获取资源内容失败: {str(e)}"
548
- print(f"❌ {error_msg}")
558
+ PrettyOutput.auto_print(f"❌ {error_msg}")
549
559
  return {"success": False, "stdout": "", "stderr": error_msg}
550
560
 
551
561
  def __del__(self):
@@ -2,9 +2,14 @@
2
2
  import json
3
3
  import os
4
4
  import subprocess
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any
6
+ from typing import Dict
7
+ from typing import List
8
+ from typing import Optional
9
+ from typing import cast
6
10
 
7
11
  from jarvis.jarvis_mcp import McpClient
12
+ from jarvis.jarvis_utils.output import PrettyOutput
8
13
 
9
14
 
10
15
  class StdioMcpClient(McpClient):
@@ -49,7 +54,7 @@ class StdioMcpClient(McpClient):
49
54
  )
50
55
 
51
56
  except Exception as e:
52
- print(f"❌ 启动MCP进程失败: {str(e)}")
57
+ PrettyOutput.auto_print(f"❌ 启动MCP进程失败: {str(e)}")
53
58
  raise
54
59
 
55
60
  def _initialize(self) -> None:
@@ -78,7 +83,7 @@ class StdioMcpClient(McpClient):
78
83
  self._send_notification("notifications/initialized", {})
79
84
 
80
85
  except Exception as e:
81
- print(f"❌ MCP初始化失败: {str(e)}")
86
+ PrettyOutput.auto_print(f"❌ MCP初始化失败: {str(e)}")
82
87
  raise
83
88
 
84
89
  def _send_request(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -99,15 +104,17 @@ class StdioMcpClient(McpClient):
99
104
  request = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
100
105
 
101
106
  # 发送请求
102
- self.process.stdin.write(json.dumps(request) + "\n") # type: ignore
103
- self.process.stdin.flush() # type: ignore
107
+ assert self.process.stdin is not None
108
+ assert self.process.stdout is not None
109
+ self.process.stdin.write(json.dumps(request) + "\n")
110
+ self.process.stdin.flush()
104
111
 
105
112
  # 读取响应
106
- response = self.process.stdout.readline() # type: ignore
107
- return json.loads(response)
113
+ response = self.process.stdout.readline()
114
+ return cast(Dict[str, Any], json.loads(response))
108
115
 
109
116
  except Exception as e:
110
- print(f"❌ 发送请求失败: {str(e)}")
117
+ PrettyOutput.auto_print(f"❌ 发送请求失败: {str(e)}")
111
118
  raise
112
119
 
113
120
  def _send_notification(self, method: str, params: Dict[str, Any]) -> None:
@@ -124,11 +131,12 @@ class StdioMcpClient(McpClient):
124
131
  # 构建通知
125
132
  notification = {"jsonrpc": "2.0", "method": method, "params": params}
126
133
  # 发送通知
127
- self.process.stdin.write(json.dumps(notification) + "\n") # type: ignore
128
- self.process.stdin.flush() # type: ignore
134
+ assert self.process.stdin is not None
135
+ self.process.stdin.write(json.dumps(notification) + "\n")
136
+ self.process.stdin.flush()
129
137
 
130
138
  except Exception as e:
131
- print(f"❌ 发送通知失败: {str(e)}")
139
+ PrettyOutput.auto_print(f"❌ 发送通知失败: {str(e)}")
132
140
  raise
133
141
 
134
142
  def get_tool_list(self) -> List[Dict[str, Any]]:
@@ -171,10 +179,10 @@ class StdioMcpClient(McpClient):
171
179
  else:
172
180
  error_msg += ": 未知错误"
173
181
 
174
- print(f"❌ {error_msg}")
182
+ PrettyOutput.auto_print(f"❌ {error_msg}")
175
183
  return []
176
184
  except Exception as e:
177
- print(f"❌ 获取工具列表失败: {str(e)}")
185
+ PrettyOutput.auto_print(f"❌ 获取工具列表失败: {str(e)}")
178
186
  return []
179
187
 
180
188
  def execute(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
@@ -213,7 +221,7 @@ class StdioMcpClient(McpClient):
213
221
  "stderr": response.get("error", "Unknown error"),
214
222
  }
215
223
  except Exception as e:
216
- print(f"❌ 执行工具失败: {str(e)}")
224
+ PrettyOutput.auto_print(f"❌ 执行工具失败: {str(e)}")
217
225
  return {"success": False, "stdout": "", "stderr": str(e)}
218
226
 
219
227
  def get_resource_list(self) -> List[Dict[str, Any]]:
@@ -229,17 +237,17 @@ class StdioMcpClient(McpClient):
229
237
  try:
230
238
  response = self._send_request("resources/list", {})
231
239
  if "result" in response and "resources" in response["result"]:
232
- return response["result"]["resources"]
240
+ return cast(List[Dict[str, Any]], response["result"]["resources"])
233
241
  else:
234
242
  error_msg = "获取资源列表失败"
235
243
  if "error" in response:
236
244
  error_msg += f": {response['error']}"
237
245
  else:
238
246
  error_msg += ": 未知错误"
239
- print(f"❌ {error_msg}")
247
+ PrettyOutput.auto_print(f"❌ {error_msg}")
240
248
  return []
241
249
  except Exception as e:
242
- print(f"❌ 获取资源列表失败: {str(e)}")
250
+ PrettyOutput.auto_print(f"❌ 获取资源列表失败: {str(e)}")
243
251
  return []
244
252
 
245
253
  def get_resource(self, uri: str) -> Dict[str, Any]:
@@ -280,11 +288,11 @@ class StdioMcpClient(McpClient):
280
288
  error_msg += f": {response['error']}"
281
289
  else:
282
290
  error_msg += ": 未知错误"
283
- print(f"❌ {error_msg}")
291
+ PrettyOutput.auto_print(f"❌ {error_msg}")
284
292
  return {"success": False, "stdout": "", "stderr": error_msg}
285
293
  except Exception as e:
286
294
  error_msg = f"获取资源内容失败: {str(e)}"
287
- print(f"❌ {error_msg}")
295
+ PrettyOutput.auto_print(f"❌ {error_msg}")
288
296
  return {"success": False, "stdout": "", "stderr": error_msg}
289
297
 
290
298
  def __del__(self):