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
@@ -0,0 +1,233 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 文件变更后处理工具配置模块
6
+
7
+ 提供文件变更后处理工具配置和命令生成功能(如格式化、自动修复等)。
8
+ """
9
+
10
+ import os
11
+ from typing import Dict
12
+ from typing import List
13
+ from typing import Optional
14
+ from typing import Tuple
15
+
16
+ import yaml
17
+
18
+ from jarvis.jarvis_utils.config import get_data_dir
19
+
20
+ # 文件变更后处理工具命令模板映射(文件扩展名/文件名 -> 命令模板列表)
21
+ # 占位符说明:
22
+ # - {file_path}: 单个文件的完整路径
23
+ # - {file_name}: 文件名(不含路径)
24
+ AFTER_CHANGE_COMMAND_TEMPLATES_BY_FILE: Dict[str, List[str]] = {
25
+ # Python
26
+ ".py": ["ruff format {file_path}"],
27
+ ".pyw": ["ruff format {file_path}"],
28
+ ".pyi": ["ruff format {file_path}"],
29
+ ".pyx": ["ruff format {file_path}"],
30
+ ".pxd": ["ruff format {file_path}"],
31
+ # JavaScript/TypeScript
32
+ ".js": ["prettier --write {file_path}"],
33
+ ".mjs": ["prettier --write {file_path}"],
34
+ ".cjs": ["prettier --write {file_path}"],
35
+ ".jsx": ["prettier --write {file_path}"],
36
+ ".ts": ["prettier --write {file_path}"],
37
+ ".tsx": ["prettier --write {file_path}"],
38
+ ".cts": ["prettier --write {file_path}"],
39
+ ".mts": ["prettier --write {file_path}"],
40
+ # Rust
41
+ ".rs": ["rustfmt {file_path}"],
42
+ # Go
43
+ ".go": ["gofmt -w {file_path}"],
44
+ # Java
45
+ ".java": ["google-java-format -i {file_path}"],
46
+ # C/C++
47
+ ".c": ["clang-format -i {file_path}"],
48
+ ".cpp": ["clang-format -i {file_path}"],
49
+ ".cc": ["clang-format -i {file_path}"],
50
+ ".cxx": ["clang-format -i {file_path}"],
51
+ ".h": ["clang-format -i {file_path}"],
52
+ ".hpp": ["clang-format -i {file_path}"],
53
+ ".hxx": ["clang-format -i {file_path}"],
54
+ ".inl": ["clang-format -i {file_path}"],
55
+ ".ipp": ["clang-format -i {file_path}"],
56
+ # HTML/CSS
57
+ ".html": ["prettier --write {file_path}"],
58
+ ".htm": ["prettier --write {file_path}"],
59
+ ".xhtml": ["prettier --write {file_path}"],
60
+ ".css": ["prettier --write {file_path}"],
61
+ ".scss": ["prettier --write {file_path}"],
62
+ ".sass": ["prettier --write {file_path}"],
63
+ ".less": ["prettier --write {file_path}"],
64
+ # JSON/YAML
65
+ ".json": ["prettier --write {file_path}"],
66
+ ".jsonl": ["prettier --write {file_path}"],
67
+ ".json5": ["prettier --write {file_path}"],
68
+ ".yaml": ["prettier --write {file_path}"],
69
+ ".yml": ["prettier --write {file_path}"],
70
+ # Markdown
71
+ ".md": ["prettier --write {file_path}"],
72
+ ".markdown": ["prettier --write {file_path}"],
73
+ # SQL
74
+ ".sql": ["sqlfluff format {file_path}"],
75
+ # Shell/Bash
76
+ ".sh": ["shfmt -w {file_path}"],
77
+ ".bash": ["shfmt -w {file_path}"],
78
+ # XML
79
+ ".xml": [
80
+ "xmllint --format {file_path} > {file_path}.tmp && mv {file_path}.tmp {file_path}"
81
+ ],
82
+ ".xsd": [
83
+ "xmllint --format {file_path} > {file_path}.tmp && mv {file_path}.tmp {file_path}"
84
+ ],
85
+ ".dtd": [
86
+ "xmllint --format {file_path} > {file_path}.tmp && mv {file_path}.tmp {file_path}"
87
+ ],
88
+ }
89
+
90
+
91
+ def load_after_change_tools_config() -> Dict[str, List[str]]:
92
+ """从yaml文件加载全局文件变更后处理工具配置
93
+
94
+ Returns:
95
+ Dict[str, List[str]]: 文件扩展名/文件名 -> 命令模板列表
96
+ """
97
+ config_path = os.path.join(get_data_dir(), "after_change_tools.yaml")
98
+ if not os.path.exists(config_path):
99
+ return {}
100
+
101
+ with open(config_path, "r") as f:
102
+ config = yaml.safe_load(f) or {}
103
+ result = {}
104
+ for k, v in config.items():
105
+ k_lower = k.lower()
106
+ # 支持格式: ["template1", "template2"] 或 [("tool1", "template1"), ("tool2", "template2")]
107
+ if isinstance(v, list) and v:
108
+ if isinstance(v[0], str):
109
+ # 新格式:直接是命令模板列表
110
+ result[k_lower] = v
111
+ elif isinstance(v[0], (list, tuple)) and len(v[0]) == 2:
112
+ # 旧格式:需要提取模板
113
+ result[k_lower] = [template for _, template in v]
114
+ return result
115
+
116
+
117
+ def load_project_after_change_tools_config(project_root: str) -> Dict[str, List[str]]:
118
+ """从项目根目录加载文件变更后处理工具配置
119
+
120
+ Args:
121
+ project_root: 项目根目录
122
+
123
+ Returns:
124
+ Dict[str, List[str]]: 文件扩展名/文件名 -> 命令模板列表
125
+ """
126
+ project_config_path = os.path.join(
127
+ project_root, ".jarvis", "after_change_tools.yaml"
128
+ )
129
+ if not os.path.exists(project_config_path):
130
+ return {}
131
+
132
+ with open(project_config_path, "r") as f:
133
+ config = yaml.safe_load(f) or {}
134
+ result = {}
135
+ for k, v in config.items():
136
+ k_lower = k.lower()
137
+ # 支持格式: ["template1", "template2"] 或 [("tool1", "template1"), ("tool2", "template2")]
138
+ if isinstance(v, list) and v:
139
+ if isinstance(v[0], str):
140
+ # 新格式:直接是命令模板列表
141
+ result[k_lower] = v
142
+ elif isinstance(v[0], (list, tuple)) and len(v[0]) == 2:
143
+ # 旧格式:需要提取模板
144
+ result[k_lower] = [template for _, template in v]
145
+ return result
146
+
147
+
148
+ # 合并默认配置和全局yaml配置(项目级配置在运行时动态加载)
149
+ AFTER_CHANGE_COMMAND_TEMPLATES_BY_FILE.update(load_after_change_tools_config())
150
+
151
+
152
+ def _format_after_change_command(
153
+ template: str,
154
+ file_path: str,
155
+ project_root: Optional[str] = None,
156
+ ) -> Optional[str]:
157
+ """
158
+ 格式化命令模板(内部函数)
159
+
160
+ Args:
161
+ template: 命令模板字符串
162
+ file_path: 文件路径(相对或绝对路径)
163
+ project_root: 项目根目录(可选,用于处理相对路径)
164
+
165
+ Returns:
166
+ 命令字符串,如果无法生成则返回None
167
+ """
168
+ # 如果是绝对路径,直接使用;否则转换为绝对路径
169
+ if os.path.isabs(file_path):
170
+ abs_file_path = file_path
171
+ elif project_root:
172
+ abs_file_path = os.path.join(project_root, file_path)
173
+ else:
174
+ abs_file_path = os.path.abspath(file_path)
175
+
176
+ # 准备占位符替换字典
177
+ placeholders = {
178
+ "file_path": abs_file_path,
179
+ "file_name": os.path.basename(abs_file_path),
180
+ }
181
+
182
+ # 替换占位符
183
+ try:
184
+ command = template.format(**placeholders)
185
+ except KeyError:
186
+ # 如果模板中有未定义的占位符,返回None
187
+ return None
188
+
189
+ return command
190
+
191
+
192
+ def get_after_change_commands_for_files(
193
+ files: List[str], project_root: Optional[str] = None
194
+ ) -> List[Tuple[str, str]]:
195
+ """
196
+ 获取多个文件的变更后处理命令列表
197
+
198
+ Args:
199
+ files: 文件路径列表
200
+ project_root: 项目根目录(可选),如果提供则加载项目级配置
201
+
202
+ Returns:
203
+ [(file_path, command), ...] 格式的命令列表
204
+ """
205
+ # 加载项目级配置(如果提供项目根目录)
206
+ # 项目级配置会覆盖全局配置
207
+ config = AFTER_CHANGE_COMMAND_TEMPLATES_BY_FILE.copy()
208
+ if project_root:
209
+ project_config = load_project_after_change_tools_config(project_root)
210
+ config.update(project_config) # 项目配置覆盖全局配置
211
+
212
+ commands = []
213
+
214
+ for file_path in files:
215
+ # 从文件扩展名/文件名直接获取命令模板列表
216
+ filename = os.path.basename(file_path)
217
+ filename_lower = filename.lower()
218
+
219
+ # 优先尝试完整文件名匹配
220
+ templates = config.get(filename_lower, [])
221
+
222
+ # 如果文件名匹配失败,再尝试扩展名匹配
223
+ if not templates:
224
+ ext = os.path.splitext(filename)[1]
225
+ if ext:
226
+ templates = config.get(ext.lower(), [])
227
+
228
+ for template in templates:
229
+ command = _format_after_change_command(template, file_path, project_root)
230
+ if command:
231
+ commands.append((file_path, command))
232
+
233
+ return commands
@@ -1,6 +1,3 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
-
4
1
  """
