jarvis-ai-assistant 0.3.18__tar.gz → 0.3.20__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.
Files changed (136) hide show
  1. {jarvis_ai_assistant-0.3.18/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.3.20}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/pyproject.toml +1 -1
  3. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/setup.py +1 -1
  4. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/__init__.py +30 -12
  6. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/config_editor.py +1 -1
  7. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/edit_file_handler.py +8 -13
  8. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/memory_manager.py +4 -4
  9. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/shell_input_handler.py +17 -2
  10. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/task_analyzer.py +4 -3
  11. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/task_manager.py +6 -6
  12. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/tool_executor.py +2 -2
  13. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/code_agent.py +21 -29
  14. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/code_review.py +2 -4
  15. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_utils/git_commiter.py +17 -18
  16. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_methodology/main.py +12 -12
  17. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/ai8.py +0 -4
  18. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/base.py +16 -15
  19. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/kimi.py +13 -13
  20. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/tongyi.py +17 -15
  21. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/yuanbao.py +11 -11
  22. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/service.py +2 -2
  23. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/cli.py +36 -32
  24. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/embedding_manager.py +11 -6
  25. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/llm_interface.py +6 -5
  26. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/rag_pipeline.py +9 -8
  27. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/reranker.py +3 -2
  28. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/retriever.py +18 -8
  29. jarvis_ai_assistant-0.3.20/src/jarvis/jarvis_smart_shell/main.py +490 -0
  30. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/cli.py +2 -1
  31. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/stats.py +45 -5
  32. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/storage.py +220 -9
  33. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/clear_memory.py +0 -11
  34. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/cli/main.py +18 -17
  35. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/edit_file.py +4 -4
  36. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/execute_script.py +5 -1
  37. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/file_analyzer.py +6 -6
  38. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/generate_new_tool.py +6 -17
  39. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/read_code.py +3 -6
  40. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/read_webpage.py +4 -4
  41. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/registry.py +8 -28
  42. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/retrieve_memory.py +5 -16
  43. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/rewrite_file.py +0 -4
  44. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/save_memory.py +2 -10
  45. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/search_web.py +5 -8
  46. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/virtual_tty.py +22 -40
  47. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/clipboard.py +2 -2
  48. jarvis_ai_assistant-0.3.20/src/jarvis/jarvis_utils/input.py +712 -0
  49. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/methodology.py +3 -3
  50. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/output.py +215 -135
  51. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/utils.py +35 -58
  52. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  53. jarvis_ai_assistant-0.3.18/src/jarvis/jarvis_smart_shell/main.py +0 -230
  54. jarvis_ai_assistant-0.3.18/src/jarvis/jarvis_utils/input.py +0 -426
  55. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/LICENSE +0 -0
  56. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/MANIFEST.in +0 -0
  57. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/README.md +0 -0
  58. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/setup.cfg +0 -0
  59. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/agent_manager.py +0 -0
  60. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  61. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/file_methodology_manager.py +0 -0
  62. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/jarvis.py +0 -0
  63. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/main.py +0 -0
  64. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/methodology_share_manager.py +0 -0
  65. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/output_handler.py +0 -0
  66. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/prompt_builder.py +0 -0
  67. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/prompts.py +0 -0
  68. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/protocols.py +0 -0
  69. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/session_manager.py +0 -0
  70. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/share_manager.py +0 -0
  71. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_agent/tool_share_manager.py +0 -0
  72. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  73. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_agent/lint.py +0 -0
  74. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  75. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  76. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  77. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  78. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  79. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  80. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  81. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  82. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  83. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  84. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  85. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  86. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  87. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  88. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  89. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  90. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  91. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  92. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  93. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  94. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_data/config_schema.json +0 -0
  95. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  96. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  97. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_git_squash/main.py +0 -0
  98. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  99. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
  100. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
  101. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_mcp/streamable_mcp_client.py +0 -0
  102. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_memory_organizer/__init__.py +0 -0
  103. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_memory_organizer/memory_organizer.py +0 -0
  104. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
  105. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_multi_agent/main.py +0 -0
  106. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/__init__.py +0 -0
  107. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/human.py +0 -0
  108. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/openai.py +0 -0
  109. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform/registry.py +0 -0
  110. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  111. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  112. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/__init__.py +0 -0
  113. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/cache.py +0 -0
  114. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_rag/query_rewriter.py +0 -0
  115. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  116. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/__init__.py +0 -0
  117. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_stats/visualizer.py +0 -0
  118. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/__init__.py +0 -0
  119. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  120. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/base.py +0 -0
  121. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/cli/__init__.py +0 -0
  122. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_tools/methodology.py +0 -0
  123. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/__init__.py +0 -0
  124. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
  125. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/config.py +0 -0
  126. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/embedding.py +0 -0
  127. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  128. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/git_utils.py +0 -0
  129. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/globals.py +0 -0
  130. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/http.py +0 -0
  131. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis/jarvis_utils/tag.py +0 -0
  132. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +0 -0
  133. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  134. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  135. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  136. {jarvis_ai_assistant-0.3.18 → jarvis_ai_assistant-0.3.20}/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.3.18
