jarvis-ai-assistant 0.1.162__tar.gz → 0.1.164__tar.gz

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.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (107) hide show
  1. {jarvis_ai_assistant-0.1.162/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.164}/PKG-INFO +13 -2
  2. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/README.md +12 -1
  3. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/pyproject.toml +1 -1
  4. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/setup.py +1 -1
  5. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/__init__.py +1 -1
  6. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/__init__.py +23 -4
  7. jarvis_ai_assistant-0.1.164/src/jarvis/jarvis_agent/output_handler.py +47 -0
  8. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_agent/code_agent.py +123 -160
  9. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_dev/main.py +6 -0
  10. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_git_details/main.py +2 -1
  11. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_multi_agent/__init__.py +2 -3
  12. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/base.py +0 -2
  13. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/yuanbao.py +1 -0
  14. jarvis_ai_assistant-0.1.164/src/jarvis/jarvis_tools/edit_file.py +279 -0
  15. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/file_operation.py +0 -2
  16. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/read_code.py +0 -2
  17. jarvis_ai_assistant-0.1.164/src/jarvis/jarvis_tools/rewrite_file.py +183 -0
  18. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/git_utils.py +144 -0
  19. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/globals.py +0 -29
  20. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/methodology.py +15 -9
  21. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164/src/jarvis_ai_assistant.egg-info}/PKG-INFO +13 -2
  22. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +1 -0
  23. jarvis_ai_assistant-0.1.162/src/jarvis/jarvis_agent/output_handler.py +0 -23
  24. jarvis_ai_assistant-0.1.162/src/jarvis/jarvis_tools/edit_file.py +0 -569
  25. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/LICENSE +0 -0
  26. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/MANIFEST.in +0 -0
  27. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/setup.cfg +0 -0
  28. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  29. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/file_input_handler.py +0 -0
  30. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/jarvis.py +0 -0
  31. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/main.py +0 -0
  32. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_agent/shell_input_handler.py +0 -0
  33. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  34. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  35. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  36. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  37. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  38. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  39. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  40. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  41. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  42. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  43. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  44. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  45. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  46. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  47. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  48. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  49. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  50. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  51. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  52. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  53. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  54. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_code_analysis/code_review.py +0 -0
  55. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_git_details/__init__.py +0 -0
  56. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  57. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_git_squash/main.py +0 -0
  58. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
  59. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/base.py +0 -0
  60. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/cpp.py +0 -0
  61. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/go.py +0 -0
  62. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/python.py +0 -0
  63. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/registry.py +0 -0
  64. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_lsp/rust.py +0 -0
  65. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  66. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
  67. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
  68. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_methodology/main.py +0 -0
  69. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_multi_agent/main.py +0 -0
  70. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/__init__.py +0 -0
  71. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/human.py +0 -0
  72. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/kimi.py +0 -0
  73. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform/registry.py +0 -0
  74. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  75. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  76. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  77. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  78. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/__init__.py +0 -0
  79. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/ask_codebase.py +0 -0
  80. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  81. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/base.py +0 -0
  82. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/chdir.py +0 -0
  83. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/code_plan.py +0 -0
  84. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/create_code_agent.py +0 -0
  85. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
  86. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/execute_script.py +0 -0
  87. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
  88. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/find_methodology.py +0 -0
  89. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
  90. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/methodology.py +0 -0
  91. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  92. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/registry.py +0 -0
  93. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/search_web.py +0 -0
  94. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
  95. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/__init__.py +0 -0
  96. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
  97. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/config.py +0 -0
  98. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/embedding.py +0 -0
  99. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  100. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/input.py +0 -0
  101. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/output.py +0 -0
  102. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/tag.py +0 -0
  103. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis/jarvis_utils/utils.py +0 -0
  104. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  105. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  106. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  107. {jarvis_ai_assistant-0.1.162 → jarvis_ai_assistant-0.1.164}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.162
3
+ Version: 0.1.164
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -77,6 +77,7 @@ Dynamic: requires-python
77
77
 
78
78
  *您的智能开发和系统交互助手*
79
79
 