5
2
  构建验证配置管理模块
6
3
 
@@ -8,69 +5,80 @@
8
5
  """
9
6
 
10
7
  import os
11
- import yaml
12
- from typing import Optional, Dict, Any
13
8
  from pathlib import Path
9
+ from typing import Any
10
+
11
+ from jarvis.jarvis_utils.output import PrettyOutput
12
+
13
+ #!/usr/bin/env python3
14
+ # -*- coding: utf-8 -*-
14
15
 
16
+ from typing import Dict
17
+ from typing import Optional
18
+ from typing import cast
19
+
20
+ import yaml
15
21
 
16
22
  CONFIG_FILE_NAME = "build_validation_config.yaml"
17
23
 
18
24
 
19
25
  class BuildValidationConfig:
20
26
  """构建验证配置管理器"""
21
-
27
+
22
28
  def __init__(self, project_root: str):
23
29
  self.project_root = project_root
24
30
  self.config_dir = os.path.join(project_root, ".jarvis")
25
31
  self.config_path = os.path.join(self.config_dir, CONFIG_FILE_NAME)
26
32
  self._config: Optional[Dict[str, Any]] = None
27
-
33
+
28
34
  def _ensure_config_dir(self) -> None:
29
35
  """确保配置目录存在"""
30
36
  if not os.path.exists(self.config_dir):
31
37
  os.makedirs(self.config_dir, exist_ok=True)
32
-
38
+
33
39
  def _load_config(self) -> Dict[str, Any]:
34
40
  """加载配置文件"""
35
41
  if self._config is not None:
36
42
  return self._config
37
-
43
+
38
44
  if not os.path.exists(self.config_path):
39
45
  self._config = {}
40
46
  return self._config
41
-
47
+
42
48
  try:
43
49
  with open(self.config_path, "r", encoding="utf-8") as f:
44
50
  self._config = yaml.safe_load(f) or {}
45
51
  return self._config
46
52
  except Exception as e:
47
53
  # 配置文件损坏时,返回空配置
48
- print(f"⚠️ 加载构建验证配置失败: {e},使用默认配置")
54
+ PrettyOutput.auto_print(f"⚠️ 加载构建验证配置失败: {e},使用默认配置")
49
55
  self._config = {}
50
56
  return self._config
51
-
57
+
52
58
  def _save_config(self) -> bool:
53
59
  """保存配置文件"""
54
60
  try:
55
61
  self._ensure_config_dir()
56
62
  with open(self.config_path, "w", encoding="utf-8") as f:
57
- yaml.safe_dump(self._config, f, allow_unicode=True, default_flow_style=False)
63
+ yaml.safe_dump(
64
+ self._config, f, allow_unicode=True, default_flow_style=False
65
+ )
58
66
  return True
59
67
  except Exception as e:
60
- print(f"❌ 保存构建验证配置失败: {e}")
68
+ PrettyOutput.auto_print(f"❌ 保存构建验证配置失败: {e}")
61
69
  return False
62
-
70
+
63
71
  def is_build_validation_disabled(self) -> bool:
64
72
  """检查是否已禁用构建验证"""
65
73
  config = self._load_config()
66
- return config.get("disable_build_validation", False)
67
-
74
+ return cast(bool, config.get("disable_build_validation", False))
75
+
68
76
  def disable_build_validation(self, reason: Optional[str] = None) -> bool:
69
77
  """禁用构建验证
70
-
78
+
71
79
  Args:
72
80
  reason: 禁用原因(可选)
73
-
81
+
74
82
  Returns:
75
83
  bool: 是否成功保存配置
76
84
  """
@@ -81,7 +89,7 @@ class BuildValidationConfig:
81
89
  config["disabled_at"] = str(Path(self.project_root).resolve())
82
90
  self._config = config
83
91
  return self._save_config()
84
-
92
+
85
93
  def enable_build_validation(self) -> bool:
86
94
  """重新启用构建验证"""
87
95
  config = self._load_config()
@@ -89,39 +97,39 @@ class BuildValidationConfig:
89
97
  # 保留历史信息,但清除禁用标志
90
98
  self._config = config
91
99
  return self._save_config()
92
-
100
+
93
101
  def get_disable_reason(self) -> Optional[str]:
94
102
  """获取禁用原因"""
95
103
  config = self._load_config()
96
104
  return config.get("disable_reason")
97
-
105
+
98
106
  def has_been_asked(self) -> bool:
99
107
  """检查是否已经询问过用户"""
100
108
  config = self._load_config()
101
- return config.get("has_been_asked", False)
102
-
109
+ return cast(bool, config.get("has_been_asked", False))
110
+
103
111
  def mark_as_asked(self) -> bool:
104
112
  """标记为已询问"""
105
113
  config = self._load_config()
106
114
  config["has_been_asked"] = True
107
115
  self._config = config
108
116
  return self._save_config()
109
-
117
+
110
118
  def get_selected_build_system(self) -> Optional[str]:
111
119
  """获取用户选择的构建系统
112
-
120
+
113
121
  Returns:
114
122
  构建系统名称(如 "rust", "python"),如果未选择则返回None
115
123
  """
116
124
  config = self._load_config()
117
125
  return config.get("selected_build_system")
118
-
126
+
119
127
  def set_selected_build_system(self, build_system: str) -> bool:
120
128
  """保存用户选择的构建系统
121
-
129
+
122
130
  Args:
123
131
  build_system: 构建系统名称(如 "rust", "python")
124
-
132
+
125
133
  Returns:
126
134
  bool: 是否成功保存配置
127
135
  """
@@ -129,4 +137,3 @@ class BuildValidationConfig:
129
137
  config["selected_build_system"] = build_system
130
138
  self._config = config
131
139
  return self._save_config()
132
-
@@ -0,0 +1,68 @@
1
+ # -*- coding: utf-8 -*-
2
+ """CodeAgent 内置规则模块
3
+
4
+ 提供一些优秀的开发实践规则,如 TDD、代码审查、重构等。
5
+ """
6
+
7
+ from pathlib import Path
8
+
9
+ # 内置规则字典:规则名称 -> 规则内容
10
+ # 此字典将在模块加载时通过 _load_builtin_rules() 函数动态填充
11
+ BUILTIN_RULES: dict[str, str] = {}
12
+
13
+
14
+ def _load_rules_from_directory(directory: Path) -> None:
15
+ """从指定目录加载规则文件
16
+
17
+ 参数:
18
+ directory: 规则文件所在目录
19
+ """
20
+ if not directory.exists():
21
+ return
22
+
23
+ for rule_file in directory.glob("*.md"):
24
+ rule_name = rule_file.stem # 去掉 .md 后缀
25
+ try:
26
+ with open(rule_file, "r", encoding="utf-8") as f:
27
+ rule_content = f.read().strip()
28
+ if rule_content:
29
+ BUILTIN_RULES[rule_name] = rule_content
30
+ except Exception:
31
+ # 忽略加载失败的文件,不影响其他规则
32
+ continue
33
+
34
+
35
+ def _load_builtin_rules() -> None:
36
+ """加载所有内置规则"""
37
+ rules_dir = Path(__file__).parent
38
+
39
+ # 加载通用规则(rules 目录)
40
+ _load_rules_from_directory(rules_dir / "rules")
41
+
42
+ # 加载测试规则(test_rules 目录)
43
+ _load_rules_from_directory(rules_dir / "test_rules")
44
+
45
+
46
+ # 在模块加载时自动加载所有规则
47
+ _load_builtin_rules()
48
+
49
+
50
+ def get_builtin_rule(rule_name: str) -> str | None:
51
+ """获取内置规则
52
+
53
+ 参数:
54
+ rule_name: 规则名称(不区分大小写)
55
+
56
+ 返回:
57
+ str: 规则内容,如果未找到则返回 None
58
+ """
59
+ return BUILTIN_RULES.get(rule_name.lower())
60
+
61
+
62
+ def list_builtin_rules() -> list[str]:
63
+ """列出所有可用的内置规则名称
64
+
65
+ 返回:
66
+ list[str]: 规则名称列表
67
+ """
68
+ return list(BUILTIN_RULES.keys())