3
+ Version: 0.3.20
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jarvis-ai-assistant"
7
- version = "0.3.18"
7
+ version = "0.3.20"
8
8
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages # type: ignore
3
3
 
4
4
  setup(
5
5
  name="jarvis-ai-assistant",
6
- version="0.3.18",
6
+ version="0.3.20",
7
7
  author="skyfire",
8
8
  author_email="skyfireitdiy@hotmail.com",
9
9
  description="An AI assistant that uses various tools to interact with the system",
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.3.18"
4
+ __version__ = "0.3.20"
@@ -223,6 +223,7 @@ class Agent:
223
223
  use_analysis: Optional[bool] = None,
224
224
  force_save_memory: Optional[bool] = None,
225
225
  files: Optional[List[str]] = None,
226
+ confirm_callback: Optional[Callable[[str, bool], bool]] = None,
226
227
  ):
227
228
  """初始化Jarvis Agent实例
228
229
 
@@ -241,6 +242,7 @@ class Agent:
241
242
  use_methodology: 是否使用方法论
242
243
  use_analysis: 是否使用任务分析
243
244
  force_save_memory: 是否强制保存记忆
245
+ confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
244
246
  """
245
247
  # 基础属性初始化
246
248
  self.files = files or []
@@ -254,6 +256,11 @@ class Agent:
254
256
  self.user_data: Dict[str, Any] = {}
255
257
  self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
256
258
 
259
+ # 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
260
+ self.user_confirm: Callable[[str, bool], bool] = (
261
+ confirm_callback or user_confirm # type: ignore[assignment]
262
+ )
263
+
257
264
  # 初始化模型和会话
258
265
  self._init_model(llm_type, model_group)
259
266
  self._init_session()
@@ -413,6 +420,19 @@ class Agent:
413
420
  """Sets the flag to run input handlers on the next turn."""
414
421
  self.run_input_handlers_next_turn = value
415
422
 
423
+ def _multiline_input(self, tip: str, print_on_empty: bool) -> str:
424
+ """
425
+ Safe wrapper for multiline input to optionally suppress empty-input notice.
426
+ If the configured multiline_inputer supports 'print_on_empty' keyword, pass it;
427
+ otherwise, fall back to calling with a single argument for compatibility.
428
+ """
429
+ try:
430
+ # Try to pass the keyword for enhanced input handler
431
+ return self.multiline_inputer(tip, print_on_empty=print_on_empty) # type: ignore
432
+ except TypeError:
433
+ # Fallback for custom handlers that only accept one argument
434
+ return self.multiline_inputer(tip) # type: ignore
435
+
416
436
  def set_after_tool_call_cb(self, cb: Callable[[Any], None]): # type: ignore
417
437
  """设置工具调用后回调函数。
418
438
 
@@ -527,17 +547,17 @@ class Agent:
527
547
  注意:
528
548
  仅生成摘要,不修改对话状态
529
549
  """
530
- print("📄 正在总结对话历史...")
550
+
531
551
  try:
532
552
  if not self.model:
533
553
  raise RuntimeError("Model not initialized")
534
554
  summary = self.model.chat_until_success(
535
555
  self.session.prompt + "\n" + SUMMARY_REQUEST_PROMPT
536
556
  ) # type: ignore
537
- print("✅ 总结对话历史完成")
557
+
538
558
  return summary
539
559
  except Exception as e:
540
- print("总结对话历史失败")
560
+ PrettyOutput.print("总结对话历史失败", OutputType.ERROR)
541
561
  return ""
542
562
 