80
+ [核心特色](#core-features) •
80
81
  [视频介绍](#video-introduction) •
81
82
  [快速开始](#quick-start) •
82
83
  [配置说明](#configuration) •
@@ -89,6 +90,15 @@ Dynamic: requires-python
89
90
 
90
91
  ---
91
92
 
93
+ ## 🌟 核心特色 <a id="core-features"></a>
94
+
95
+ - 🆓 零成本接入:无缝集成元宝、Kimi等优质模型,无需支付API费用,同时保留强大的文件处理、搜索和推理能力
96
+ - 🛠️ 工具驱动:内置丰富工具集,涵盖脚本执行、代码开发、网页搜索、终端操作等核心功能
97
+ - 👥 人机协作:支持实时交互,用户可随时介入指导,确保AI行为符合预期
98
+ - 🔌 高度可扩展:支持自定义工具和平台,轻松集成MCP协议
99
+ - 📈 智能进化:内置方法论系统,持续学习优化,越用越智能
100
+
101
+
92
102
  ## 📺 视频介绍<a id="video-introduction"></a>
93
103
 
94
104
  [![视频介绍](docs/images/intro.png)](https://player.bilibili.com/player.html?isOutside=true&aid=114306578382907&bvid=BV1x2dAYeEpM&cid=29314583629&p=1)
@@ -205,7 +215,6 @@ jarvis-methodology --help
205
215
  | `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
206
216
  | `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
207
217
  | `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
208
- | `JARVIS_CODE_EMBEDDING_MODEL_SIZE` | small | 代码嵌入模型大小,可选值:small、large |
209
218
 
210
219
 
211
220
  ---
@@ -216,6 +225,8 @@ jarvis-methodology --help
216
225
  | ask_codebase | 智能代码库查询和分析,用于定位功能所在文件和理解单点实现,适合查询特定功能位置和实现原理 |
217
226
  | ask_user | 交互式用户输入收集 |
218
227
  | chdir | 更改当前工作目录 |
228
+ | rewrite_file | 文件重写工具,用于完全重写或创建文件,提供完整的文件内容替换 |
229
+ | edit_file | 代码编辑工具,用于精确修改文件内容,支持搜索替换方式编辑 |
219
230
  | code_plan | 理解需求并制定详细的代码修改计划,在修改前获取用户确认 |
220
231
  | create_code_agent | 代码开发工具,当需要修改代码时使用 |
221
232
  | create_sub_agent | 创建子代理以处理特定任务,子代理将生成任务总结报告 |
@@ -8,6 +8,7 @@
8
8
 
9
9
  *您的智能开发和系统交互助手*
10
10
 
11
+ [核心特色](#core-features) •
11
12
  [视频介绍](#video-introduction) •
12
13
  [快速开始](#quick-start) •
13
14
  [配置说明](#configuration) •
@@ -20,6 +21,15 @@
20
21
 
21
22
  ---
22
23
 
24
+ ## 🌟 核心特色 <a id="core-features"></a>
25
+
26
+ - 🆓 零成本接入:无缝集成元宝、Kimi等优质模型,无需支付API费用,同时保留强大的文件处理、搜索和推理能力
27
+ - 🛠️ 工具驱动:内置丰富工具集,涵盖脚本执行、代码开发、网页搜索、终端操作等核心功能
28
+ - 👥 人机协作:支持实时交互,用户可随时介入指导,确保AI行为符合预期
29
+ - 🔌 高度可扩展:支持自定义工具和平台,轻松集成MCP协议
30
+ - 📈 智能进化:内置方法论系统,持续学习优化,越用越智能
31
+
32
+
23
33
  ## 📺 视频介绍<a id="video-introduction"></a>
24
34
 
25
35
  [![视频介绍](docs/images/intro.png)](https://player.bilibili.com/player.html?isOutside=true&aid=114306578382907&bvid=BV1x2dAYeEpM&cid=29314583629&p=1)
@@ -136,7 +146,6 @@ jarvis-methodology --help
136
146
  | `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
137
147
  | `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
138
148
  | `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
139
- | `JARVIS_CODE_EMBEDDING_MODEL_SIZE` | small | 代码嵌入模型大小,可选值:small、large |
140
149
 
141
150
 
142
151
  ---
@@ -147,6 +156,8 @@ jarvis-methodology --help
147
156
  | ask_codebase | 智能代码库查询和分析,用于定位功能所在文件和理解单点实现,适合查询特定功能位置和实现原理 |
148
157
  | ask_user | 交互式用户输入收集 |
149
158
  | chdir | 更改当前工作目录 |
159
+ | rewrite_file | 文件重写工具,用于完全重写或创建文件,提供完整的文件内容替换 |
160
+ | edit_file | 代码编辑工具,用于精确修改文件内容,支持搜索替换方式编辑 |
150
161
  | code_plan | 理解需求并制定详细的代码修改计划,在修改前获取用户确认 |
151
162
  | create_code_agent | 代码开发工具,当需要修改代码时使用 |
152
163
  | create_sub_agent | 创建子代理以处理特定任务,子代理将生成任务总结报告 |
@@ -8,7 +8,7 @@ default = true
8
8
 
9
9
  [project]
10
10
  name = "jarvis-ai-assistant"
11
- version = "0.1.162"
11
+ version = "0.1.164"
12
12
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
13
13
  readme = "README.md"
14
14
  authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="jarvis-ai-assistant",
5
- version="0.1.162",
5
+ version="0.1.164",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.162"
3
+ __version__ = "0.1.164"
@@ -2,6 +2,7 @@ import datetime
2
2
  import platform
3
3
  from typing import Any, Callable, List, Optional, Tuple, Union
4
4
 
5
+ from jarvis.jarvis_tools.registry import ToolRegistry
5
6
  from yaspin import yaspin # type: ignore
6
7
 
7
8
  from jarvis.jarvis_agent.output_handler import OutputHandler
@@ -138,6 +139,7 @@ class Agent:
138
139
  summary_prompt: Optional[str] = None,
139
140
  auto_complete: Optional[bool] = None,
140
141
  output_handler: List[OutputHandler] = [],
142
+ use_tools: List[str] = [],
141
143
  input_handler: Optional[List[Callable[[str, Any], Tuple[str, bool]]]] = None,
142
144
  execute_tool_confirm: Optional[bool] = None,
143
145
  need_summary: bool = True,
@@ -180,6 +182,8 @@ class Agent:
180
182
 
181
183
  from jarvis.jarvis_tools.registry import ToolRegistry
182
184
  self.output_handler = output_handler if output_handler else [ToolRegistry()]
185
+ self.set_use_tools(use_tools)
186
+
183
187
  self.multiline_inputer = multiline_inputer if multiline_inputer else get_multiline_input
184
188
 
185
189
  self.prompt = ""
@@ -192,6 +196,7 @@ class Agent:
192
196
 
193
197
  self.tool_call_count = 0
194
198
  self.max_tool_call_count = get_max_tool_call_count()
199
+ self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
195
200
 
196
201
 
197
202
  self.execute_tool_confirm = execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm()
@@ -280,6 +285,13 @@ class Agent:
280
285
  """)
281
286
  self.first = True
282
287
 
288
+ def set_use_tools(self, use_tools):
289
+ for handler in self.output_handler:
290
+ if isinstance(handler, ToolRegistry):
291
+ if use_tools:
292
+ handler.use_tools(use_tools)
293
+ break
294
+
283
295
 
284
296
  def set_addon_prompt(self, addon_prompt: str):
285
297
  """设置附加提示。
@@ -289,6 +301,14 @@ class Agent:
289
301
  """
290
302
  self.addon_prompt = addon_prompt
291
303
 
304
+ def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
305
+ """设置工具调用后回调函数。
306
+
307
+ 参数:
308
+ cb: 回调函数
309
+ """
310
+ self.after_tool_call_cb = cb
311
+
292
312
  def make_default_addon_prompt(self, need_complete: bool) -> str:
293
313
  """生成附加提示。
294
314
 
@@ -357,10 +377,6 @@ class Agent:
357
377
  else:
358
378
  message += f"\n\n{self.make_default_addon_prompt(need_complete)}"
359
379
 
360
- # 在真正调用模型对话前减少文件读取计数
361
- from jarvis.jarvis_utils.globals import decrease_read_file_counts
362
- decrease_read_file_counts()
363
-
364
380
  # 累加对话长度
365
381
  self.conversation_length += get_context_token_count(message)
366
382
 
@@ -657,6 +673,9 @@ arguments:
657
673
  if need_return:
658
674
  return self.prompt
659
675
 
676
+ if self.after_tool_call_cb:
677
+ self.after_tool_call_cb(self)
678
+
660
679
  if self.prompt:
661
680
  continue
662
681
 
@@ -0,0 +1,47 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Tuple
3
+
4
+
5
+ class OutputHandler(ABC):
6
+ @abstractmethod
7
+ def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
8
+ """处理响应数据
9
+
10
+ Args:
11
+ response: 需要处理的响应字符串
12
+ agent: 执行处理的agent实例
13
+
14
+ Returns:
15
+ Tuple[bool, Any]: 返回处理结果元组,第一个元素表示是否处理成功,第二个元素为处理后的数据
16
+ """
17
+ pass
18
+
19
+ @abstractmethod
20
+ def can_handle(self, response: str) -> bool:
21
+ """判断是否能处理给定的响应
22
+
23
+ Args:
24
+ response: 需要判断的响应字符串
25
+
26
+ Returns:
27
+ bool: 返回是否能处理该响应
28
+ """
29
+ pass
30
+
31
+ @abstractmethod
32
+ def prompt(self) -> str:
33
+ """获取处理器的提示信息
34
+
35
+ Returns:
36
+ str: 返回处理器的提示字符串
37
+ """
38
+ pass
39
+
40
+ @abstractmethod
41
+ def name(self) -> str:
42
+ """获取处理器的名称
43
+
44
+ Returns:
45
+ str: 返回处理器的名称字符串
46
+ """
47
+ pass
@@ -10,6 +10,7 @@ import argparse
10
10
  from typing import Any, Dict, Optional, List, Tuple
11
11
 
12
12
  # 忽略yaspin的类型检查
13
+ from jarvis.jarvis_utils.config import is_confirm_before_apply_patch
13
14
  from yaspin import yaspin # type: ignore
14
15
 
15
16
  from jarvis.jarvis_agent import Agent
@@ -22,7 +23,9 @@ from jarvis.jarvis_tools.registry import ToolRegistry
22
23
  from jarvis.jarvis_utils.git_utils import (
23
24
  find_git_root,
24
25
  get_commits_between,
26
+ get_diff,
25
27
  get_latest_commit_hash,
28
+ handle_commit_workflow,
26
29
  has_uncommitted_changes
27
30
  )
28
31
  from jarvis.jarvis_utils.input import get_multiline_input
@@ -52,164 +55,63 @@ class CodeAgent:
52
55
  "chdir",
53
56
  "find_methodology",
54
57
  "edit_file",
58
+ "rewrite_file"
55
59
  ])
56
60
  code_system_prompt = """
57
61
  <code_engineer_guide>
58
- <principles>
62
+ ## 角色定位
63
+ 你是Jarvis系统的代码工程师,一个专业的代码分析和修改助手。你的职责是:
64
+ - 理解用户的代码需求,并提供高质量的实现方案
65
+ - 精确分析项目结构和代码,准确定位需要修改的位置
66
+ - 编写符合项目风格和标准的代码
67
+ - 在修改代码时保持谨慎,确保不破坏现有功能
68
+ - 做出专业的技术决策,减少用户决策负担
69
+
59
70
  ## 核心原则
60
71
  - 自主决策:基于专业判断做出决策,减少用户询问
61
- - 高效精准:一次性提供完整解决方案,避免反复修改
62
- - 修改审慎:修改代码前要三思而后行,充分分析影响范围,尽量做到一次把事情做好
72
+ - 高效精准:提供完整解决方案,避免反复修改
73
+ - 修改审慎:修改前充分分析影响范围,做到一次把事情做好
63
74
  - 工具精通:选择最高效工具路径解决问题
64
- - 严格确认:必须先分析项目结构,确定要修改的文件,禁止虚构已存在的代码
65
- </principles>
66
75
 
67
- <workflow>
68
76
  ## 工作流程
69
-
70
- <step>
71
- ### 1. 项目结构分析
72
- - 第一步必须分析项目结构,识别关键模块和文件
73
- - 结合用户需求,确定需要修改的文件列表
74
- - 优先使用fd命令查找文件,使用execute_script执行
75
- - 明确说明将要修改的文件及其范围
76
- </step>
77
-
78
- <step>
79
- ### 2. 需求分析
80
- - 基于项目结构理解,分析需求意图和实现方案
81
- - 当需求有多种实现方式时,选择影响最小的方案
82
- - 仅当需求显著模糊时才询问用户
83
- </step>
84
-
85
- <step>
86
- ### 3. 代码分析与确认
87
- - 详细分析确定要修改的文件内容
88
- - 明确区分现有代码和需要新建的内容
89
- - 绝对禁止虚构或假设现有代码的实现细节
90
- - 分析顺序:项目结构 → 目标文件 → 相关文件
91
- - 只在必要时扩大分析范围,避免过度分析
92
- - 工具选择:
93
- | 分析需求 | 首选工具 | 备选工具 |
94
- |---------|---------|----------|
95
- | 项目结构 | fd (通过execute_script) | ask_codebase(仅在必要时) |
96
- | 文件内容 | read_code | ask_codebase(仅在必要时) |
97
- | 查找引用 | rg (通过execute_script) | ask_codebase(仅在必要时) |
98
- | 查找定义 | rg (通过execute_script) | ask_codebase(仅在必要时) |
99
- | 函数调用者 | rg (通过execute_script) | ask_codebase(仅在必要时) |
100
- | 函数分析 | read_code + rg | ask_codebase(仅在必要时) |
101
- | 整体分析 | execute_script | ask_codebase(仅在必要时) |
102
- | 代码质量检查 | execute_script | ask_codebase(仅在必要时) |
103
- | 统计代码行数 | loc (通过execute_script) | - |
104
- </step>
105
-
106
- <step>
107
- ### 4. 方案设计
108
- - 确定最小变更方案,保持代码结构
109
- - 变更类型处理:
110
- - 修改现有文件:必须先确认文件存在及其内容
111
- - 创建新文件:可以根据需求创建,但要符合项目结构和风格
112
- - 变更规模处理:
113
- - ≤50行:一次性完成所有修改
114
- - 50-200行:按功能模块分组
115
- - >200行:按功能拆分,但尽量减少提交次数
116
- </step>
117
-
118
- <step>
119
- ### 5. 实施修改
120
- - 遵循"先读后写"原则,在修改已有代码前,必须已经读取了对应文件,如果已经读取过文件,不需要重新读取
121
- - 保持代码风格一致性
122
- - 自动匹配项目现有命名风格
123
- - 允许创建新文件和结构,但不得假设或虚构现有代码
124
- </step>
125
- </workflow>
126
-
127
- <tools>
128
- ## 专用工具简介
129
- 仅在必要时使用以下专用工具:
130
-
131
- - **ask_codebase**: 代码库整体查询,应优先使用fd、rg和read_code组合替代
132
- </tools>
133
-
134
- <shell_commands>
135
- ## Shell命令优先策略
136
-
137
- <category>
138
- ### 优先使用的Shell命令
139
- - **项目结构分析**:
140
- - `fd -t f -e py` 查找所有Python文件
141
- - `fd -t f -e js -e ts` 查找所有JavaScript/TypeScript文件
142
- - `fd -t d` 列出所有目录
143
- - `fd -t f -e java -e kt` 查找所有Java/Kotlin文件
144
- - `fd -t f -e go` 查找所有Go文件
145
- - `fd -t f -e rs` 查找所有Rust文件
146
- - `fd -t f -e c -e cpp -e h -e hpp` 查找所有C/C++文件
147
- </category>
148
-
149
- <category>
150
- - **代码内容搜索**:
151
- - `rg "pattern" --type py` 在Python文件中搜索
152
- - `rg "pattern" --type js` 在JavaScript文件中搜索
153
- - `rg "pattern" --type java` 在Java文件中搜索
154
- - `rg "pattern" --type c` 在C文件中搜索
155
- - `rg "class ClassName"` 查找类定义
156
- - `rg "func|function|def" -g "*.py" -g "*.js" -g "*.go" -g "*.rs"` 查找函数定义
157
- - `rg -w "word"` 精确匹配单词
158
- </category>
159
-
160
- <category>
161
- - **代码统计分析**:
162
- - `loc` 统计当前目录代码行数
163
- </category>
164
-
165
- <category>
166
- - **代码质量检查**:
167
- - Python: `pylint <file_path>`, `flake8 <file_path>`
168
- - JavaScript: `eslint <file_path>`
169
- - TypeScript: `tsc --noEmit <file_path>`
170
- - Java: `checkstyle <file_path>`
171
- - Go: `go vet <file_path>`
172
- - Rust: `cargo clippy`
173
- - C/C++: `cppcheck <file_path>`
174
- </category>
175
-
176
- <category>
177
- - **整体代码分析**:
178
- - 使用execute_script编写和执行脚本,批量分析多个文件
179
- - 简单脚本示例:`find . -name "*.py" | xargs pylint`
180
- - 使用多工具组合:`fd -e py | xargs pylint`
181
- </category>
182
- </shell_commands>
183
-
184
- <read_code_usage>
185
- ### read_code工具使用
186
- 读取文件应优先使用read_code工具,而非shell命令:
187
- - 完整读取:使用read_code读取整个文件内容
188
- - 部分读取:使用read_code指定行范围
189
- - 大文件处理:对大型文件使用read_code指定行范围,避免全部加载
190
- </read_code_usage>
191
-
192
- <tool_usage>
193
- ### 仅在命令行工具不足时使用专用工具
194
- 只有当fd、rg、loc和read_code工具无法获取足够信息时,才考虑使用专用工具(ask_codebase等)。在每次使用专用工具前,应先尝试使用上述工具获取所需信息。
195
- </tool_usage>
196
-
197
- <notes>
198
- ### 注意事项
199
- - read_code比cat或grep更适合阅读代码
200
- - rg比grep更快更强大,应优先使用
201
- - fd比find更快更易用,应优先使用
202
- - loc比wc -l提供更多代码统计信息,应优先使用
203
- - 针对不同编程语言选择对应的代码质量检查工具
204
- - 不要留下未实现的代码
205
-
206
- ### 代码编辑规范
207
- - 使用edit_file工具进行代码修改时,必须遵循最小补丁原则
208
- - 只提供需要修改的代码部分,不要提供完整文件内容
209
- - 保持原始代码的缩进、空行和格式风格
77
+ 1. **项目分析**:分析项目结构,确定需修改的文件
78
+ 2. **需求分析**:理解需求意图,选择影响最小的实现方案
79
+ 3. **代码分析**:详细分析目标文件,禁止虚构现有代码
80
+ 4. **方案设计**:确定最小变更方案,保持代码结构
81
+ 5. **实施修改**:遵循"先读后写"原则,保持代码风格一致性
82
+
83
+ ## 工具使用
84
+ - 项目结构:优先使用fd命令查找文件
85
+ - 代码搜索:优先使用rg进行内容搜索
86
+ - 代码阅读:优先使用read_code工具
87
+ - 仅在命令行工具不足时使用专用工具
88
+
89
+ ## 代码编辑规范
90
+ ### 代码修改工具选择
91
+ - 对于所有代码修改任务,优先使用edit_file工具,对于特别简单的修改,可以通过execute_script工具使用shell命令修改
92
+ - edit_file通过搜索和替换实现精确的代码编辑,是首选的代码修改方式
93
+ - 每个搜索文本在文件中必须唯一匹配,确保修改的准确性
94
+ - 为新文件创建时,使用空字符串作为搜索文本,替换文本作为完整内容
95
+ - 保持与原代码完全一致的格式和缩进风格
96
+
97
+ ### 文件重写工具使用
98
+ - rewrite_file工具用于完全重写文件内容或创建新文件
99
+ - 当需要替换整个文件内容时,优先使用rewrite_file工具
100
+ - 创建新文件时,使用rewrite_file工具提供完整的文件内容
101
+ - 保持与原代码相同的格式、缩进和编码风格
102
+ - 确保提供格式良好的完整文件内容
103
+
104
+ ### 最小补丁原则
105
+ - 对于任何代码修改,只提供需要修改的代码部分,不提供完整文件内容
106
+ - 严格保持原始代码的缩进、空行和格式风格
107
+ - 提供最小必要的上下文,确保修改位置精确
210
108
  - 每个修改必须包含清晰的修改理由
211
- - 新建文件时可以提供完整内容,修改现有文件时只提供差异部分
212
- </notes>
109
+
110
+ ### 格式兼容要求
111
+ - 保持与原代码相同的缩进方式(空格或制表符)
112
+ - 保持原代码的空行数量和位置
113
+ - 不改变原代码的换行风格
114
+ - 对新文件可提供完整内容,对现有文件只提供差异部分
213
115
  </code_engineer_guide>
214
116
  """
215
117
  # Dynamically add ask_codebase based on task complexity if really needed
@@ -236,9 +138,14 @@ class CodeAgent:
236
138
  self.agent.set_addon_prompt(
237
139
  "请使用工具充分理解用户需求,然后根据需求一步步执行代码修改/开发,"
238
140
  "如果不清楚要修改那些文件,可以使用ask_codebase工具,"
239
- "以:xxxx功能在哪个文件中实现?类似句式提问"
141
+ "以:xxxx功能在哪个文件中实现?类似句式提问。"
142
+ "所有代码修改任务都应优先使用edit_file工具,而非edit_file工具。"
143
+ "edit_file工具通过精确的搜索和替换实现代码编辑,"
144
+ "搜索文本需在目标文件中有且仅有一次精确匹配,确保修改的准确性。"
240
145
  )
241
146
 
147
+ self.agent.set_after_tool_call_cb(self.after_tool_call_cb)
148
+
242
149
  def get_root_dir(self) -> str:
243
150
  """获取项目根目录
244
151
 
@@ -275,7 +182,7 @@ class CodeAgent:
275
182
  'message': 提交信息,
276
183
  'author': 作者,
277
184
  'date': 提交日期,
278
- 'files': [修改的文件列表] (最多50个文件)
185
+ 'files': [修改的文件列表] (最多20个文件)
279
186
  },
280
187
  ...
281
188
  ]
@@ -317,7 +224,7 @@ class CodeAgent:
317
224
  )
318
225
  if files_result.returncode == 0:
319
226
  files = list(set(filter(None, files_result.stdout.splitlines())))
320
- commit['files'] = files[:50] # 限制最多50个文件
227
+ commit['files'] = files[:20] # 限制最多20个文件
321
228
 
322
229
  return commits
323
230
 
@@ -325,7 +232,10 @@ class CodeAgent:
325
232
  return []
326
233
 
327
234
  def _init_env(self) -> None:
328
- """初始化环境"""
235
+ """初始化环境,包括:
236
+ 1. 查找git根目录
237
+ 2. 检查并处理未提交的修改
238
+ """
329
239
  with yaspin(text="正在初始化环境...", color="cyan") as spinner:
330
240
  curr_dir = os.getcwd()
331
241
  git_dir = find_git_root(curr_dir)
@@ -338,7 +248,10 @@ class CodeAgent:
338
248
  spinner.ok("✅")
339
249
 
340
250
  def _handle_uncommitted_changes(self) -> None:
341
- """处理未提交的修改"""
251
+ """处理未提交的修改,包括:
252
+ 1. 提示用户确认是否提交
253
+ 2. 如果确认,则暂存并提交所有修改
254
+ """
342
255
  if has_uncommitted_changes():
343
256
  PrettyOutput.print("检测到未提交的修改,是否要提交?", OutputType.WARNING)
344
257
  if user_confirm("是否要提交?", True):
@@ -371,14 +284,14 @@ class CodeAgent:
371
284
  start_commit: Optional[str],
372
285
  end_commit: Optional[str]
373
286
  ) -> List[Tuple[str, str]]:
374
- """Show commit history between two commits.
287
+ """显示两个提交之间的提交历史
375
288
 
376
- Args:
377
- start_commit: The starting commit hash
378
- end_commit: The ending commit hash
289
+ 参数:
290
+ start_commit: 起始提交hash
291
+ end_commit: 结束提交hash
379
292
 
380
- Returns:
381
- List of tuples containing (commit_hash, commit_message)
293
+ 返回:
294
+ 包含(commit_hash, commit_message)的元组列表
382
295
  """
383
296
  if start_commit and end_commit:
384
297
  commits = get_commits_between(start_commit, end_commit)
@@ -458,6 +371,56 @@ class CodeAgent:
458
371
 
459
372
  except RuntimeError as e:
460
373
  return f"Error during execution: {str(e)}"
374
+
375
+ def after_tool_call_cb(self, agent: Agent) -> None:
376
+ """工具调用后回调函数。"""
377
+ final_ret = ""
378
+ diff = get_diff()
379
+ if diff:
380
+ start_hash = get_latest_commit_hash()
381
+ PrettyOutput.print(diff, OutputType.CODE, lang="diff")
382
+ commited = handle_commit_workflow()
383
+ if commited:
384
+ # 获取提交信息
385
+ end_hash = get_latest_commit_hash()
386
+ commits = get_commits_between(start_hash, end_hash)
387
+
388
+ # 添加提交信息到final_ret
389
+ if commits:
390
+ final_ret += "✅ 补丁已应用\n"
391
+ final_ret += "# 提交信息:\n"
392
+ for commit_hash, commit_message in commits:
393
+ final_ret += f"- {commit_hash[:7]}: {commit_message}\n"
394
+
395
+ final_ret += f"# 应用补丁:\n```diff\n{diff}\n```"
396
+
397
+ # 修改后的提示逻辑
398
+ addon_prompt = f"如果用户的需求未完成,请继续生成补丁,如果已经完成,请终止,不要输出新的PATCH,不要实现任何超出用户需求外的内容\n"
399
+ addon_prompt += "如果有任何信息不明确,调用工具获取信息\n"
400
+ addon_prompt += "每次响应必须且只能包含一个操作\n"
401
+
402
+ agent.set_addon_prompt(addon_prompt)
403
+
404
+ else:
405
+ final_ret += "✅ 补丁已应用(没有新的提交)"
406
+ else:
407
+ final_ret += "❌ 补丁应用被拒绝\n"
408
+ final_ret += f"# 补丁预览:\n```diff\n{diff}\n```"
409
+ else:
410
+ return
411
+ # 用户确认最终结果
412
+ if commited:
413
+ agent.prompt += final_ret
414
+ return
415
+ PrettyOutput.print(final_ret, OutputType.USER, lang="markdown")
416
+ if not is_confirm_before_apply_patch() or user_confirm("是否使用此回复?", default=True):
417
+ agent.prompt += final_ret
418
+ return
419
+ custom_reply = get_multiline_input("请输入自定义回复")
420
+ if not custom_reply.strip(): # 如果自定义回复为空,返回空字符串
421
+ agent.prompt += final_ret
422
+ agent.set_addon_prompt(custom_reply)
423
+ agent.prompt += final_ret
461
424
 
462
425
 
463
426
  def main() -> None:
@@ -997,6 +997,7 @@ def create_dev_team() -> MultiAgent:
997
997
  "methodology",
998
998
  "ask_codebase",
999
999
  "edit_file",
1000
+ "rewrite_file",
1000
1001
  ])
1001
1002
 
1002
1003
  BA_output_handler = ToolRegistry()
@@ -1009,6 +1010,7 @@ def create_dev_team() -> MultiAgent:
1009
1010
  "methodology",
1010
1011
  "ask_codebase",
1011
1012
  "edit_file",
1013
+ "rewrite_file",
1012
1014
  ])