543
563
  def _summarize_and_clear_history(self) -> str:
@@ -559,7 +579,7 @@ class Agent:
559
579
  """
560
580
  # 在清理历史之前,提示用户保存重要记忆
561
581
  if self.force_save_memory:
562
- print("📌 对话历史即将被总结和清理,请先保存重要信息...")
582
+ PrettyOutput.print("对话历史即将被总结和清理,请先保存重要信息...", OutputType.INFO)
563
583
  self.memory_manager.prompt_memory_save()
564
584
 
565
585
  if self._should_use_file_upload():
@@ -634,12 +654,12 @@ class Agent:
634
654
  self._check_and_organize_memory()
635
655
 
636
656
  if self.need_summary:
637
- print("📄 正在生成总结...")
657
+
638
658
  self.session.prompt = self.summary_prompt
639
659
  if not self.model:
640
660
  raise RuntimeError("Model not initialized")
641
661
  ret = self.model.chat_until_success(self.session.prompt) # type: ignore
642
- print("✅ 总结生成完成")
662
+
643
663
  return ret
644
664
 
645
665
  return "任务完成"
@@ -789,7 +809,7 @@ class Agent:
789
809
  return None
790
810
 
791
811
  set_interrupt(False)
792
- user_input = self.multiline_inputer(f"模型交互期间被中断,请输入用户干预信息:")
812
+ user_input = self._multiline_input("模型交互期间被中断,请输入用户干预信息:", False)
793
813
 
794
814
  self.run_input_handlers_next_turn = True
795
815
 
@@ -798,7 +818,7 @@ class Agent:
798
818
  return self._complete_task(auto_completed=False)
799
819
 
800
820
  if any(handler.can_handle(current_response) for handler in self.output_handler):
801
- if user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
821
+ if self.user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
802
822
  self.session.prompt = f"被用户中断,用户补充信息为:{user_input}\n\n用户同意继续工具调用。"
803
823
  return None # 继续执行工具调用
804
824
  else:
@@ -814,9 +834,7 @@ class Agent:
814
834
  返回:
815
835
  str: "continue" 或 "complete"
816
836
  """
817
- user_input = self.multiline_inputer(
818
- f"{self.name}: 请输入,或输入空行来结束当前任务:"
819
- )
837
+ user_input = self._multiline_input(f"{self.name}: 请输入,或输入空行来结束当前任务:", False)
820
838
 
821
839
  if user_input:
822
840
  self.session.prompt = user_input
@@ -894,7 +912,7 @@ class Agent:
894
912
  f"并且存在3个以上标签重叠的记忆。\n"
895
913
  f"是否立即整理记忆库以优化性能和相关性?"
896
914
  )
897
- if user_confirm(prompt, default=True):
915
+ if self.user_confirm(prompt, True):
898
916
  PrettyOutput.print(
899
917
  f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
900
918
  OutputType.INFO,
@@ -40,7 +40,7 @@ class ConfigEditor:
40
40
 
41
41
  if editor:
42
42
  try:
43
- subprocess.run([editor, str(config_file_path)], check=True)
43
+ subprocess.run([editor, str(config_file_path)], check=True, shell=(platform.system() == "Windows"))
44
44
  raise typer.Exit(code=0)
45
45
  except (subprocess.CalledProcessError, FileNotFoundError) as e:
46
46
  PrettyOutput.print(f"Failed to open editor: {e}", OutputType.ERROR)
@@ -68,7 +68,7 @@ class EditFileHandler(OutputHandler):
68
68
  {"SEARCH": diff["SEARCH"], "REPLACE": diff["REPLACE"]} for diff in diffs
69
69
  ]
70
70
 
71
- print(f"📝 正在处理文件 {file_path}...")
71
+
72
72
  success, result = self._fast_edit(file_path, file_patches)
73
73
 
74
74
  if success:
@@ -208,7 +208,7 @@ class EditFileHandler(OutputHandler):
208
208
  modified_content = modified_content.replace(
209
209
  exact_search, replace_text, 1
210
210
  )
211
- print(f"✅ 补丁 #{patch_count} 应用成功")
211
+
212
212
  found = True
213
213
  else:
214
214
  # 如果匹配不到,并且search与replace块的首尾都是换行,尝试去掉第一个和最后一个换行
@@ -224,7 +224,7 @@ class EditFileHandler(OutputHandler):
224
224
  modified_content = modified_content.replace(
225
225
  stripped_search, stripped_replace, 1
226
226
  )
227
- print(f"✅ 补丁 #{patch_count} 应用成功 (自动去除首尾换行)")
227
+
228
228
  found = True
229
229
 
230
230
  if not found:
@@ -253,9 +253,7 @@ class EditFileHandler(OutputHandler):
253
253
  modified_content = modified_content.replace(
254
254
  indented_search, indented_replace, 1
255
255
  )
256
- print(
257
- f"✅ 补丁 #{patch_count} 应用成功 (自动增加 {space_count} 个空格缩进)"
258
- )
256
+
259
257
  found = True
260
258
  break
261
259
 
@@ -263,10 +261,7 @@ class EditFileHandler(OutputHandler):
263
261
  successful_patches += 1
264
262
  else:
265
263
  error_msg = "搜索文本在文件中不存在"
266
- PrettyOutput.print(
267
- f"{error_msg}:\n{search_text}",
268
- output_type=OutputType.WARNING,
269
- )
264
+
270
265
  failed_patches.append({"patch": patch, "error": error_msg})
271
266
 
272
267
  # 写入修改后的内容
@@ -284,12 +279,12 @@ class EditFileHandler(OutputHandler):
284
279
  f"失败: {len(failed_patches)}/{patch_count}.\n"
285
280
  f"失败详情:\n" + "\n".join(error_details)
286
281
  )
287
- print(f"❌ {summary}")
282
+ PrettyOutput.print(summary, OutputType.ERROR)
288
283
  return False, summary
289
284
 
290
- print(f"✅ 文件 {file_path} 修改完成,应用了 {patch_count} 个补丁")
285
+
291
286
  return True, modified_content
292
287
 
293
288
  except Exception as e:
294
- print(f"文件修改失败: {str(e)}")
289
+ PrettyOutput.print(f"文件修改失败: {str(e)}", OutputType.ERROR)
295
290
  return False, f"文件修改失败: {str(e)}"
@@ -74,7 +74,7 @@ class MemoryManager:
74
74
  if "save_memory" not in tool_names:
75
75
  return
76
76
 
77
- print("🔍 正在分析是否有值得记忆的信息...")
77
+
78
78
 
79
79
  # 构建提示词,让大模型自己判断并保存记忆
80
80
  prompt = """请回顾本次任务的整个过程,判断是否有值得长期记忆或项目记忆的信息。
@@ -97,12 +97,12 @@ class MemoryManager:
97
97
 
98
98
  # 根据响应判断是否保存了记忆
99
99
  if "save_memory" in response:
100
- print("已自动保存有价值的信息到记忆系统")
100
+ PrettyOutput.print("已自动保存有价值的信息到记忆系统", OutputType.SUCCESS)
101
101
  else:
102
- print("📝 本次任务没有特别需要记忆的信息")
102
+ PrettyOutput.print("本次任务没有特别需要记忆的信息", OutputType.INFO)
103
103
 
104
104
  except Exception as e:
105
- print(f"记忆分析失败: {str(e)}")
105
+ PrettyOutput.print(f"记忆分析失败: {str(e)}", OutputType.ERROR)
106
106
 
107
107
  def add_memory_prompts_to_addon(self, addon_prompt: str, tool_registry) -> str:
108
108
  """在附加提示中添加记忆相关提示"""
@@ -11,9 +11,24 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
11
11
  if len(cmdline) == 0:
12
12
  return user_input, False
13
13
  else:
14
- script = "\n".join([c[1:] for c in cmdline])
14
+ marker = "# JARVIS-NOCONFIRM"
15
+
16
+ def _clean(line: str) -> str:
17
+ s = line[1:] # remove leading '!'
18
+ # strip no-confirm marker if present
19
+ idx = s.find(marker)
20
+ if idx != -1:
21
+ s = s[:idx]
22
+ return s.rstrip()
23
+
24
+ # Build script while stripping the no-confirm marker from each line
25
+ script = "\n".join([_clean(c) for c in cmdline])
15
26
  PrettyOutput.print(script, OutputType.CODE, lang="bash")
16
- if user_confirm(f"是否要执行以上shell脚本?", default=True):
27
+
28
+ # If any line contains the no-confirm marker, skip the pre-execution confirmation
29
+ no_confirm = any(marker in c for c in cmdline)
30
+
31
+ if no_confirm or user_confirm(f"是否要执行以上shell脚本?", default=True):
17
32
  from jarvis.jarvis_tools.registry import ToolRegistry
18
33
 
19
34
  output = ToolRegistry().handle_tool_calls(
@@ -8,6 +8,7 @@ from typing import Optional
8
8
  from jarvis.jarvis_utils.globals import get_interrupt, set_interrupt
9
9
  from jarvis.jarvis_utils.input import user_confirm
10
10
  from jarvis.jarvis_agent.prompts import TASK_ANALYSIS_PROMPT
11
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
12
 
12
13
 
13
14
  class TaskAnalyzer:
@@ -24,7 +25,7 @@ class TaskAnalyzer:
24
25
 
25
26
  def analysis_task(self, satisfaction_feedback: str = ""):
26
27
  """分析任务并生成方法论"""
27
- print("🔍 正在分析任务...")
28
+
28
29
  try:
29
30
  # 准备分析提示
30
31
  self.agent.session.prompt = self._prepare_analysis_prompt(
@@ -37,9 +38,9 @@ class TaskAnalyzer:
37
38
  # 循环处理工具调用,直到没有工具调用为止
38
39
  self._process_analysis_loop()
39
40
 
40
- print("✅ 分析完成")
41
+
41
42
  except Exception as e:
42
- print("分析失败")
43
+ PrettyOutput.print("分析失败", OutputType.ERROR)
43
44
 
44
45
  def _prepare_analysis_prompt(self, satisfaction_feedback: str) -> str:
45
46
  """准备分析提示"""
@@ -29,7 +29,7 @@ class TaskManager:
29
29
  data_dir = get_data_dir()
30
30
  pre_command_path = os.path.join(data_dir, "pre-command")
31
31
  if os.path.exists(pre_command_path):
32
- print(f"🔍 从{pre_command_path}加载预定义任务...")
32
+ PrettyOutput.print(f"从{pre_command_path}加载预定义任务...", OutputType.INFO)
33
33
  try:
34
34
  with open(
35
35
  pre_command_path, "r", encoding="utf-8", errors="ignore"
@@ -39,15 +39,15 @@ class TaskManager:
39
39
  for name, desc in user_tasks.items():
40
40
  if desc:
41
41
  tasks[str(name)] = str(desc)
42
- print(f"预定义任务加载完成 {pre_command_path}")
42
+ PrettyOutput.print(f"预定义任务加载完成 {pre_command_path}", OutputType.SUCCESS)
43
43
  except (yaml.YAMLError, OSError):
44
- print(f"预定义任务加载失败 {pre_command_path}")
44
+ PrettyOutput.print(f"预定义任务加载失败 {pre_command_path}", OutputType.ERROR)
45
45
 
46
46
  # Check .jarvis/pre-command in current directory
47
47
  pre_command_path = ".jarvis/pre-command"
48
48
  if os.path.exists(pre_command_path):
49
49
  abs_path = os.path.abspath(pre_command_path)
50
- print(f"🔍 从{abs_path}加载预定义任务...")
50
+ PrettyOutput.print(f"从{abs_path}加载预定义任务...", OutputType.INFO)
51
51
  try:
52
52
  with open(
53
53
  pre_command_path, "r", encoding="utf-8", errors="ignore"
@@ -57,9 +57,9 @@ class TaskManager:
57
57
  for name, desc in local_tasks.items():
58
58
  if desc:
59
59
  tasks[str(name)] = str(desc)
60
- print(f"预定义任务加载完成 {pre_command_path}")
60
+ PrettyOutput.print(f"预定义任务加载完成 {pre_command_path}", OutputType.SUCCESS)
61
61
  except (yaml.YAMLError, OSError):
62
- print(f"预定义任务加载失败 {pre_command_path}")
62
+ PrettyOutput.print(f"预定义任务加载失败 {pre_command_path}", OutputType.ERROR)
63
63
 
64
64
  return tasks
65
65
 
@@ -42,9 +42,9 @@ def execute_tool_call(response: str, agent: "Agent") -> Tuple[bool, Any]:
42
42
  f"需要执行{tool_to_execute.name()}确认执行?", True
43
43
  ):
44
44
  try:
45
- print(f"🔧 正在执行{tool_to_execute.name()}...")
45
+
46
46
  result = tool_to_execute.handle(response, agent)
47
- print(f"✅ {tool_to_execute.name()}执行完成")
47
+
48
48
  return result
49
49
  except Exception as e:
50
50
  PrettyOutput.print(f"工具执行失败: {str(e)}", OutputType.ERROR)
@@ -205,11 +205,11 @@ class CodeAgent:
205
205
  返回:
206
206
  str: git根目录路径
207
207
  """
208
- print("🔍 正在查找git根目录...")
208
+
209
209
  curr_dir = os.getcwd()
210
210
  git_dir = find_git_root_and_cd(curr_dir)
211
211
  self.root_dir = git_dir
212
- print(f"✅ 已找到git根目录: {git_dir}")
212
+
213
213
  return git_dir
214
214
 
215
215
  def _update_gitignore(self, git_dir: str) -> None:
@@ -218,33 +218,30 @@ class CodeAgent:
218
218
  参数:
219
219
  git_dir: git根目录路径
220
220
  """
221
- print("📝 正在检查.gitignore文件...")
221
+
222
222
  gitignore_path = os.path.join(git_dir, ".gitignore")
223
223
  jarvis_ignore = ".jarvis"
224
224
 
225
225
  if not os.path.exists(gitignore_path):
226
226
  with open(gitignore_path, "w", encoding="utf-8") as f:
227
227
  f.write(f"{jarvis_ignore}\n")
228
- print(f" 已创建.gitignore文件并添加'{jarvis_ignore}'")
228
+ PrettyOutput.print(f"已创建 .gitignore 并添加 '{jarvis_ignore}'", OutputType.SUCCESS)
229
229
  else:
230
230
  with open(gitignore_path, "r+", encoding="utf-8") as f:
231
231
  content = f.read()
232
232
  if jarvis_ignore not in content.splitlines():
233
233
  f.write(f"\n{jarvis_ignore}\n")
234
- print(f"✅ 已更新.gitignore文件,添加'{jarvis_ignore}'")
235
- else:
236
- print("ℹ️ .jarvis已在.gitignore中")
234
+ PrettyOutput.print(
235
+ f"已更新 .gitignore,添加 '{jarvis_ignore}'", OutputType.SUCCESS
236
+ )
237
237
 
238
238
  def _handle_git_changes(self, prefix: str, suffix: str) -> None:
239
239
  """处理git仓库中的未提交修改"""
240
- print("🔄 正在检查未提交的修改...")
240
+
241
241
  if has_uncommitted_changes():
242
- print("⏳ 发现未提交修改,正在处理...")
242
+
243
243
  git_commiter = GitCommitTool()
244
244
  git_commiter.execute({"prefix": prefix, "suffix": suffix})
245
- print("✅ 未提交修改已处理完成")
246
- else:
247
- print("✅ 没有未提交的修改")
248
245
 
249
246
  def _init_env(self, prefix: str, suffix: str) -> None:
250
247
  """初始化环境,组合以下功能:
@@ -253,13 +250,12 @@ class CodeAgent:
253
250
  3. 处理未提交的修改
254
251
  4. 配置git对换行符变化不敏感
255
252
  """
256
- print("🚀 正在初始化环境...")
253
+
257
254
  git_dir = self._find_git_root()
258
255
  self._update_gitignore(git_dir)
259
256
  self._handle_git_changes(prefix, suffix)
260
257
  # 配置git对换行符变化不敏感
261
258
  self._configure_line_ending_settings()
262
- print("✅ 环境初始化完成")
263
259
 
264
260
  def _configure_line_ending_settings(self) -> None:
265
261
  """配置git对换行符变化不敏感,只在当前设置与目标设置不一致时修改"""
@@ -285,17 +281,17 @@ class CodeAgent:
285
281
  need_change = True
286
282
 
287
283
  if not need_change:
288
- print("✅ git换行符敏感设置已符合要求")
284
+
289
285
  return
290
286
 
291
287
  PrettyOutput.print(
292
288
  "⚠️ 正在修改git换行符敏感设置,这会影响所有文件的换行符处理方式",
293
289
  OutputType.WARNING,
294
290
  )
295
- print("将进行以下设置:")
291
+ PrettyOutput.print("将进行以下设置:", OutputType.INFO)
296
292
  for key, value in target_settings.items():
297
293
  current = current_settings.get(key, "未设置")
298
- print(f" {key}: {current} -> {value}")
294
+ PrettyOutput.print(f"{key}: {current} -> {value}", OutputType.INFO)
299
295
 
300
296
  # 直接执行设置,不需要用户确认
301
297
  for key, value in target_settings.items():
@@ -305,7 +301,7 @@ class CodeAgent:
305
301
  if sys.platform.startswith("win"):
306
302
  self._handle_windows_line_endings()
307
303
 
308
- print("git换行符敏感设置已更新")
304
+ PrettyOutput.print("git换行符敏感设置已更新", OutputType.SUCCESS)
309
305
 
310
306
  def _handle_windows_line_endings(self) -> None:
311
307
  """在Windows系统上处理换行符问题,提供建议而非强制修改"""
@@ -319,10 +315,8 @@ class CodeAgent:
319
315
  if any(keyword in content for keyword in ["text=", "eol=", "binary"]):
320
316
  return
321
317
 
322
- print(
323
- "\n💡 提示:在Windows系统上,建议配置.gitattributes文件来避免换行符问题。"
324
- )
325
- print("这可以防止仅因换行符不同而导致整个文件被标记为修改。")
318
+ PrettyOutput.print("提示:在Windows系统上,建议配置 .gitattributes 文件来避免换行符问题。", OutputType.INFO)
319
+ PrettyOutput.print("这可以防止仅因换行符不同而导致整个文件被标记为修改。", OutputType.INFO)
326
320
 
327
321
  if user_confirm("是否要创建一个最小化的.gitattributes文件?", False):
328
322
  # 最小化的内容,只影响特定类型的文件
@@ -341,20 +335,18 @@ class CodeAgent:
341
335
  if not os.path.exists(gitattributes_path):
342
336
  with open(gitattributes_path, "w", encoding="utf-8", newline="\n") as f:
343
337
  f.write(minimal_content)
344
- print(" 已创建最小化的.gitattributes文件")
338
+ PrettyOutput.print("已创建最小化的 .gitattributes 文件", OutputType.SUCCESS)
345
339
  else:
346
- print("📝 将以下内容追加到现有.gitattributes文件:")
347
- print(minimal_content)
340
+ PrettyOutput.print("将以下内容追加到现有 .gitattributes 文件:", OutputType.INFO)
341
+ PrettyOutput.print(minimal_content, OutputType.CODE, lang="text")
348
342
  if user_confirm("是否追加到现有文件?", True):
349
343
  with open(
350
344
  gitattributes_path, "a", encoding="utf-8", newline="\n"
351
345
  ) as f:
352
346
  f.write("\n" + minimal_content)
353
- print(" 已更新.gitattributes文件")
347
+ PrettyOutput.print("已更新 .gitattributes 文件", OutputType.SUCCESS)
354
348
  else:
355
- print(
356
- "ℹ️ 跳过.gitattributes文件创建。如果遇到换行符问题,可以手动创建此文件。"
357
- )
349
+ PrettyOutput.print("跳过 .gitattributes 文件创建。如遇换行符问题,可手动创建此文件。", OutputType.INFO)
358
350
 
359
351
  def _record_code_changes_stats(self, diff_text: str) -> None:
360
352
  """记录代码变更的统计信息。
@@ -286,7 +286,6 @@ class CodeReviewTool:
286
286
  diff_output = ""
287
287
 
288
288
  # Build git diff command based on review type
289
- print("📊 正在获取代码变更...")
290
289
 
291
290
  if review_type == "commit":
292
291
  if "commit_sha" not in args:
@@ -458,7 +457,6 @@ class CodeReviewTool:
458
457
  diff_output = review_info + diff_output
459
458
 
460
459
  PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
461
- print("✅ 代码变更获取完成")
462
460
 
463
461
  system_prompt = """<code_review_guide>
464
462
  <role>
@@ -753,10 +751,10 @@ class CodeReviewTool:
753
751
  "stdout": "",
754
752
  "stderr": "代码差异太大,无法处理",
755
753
  }
756
- print("📤 正在上传代码差异文件...")
754
+
757
755
  upload_success = agent.model.upload_files([temp_file_path])
758
756
  if upload_success:
759
- print("✅ 已成功上传代码差异文件")
757
+ pass
760
758
  else:
761
759
  return {
762
760
  "success": False,