1013
1015
 
1014
1016
  SA_output_handler = ToolRegistry()
@@ -1020,6 +1022,7 @@ def create_dev_team() -> MultiAgent:
1020
1022
  "read_code",
1021
1023
  "methodology",
1022
1024
  "edit_file",
1025
+ "rewrite_file",
1023
1026
  ])
1024
1027
 
1025
1028
  TL_output_handler = ToolRegistry()
@@ -1030,6 +1033,7 @@ def create_dev_team() -> MultiAgent:
1030
1033
  "execute_script",
1031
1034
  "methodology",
1032
1035
  "edit_file",
1036
+ "rewrite_file",
1033
1037
  ])
1034
1038
 
1035
1039
  DEV_output_handler = ToolRegistry()
@@ -1042,6 +1046,7 @@ def create_dev_team() -> MultiAgent:
1042
1046
  "create_sub_agent",
1043
1047
  "methodology",
1044
1048
  "edit_file",
1049
+ "rewrite_file",
1045
1050
  ])
1046
1051
 
1047
1052
  QA_output_handler = ToolRegistry()
@@ -1055,6 +1060,7 @@ def create_dev_team() -> MultiAgent:
1055
1060
  "read_code",
1056
1061
  "methodology",
1057
1062
  "edit_file",
1063
+ "rewrite_file",
1058
1064
  ])
1059
1065
 
1060
1066
  # Update PM prompt with tool usage guidance
@@ -13,7 +13,8 @@ from jarvis.jarvis_agent import Agent
13
13
  from jarvis.jarvis_platform.registry import PlatformRegistry
14
14
  from jarvis.jarvis_tools.registry import ToolRegistry
15
15
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
16
- from jarvis.jarvis_utils.utils import ct, ot, init_env
16
+ from jarvis.jarvis_utils.tag import ct, ot
17
+ from jarvis.jarvis_utils.utils import init_env
17
18
 
18
19
 
19
20
  class GitCommitAnalyzer: