jarvis-ai-assistant 0.4.0__tar.gz → 0.4.2__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 (151) hide show
  1. {jarvis_ai_assistant-0.4.0/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.4.2}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/pyproject.toml +1 -1
  3. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/setup.py +1 -1
  4. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/__init__.py +95 -74
  6. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/agent_manager.py +6 -4
  7. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/edit_file_handler.py +2 -2
  8. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/jarvis.py +40 -9
  9. jarvis_ai_assistant-0.4.2/src/jarvis/jarvis_agent/rewrite_file_handler.py +143 -0
  10. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/run_loop.py +23 -4
  11. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/utils.py +5 -1
  12. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/web_server.py +332 -234
  13. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_agent/code_agent.py +10 -7
  14. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/code_review.py +0 -1
  15. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_data/config_schema.json +10 -0
  16. jarvis_ai_assistant-0.4.2/src/jarvis/jarvis_multi_agent/__init__.py +402 -0
  17. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_multi_agent/main.py +10 -1
  18. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/base.py +15 -6
  19. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/registry.py +6 -0
  20. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/sub_agent.py +19 -34
  21. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/sub_code_agent.py +3 -1
  22. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/config.py +26 -11
  23. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/input.py +77 -6
  24. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  25. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +1 -3
  26. jarvis_ai_assistant-0.4.0/src/jarvis/jarvis_agent/config.py +0 -99
  27. jarvis_ai_assistant-0.4.0/src/jarvis/jarvis_multi_agent/__init__.py +0 -209
  28. jarvis_ai_assistant-0.4.0/src/jarvis/jarvis_tools/edit_file.py +0 -208
  29. jarvis_ai_assistant-0.4.0/src/jarvis/jarvis_tools/rewrite_file.py +0 -191
  30. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/LICENSE +0 -0
  31. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/MANIFEST.in +0 -0
  32. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/README.md +0 -0
  33. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/setup.cfg +0 -0
  34. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  35. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/config_editor.py +0 -0
  36. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/event_bus.py +0 -0
  37. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/events.py +0 -0
  38. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/file_context_handler.py +0 -0
  39. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/file_methodology_manager.py +0 -0
  40. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/main.py +0 -0
  41. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/memory_manager.py +0 -0
  42. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/methodology_share_manager.py +0 -0
  43. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/output_handler.py +0 -0
  44. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/prompt_builder.py +0 -0
  45. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/prompt_manager.py +0 -0
  46. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/prompts.py +0 -0
  47. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/protocols.py +0 -0
  48. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/session_manager.py +0 -0
  49. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/share_manager.py +0 -0
  50. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/shell_input_handler.py +0 -0
  51. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/stdio_redirect.py +0 -0
  52. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/task_analyzer.py +0 -0
  53. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/task_manager.py +0 -0
  54. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/tool_executor.py +0 -0
  55. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/tool_share_manager.py +0 -0
  56. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/user_interaction.py +0 -0
  57. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/web_bridge.py +0 -0
  58. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_agent/web_output_sink.py +0 -0
  59. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  60. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_agent/lint.py +0 -0
  61. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  62. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  63. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  64. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  65. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  66. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  67. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  68. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  69. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  70. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  71. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  72. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  73. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  74. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  75. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  76. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  77. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  78. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  79. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  80. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  81. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_data/tiktoken/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  82. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  83. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_git_squash/main.py +0 -0
  84. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
  85. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  86. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_mcp/sse_mcp_client.py +0 -0
  87. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_mcp/stdio_mcp_client.py +0 -0
  88. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_mcp/streamable_mcp_client.py +0 -0
  89. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_memory_organizer/__init__.py +0 -0
  90. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_memory_organizer/memory_organizer.py +0 -0
  91. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_methodology/main.py +0 -0
  92. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/__init__.py +0 -0
  93. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/ai8.py +0 -0
  94. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/human.py +0 -0
  95. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/kimi.py +0 -0
  96. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/openai.py +0 -0
  97. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/registry.py +0 -0
  98. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/tongyi.py +0 -0
  99. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
  100. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  101. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  102. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_platform_manager/service.py +0 -0
  103. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/__init__.py +0 -0
  104. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/cache.py +0 -0
  105. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/cli.py +0 -0
  106. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/embedding_manager.py +0 -0
  107. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/llm_interface.py +0 -0
  108. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/query_rewriter.py +0 -0
  109. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/rag_pipeline.py +0 -0
  110. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/reranker.py +0 -0
  111. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_rag/retriever.py +0 -0
  112. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  113. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  114. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_stats/__init__.py +0 -0
  115. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_stats/cli.py +0 -0
  116. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_stats/stats.py +0 -0
  117. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_stats/storage.py +0 -0
  118. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_stats/visualizer.py +0 -0
  119. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/__init__.py +0 -0
  120. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  121. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/base.py +0 -0
  122. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/clear_memory.py +0 -0
  123. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/cli/__init__.py +0 -0
  124. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/cli/main.py +0 -0
  125. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/execute_script.py +0 -0
  126. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
  127. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/generate_new_tool.py +0 -0
  128. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/methodology.py +0 -0
  129. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/read_code.py +0 -0
  130. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  131. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/retrieve_memory.py +0 -0
  132. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/save_memory.py +0 -0
  133. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/search_web.py +0 -0
  134. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
  135. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/__init__.py +0 -0
  136. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/builtin_replace_map.py +0 -0
  137. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/clipboard.py +0 -0
  138. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/embedding.py +0 -0
  139. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  140. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/fzf.py +0 -0
  141. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/git_utils.py +0 -0
  142. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/globals.py +0 -0
  143. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/http.py +0 -0
  144. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/methodology.py +0 -0
  145. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/output.py +0 -0
  146. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/tag.py +0 -0
  147. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis/jarvis_utils/utils.py +0 -0
  148. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  149. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  150. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  151. {jarvis_ai_assistant-0.4.0 → jarvis_ai_assistant-0.4.2}/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.4.0
3
+ Version: 0.4.2
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.4.0"
7
+ version = "0.4.2"
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.4.0",
6
+ version="0.4.2",
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.4.0"
4
+ __version__ = "0.4.2"
@@ -9,6 +9,7 @@ from pathlib import Path
9
9
  from enum import Enum
10
10
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
11
11
 
12
+
12
13
  # 第三方库导入
13
14
  from rich.align import Align
14
15
  from rich.console import Console
@@ -31,9 +32,10 @@ from jarvis.jarvis_agent.prompts import (
31
32
  TASK_ANALYSIS_PROMPT,
32
33
  )
33
34
  from jarvis.jarvis_tools.registry import ToolRegistry
35
+ from jarvis.jarvis_agent.edit_file_handler import EditFileHandler
36
+ from jarvis.jarvis_agent.rewrite_file_handler import RewriteFileHandler
34
37
  from jarvis.jarvis_agent.prompt_manager import PromptManager
35
38
  from jarvis.jarvis_agent.event_bus import EventBus
36
- from jarvis.jarvis_agent.config import AgentConfig
37
39
  from jarvis.jarvis_agent.run_loop import AgentRunLoop
38
40
  from jarvis.jarvis_agent.events import (
39
41
  BEFORE_SUMMARY,
@@ -65,7 +67,6 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
65
67
  # jarvis_utils 相关
66
68
  from jarvis.jarvis_utils.config import (
67
69
  get_data_dir,
68
- get_max_token_count,
69
70
  get_normal_model_name,
70
71
  get_normal_platform_name,
71
72
  is_execute_tool_confirm,
@@ -74,6 +75,8 @@ from jarvis.jarvis_utils.config import (
74
75
  is_use_methodology,
75
76
  get_tool_filter_threshold,
76
77
  get_after_tool_call_cb_dirs,
78
+
79
+
77
80
  )
78
81
  from jarvis.jarvis_utils.embedding import get_context_token_count
79
82
  from jarvis.jarvis_utils.globals import (
@@ -279,12 +282,16 @@ class Agent:
279
282
  use_tools: Optional[List[str]] = None,
280
283
  execute_tool_confirm: Optional[bool] = None,
281
284
  need_summary: bool = True,
285
+ auto_summary_rounds: Optional[int] = None,
282
286
  multiline_inputer: Optional[Callable[[str], str]] = None,
283
287
  use_methodology: Optional[bool] = None,
284
288
  use_analysis: Optional[bool] = None,
285
289
  force_save_memory: Optional[bool] = None,
286
290
  files: Optional[List[str]] = None,
287
291
  confirm_callback: Optional[Callable[[str, bool], bool]] = None,
292
+ non_interactive: Optional[bool] = None,
293
+ in_multi_agent: Optional[bool] = None,
294
+ **kwargs,
288
295
  ):
289
296
  """初始化Jarvis Agent实例
290
297
 
@@ -295,7 +302,6 @@ class Agent:
295
302
 
296
303
  summary_prompt: 任务总结提示模板
297
304
  auto_complete: 是否自动完成任务
298
- output_handler: 输出处理器列表
299
305
  execute_tool_confirm: 执行工具前是否需要确认
300
306
  need_summary: 是否需要生成总结
301
307
  multiline_inputer: 多行输入处理器
@@ -303,21 +309,38 @@ class Agent:
303
309
  use_analysis: 是否使用任务分析
304
310
  force_save_memory: 是否强制保存记忆
305
311
  confirm_callback: 用户确认回调函数,签名为 (tip: str, default: bool) -> bool;默认使用CLI的user_confirm
312
+ non_interactive: 是否以非交互模式运行(优先级最高,覆盖环境变量与配置)
306
313
  """
307
- # 基础属性初始化
308
- self.files = files or []
314
+ # 基础属性初始化(仅根据入参设置原始值;实际生效的默认回退在 _init_config 中统一解析)
315
+ # 标识与描述
309
316
  self.name = make_agent_name(name)
310
317
  self.description = description
311
318
  self.system_prompt = system_prompt
312
- self.need_summary = need_summary
313
- self.auto_complete = auto_complete
319
+ # 行为控制开关(原始入参值)
320
+ self.auto_complete = bool(auto_complete)
321
+ self.need_summary = bool(need_summary)
322
+ # 自动摘要轮次:None 表示使用配置文件中的默认值,由 AgentRunLoop 决定最终取值
323
+ self.auto_summary_rounds = auto_summary_rounds
324
+ self.use_methodology = use_methodology
325
+ self.use_analysis = use_analysis
326
+ self.execute_tool_confirm = execute_tool_confirm
327
+ self.summary_prompt = summary_prompt
328
+ self.force_save_memory = force_save_memory
329
+ # 资源与环境
330
+ self.model_group = model_group
331
+ self.files = files or []
332
+ self.use_tools = use_tools
333
+ self.non_interactive = non_interactive
334
+ # 多智能体运行标志:用于控制非交互模式下的自动完成行为
335
+ self.in_multi_agent = bool(in_multi_agent)
336
+ # 运行时状态
314
337
  self.first = True
315
338
  self.run_input_handlers_next_turn = False
316
339
  self.user_data: Dict[str, Any] = {}
317
340
 
318
341
 
319
342
  # 用户确认回调:默认使用 CLI 的 user_confirm,可由外部注入以支持 TUI/GUI
320
- self.user_confirm: Callable[[str, bool], bool] = (
343
+ self.confirm_callback: Callable[[str, bool], bool] = (
321
344
  confirm_callback or user_confirm # type: ignore[assignment]
322
345
  )
323
346
 
@@ -327,24 +350,62 @@ class Agent:
327
350
 
328
351
  # 初始化处理器
329
352
  self._init_handlers(
330
- output_handler or [],
331
353
  multiline_inputer,
354
+ output_handler,
332
355
  use_tools or [],
333
356
  )
334
357
  # 初始化用户交互封装,保持向后兼容
335
- self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.user_confirm)
358
+ self.user_interaction = UserInteractionHandler(self.multiline_inputer, self.confirm_callback)
336
359
  # 将确认函数指向封装后的 confirm,保持既有调用不变
337
- self.user_confirm = self.user_interaction.confirm # type: ignore[assignment]
338
-
339
- # 初始化配置
340
- self._init_config(
341
- use_methodology,
342
- use_analysis,
343
- execute_tool_confirm,
344
- summary_prompt,
345
- model_group,
346
- force_save_memory,
347
- )
360
+ self.confirm_callback = self.user_interaction.confirm # type: ignore[assignment]
361
+ # 非交互模式参数支持:允许通过构造参数显式控制,便于其他Agent调用时设置
362
+ try:
363
+ # 优先使用构造参数,其次回退到环境变量
364
+ self.non_interactive = (
365
+ bool(non_interactive)
366
+ if non_interactive is not None
367
+ else str(os.environ.get("JARVIS_NON_INTERACTIVE", "")).lower() in ("1", "true", "yes")
368
+ )
369
+ # 如果构造参数显式提供,则同步到环境变量与全局配置,供下游组件读取
370
+ if non_interactive is not None:
371
+ os.environ["JARVIS_NON_INTERACTIVE"] = "true" if self.non_interactive else "false"
372
+
373
+ except Exception:
374
+ # 防御式回退
375
+ self.non_interactive = False
376
+
377
+ # 初始化配置(直接解析,不再依赖 _init_config)
378
+ try:
379
+ resolved_use_methodology = bool(use_methodology if use_methodology is not None else is_use_methodology())
380
+ except Exception:
381
+ resolved_use_methodology = bool(use_methodology) if use_methodology is not None else True
382
+
383
+ try:
384
+ resolved_use_analysis = bool(use_analysis if use_analysis is not None else is_use_analysis())
385
+ except Exception:
386
+ resolved_use_analysis = bool(use_analysis) if use_analysis is not None else True
387
+
388
+ try:
389
+ resolved_execute_tool_confirm = bool(execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm())
390
+ except Exception:
391
+ resolved_execute_tool_confirm = bool(execute_tool_confirm) if execute_tool_confirm is not None else False
392
+
393
+ try:
394
+ resolved_force_save_memory = bool(force_save_memory if force_save_memory is not None else is_force_save_memory())
395
+ except Exception:
396
+ resolved_force_save_memory = bool(force_save_memory) if force_save_memory is not None else False
397
+
398
+ self.use_methodology = resolved_use_methodology
399
+ self.use_analysis = resolved_use_analysis
400
+ self.execute_tool_confirm = resolved_execute_tool_confirm
401
+ self.summary_prompt = (summary_prompt or DEFAULT_SUMMARY_PROMPT)
402
+ self.force_save_memory = resolved_force_save_memory
403
+ # 多智能体模式下,默认不自动完成(即使是非交互),仅在明确传入 auto_complete=True 时开启
404
+ if self.in_multi_agent:
405
+ self.auto_complete = bool(self.auto_complete)
406
+ else:
407
+ # 非交互模式下默认自动完成;否则保持传入的 auto_complete 值
408
+ self.auto_complete = bool(self.auto_complete or (self.non_interactive or False))
348
409
 
349
410
  # 初始化事件总线需先于管理器,以便管理器在构造中安全订阅事件
350
411
  self.event_bus = EventBus()
@@ -394,12 +455,12 @@ class Agent:
394
455
 
395
456
  def _init_handlers(
396
457
  self,
397
- output_handler: List[OutputHandlerProtocol],
398
458
  multiline_inputer: Optional[Callable[[str], str]],
459
+ output_handler: Optional[List[OutputHandlerProtocol]],
399
460
  use_tools: List[str],
400
461
  ):
401
462
  """初始化各种处理器"""
402
- self.output_handler = output_handler or [ToolRegistry()]
463
+ self.output_handler = output_handler or [ToolRegistry(), EditFileHandler(), RewriteFileHandler()]
403
464
  self.set_use_tools(use_tools)
404
465
  self.input_handler = [
405
466
  builtin_input_handler,
@@ -408,46 +469,6 @@ class Agent:
408
469
  ]
409
470
  self.multiline_inputer = multiline_inputer or get_multiline_input
410
471
 
411
- def _init_config(
412
- self,
413
- use_methodology: Optional[bool],
414
- use_analysis: Optional[bool],
415
- execute_tool_confirm: Optional[bool],
416
- summary_prompt: Optional[str],
417
- model_group: Optional[str],
418
- force_save_memory: Optional[bool],
419
- ):
420
- """初始化配置选项"""
421
- # 使用集中配置解析,保持与原逻辑一致
422
- cfg = AgentConfig(
423
- system_prompt=self.system_prompt,
424
- name=self.name,
425
- description=self.description,
426
- model_group=model_group,
427
- auto_complete=self.auto_complete,
428
- need_summary=self.need_summary,
429
- summary_prompt=summary_prompt,
430
- execute_tool_confirm=execute_tool_confirm,
431
- use_methodology=use_methodology,
432
- use_analysis=use_analysis,
433
- force_save_memory=force_save_memory,
434
- files=self.files,
435
- max_token_count=None,
436
- ).resolve_defaults()
437
-
438
- # 将解析结果回填到 Agent 实例属性,保持向后兼容
439
- self.use_methodology = bool(cfg.use_methodology)
440
- self.use_analysis = bool(cfg.use_analysis)
441
- self.execute_tool_confirm = bool(cfg.execute_tool_confirm)
442
- self.summary_prompt = cfg.summary_prompt or DEFAULT_SUMMARY_PROMPT
443
- self.max_token_count = int(cfg.max_token_count or get_max_token_count(model_group))
444
- self.force_save_memory = bool(cfg.force_save_memory)
445
- # 非交互模式下自动完成标志需要同步到 Agent 实例,避免循环
446
- self.auto_complete = bool(cfg.auto_complete)
447
-
448
- # 聚合配置到 AgentConfig,作为后续单一事实来源(保持兼容,不改变既有属性使用)
449
- self.config = cfg
450
-
451
472
  def _setup_system_prompt(self):
452
473
  """设置系统提示词"""
453
474
  try:
@@ -707,14 +728,9 @@ class Agent:
707
728
  return message
708
729
 
709
730
  def _manage_conversation_length(self, message: str) -> str:
710
- """管理对话长度,必要时进行摘要"""
731
+ """管理对话长度计数;摘要触发由轮次在 AgentRunLoop 中统一处理。"""
711
732
  self.session.conversation_length += get_context_token_count(message)
712
733
 
713
- if self.session.conversation_length > self.max_token_count:
714
- summary = self._summarize_and_clear_history()
715
- if summary:
716
- message = join_prompts([summary, message])
717
- self.session.conversation_length = get_context_token_count(message)
718
734
 
719
735
  return message
720
736
 
@@ -900,13 +916,17 @@ class Agent:
900
916
 
901
917
  if self.need_summary:
902
918
 
903
- self.session.prompt = self.summary_prompt
919
+ # 确保总结提示词非空:若为None或仅空白,则回退到默认提示词
920
+ safe_summary_prompt = self.summary_prompt or ""
921
+ if isinstance(safe_summary_prompt, str) and safe_summary_prompt.strip() == "":
922
+ safe_summary_prompt = DEFAULT_SUMMARY_PROMPT
923
+ # 注意:不要写回 session.prompt,避免 BEFORE_SUMMARY 事件回调修改/清空后导致使用空prompt
904
924
  # 广播将要生成总结事件
905
925
  try:
906
926
  self.event_bus.emit(
907
927
  BEFORE_SUMMARY,
908
928
  agent=self,
909
- prompt=self.session.prompt,
929
+ prompt=safe_summary_prompt,
910
930
  auto_completed=auto_completed,
911
931
  need_summary=self.need_summary,
912
932
  )
@@ -915,7 +935,8 @@ class Agent:
915
935
 
916
936
  if not self.model:
917
937
  raise RuntimeError("Model not initialized")
918
- ret = self.model.chat_until_success(self.session.prompt) # type: ignore
938
+ # 直接使用本地变量,避免受事件回调影响
939
+ ret = self.model.chat_until_success(safe_summary_prompt) # type: ignore
919
940
  # 防御: 总结阶段模型可能返回空响应(None或空字符串),统一为空字符串并告警
920
941
  if not ret:
921
942
  try:
@@ -1066,7 +1087,7 @@ class Agent:
1066
1087
  return self._complete_task(auto_completed=False)
1067
1088
 
1068
1089
  if any(handler.can_handle(current_response) for handler in self.output_handler):
1069
- if self.user_confirm("检测到有工具调用,是否继续处理工具调用?", True):
1090
+ if self.confirm_callback("检测到有工具调用,是否继续处理工具调用?", True):
1070
1091
  self.session.prompt = join_prompts([
1071
1092
  f"被用户中断,用户补充信息为:{user_input}",
1072
1093
  "用户同意继续工具调用。"
@@ -1293,7 +1314,7 @@ class Agent:
1293
1314
  f"并且存在3个以上标签重叠的记忆。\n"
1294
1315
  f"是否立即整理记忆库以优化性能和相关性?"
1295
1316
  )
1296
- if self.user_confirm(prompt, True):
1317
+ if self.confirm_callback(prompt, True):
1297
1318
  PrettyOutput.print(
1298
1319
  f"正在开始整理 '{scope_name}' ({memory_type}) 记忆库...",
1299
1320
  OutputType.INFO,
@@ -16,7 +16,7 @@ from jarvis.jarvis_agent.file_context_handler import file_context_handler
16
16
  from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
17
17
  from jarvis.jarvis_agent.task_manager import TaskManager
18
18
  from jarvis.jarvis_tools.registry import ToolRegistry
19
- from jarvis.jarvis_utils.config import is_non_interactive
19
+ from jarvis.jarvis_utils.config import is_non_interactive, is_skip_predefined_tasks
20
20
 
21
21
 
22
22
  class AgentManager:
@@ -31,6 +31,7 @@ class AgentManager:
31
31
  use_analysis: Optional[bool] = None,
32
32
  multiline_inputer: Optional[Callable[[str], str]] = None,
33
33
  confirm_callback: Optional[Callable[[str, bool], bool]] = None,
34
+ non_interactive: Optional[bool] = None,
34
35
  ):
35
36
  self.model_group = model_group
36
37
  self.tool_group = tool_group
@@ -41,6 +42,7 @@ class AgentManager:
41
42
  # 可选:注入输入与确认回调,用于Web模式等前端替代交互
42
43
  self.multiline_inputer = multiline_inputer
43
44
  self.confirm_callback = confirm_callback
45
+ self.non_interactive = non_interactive
44
46
 
45
47
  def initialize(self) -> Agent:
46
48
  """初始化Agent"""
@@ -53,12 +55,12 @@ class AgentManager:
53
55
  self.agent = Agent(
54
56
  system_prompt=origin_agent_system_prompt,
55
57
  model_group=self.model_group,
56
- output_handler=[ToolRegistry()], # type: ignore
57
58
  need_summary=False,
58
59
  use_methodology=self.use_methodology,
59
60
  use_analysis=self.use_analysis,
60
61
  multiline_inputer=self.multiline_inputer,
61
62
  confirm_callback=self.confirm_callback,
63
+ non_interactive=self.non_interactive,
62
64
  )
63
65
 
64
66
  # 尝试恢复会话
@@ -80,8 +82,8 @@ class AgentManager:
80
82
  self.agent.run(task_content)
81
83
  raise typer.Exit(code=0)
82
84
 
83
- # 处理预定义任务(非交互模式下跳过)
84
- if not is_non_interactive() and self.agent.first:
85
+ # 处理预定义任务(非交互模式下跳过;支持配置跳过加载)
86
+ if not is_non_interactive() and not is_skip_predefined_tasks() and self.agent.first:
85
87
  task_manager = TaskManager()
86
88
  tasks = task_manager.load_tasks()
87
89
  if tasks and (selected_task := task_manager.select_task(tasks)):
@@ -92,10 +92,10 @@ class EditFileHandler(OutputHandler):
92
92
  if not patches:
93
93
  return False, "未找到有效的文件编辑指令"
94
94
 
95
- # 记录 edit_file 工具调用统计
95
+ # 记录 PATCH 操作调用统计
96
96
  from jarvis.jarvis_stats.stats import StatsManager
97
97
 
98
- StatsManager.increment("edit_file", group="tool")
98
+ StatsManager.increment("patch", group="tool")
99
99
 
100
100
  results = []
101
101
 
@@ -595,7 +595,10 @@ def handle_builtin_config_selector(
595
595
 
596
596
  elif sel["category"] == "multi_agent":
597
597
  # jarvis-multi-agent 需要 -c/--config,用户输入通过 -i/--input 传递
598
+ # 同时传递 -g/--llm-group 以继承 jvs 的模型组选择
598
599
  args = [str(sel["cmd"]), "-c", str(sel["file"])]
600
+ if model_group:
601
+ args += ["-g", str(model_group)]
599
602
  if task:
600
603
  args += ["-i", str(task)]
601
604
 
@@ -967,14 +970,14 @@ def run_cli(
967
970
  return
968
971
 
969
972
  # 在初始化环境前检测Git仓库,并可选择自动切换到代码开发模式(jca)
970
- if not non_interactive and not web:
973
+ if not non_interactive:
971
974
  try_switch_to_jca_if_git_repo(
972
975
  model_group, tool_group, config_file, restore_session, task
973
976
  )
974
977
 
975
978
  # 在进入默认通用代理前,列出内置配置供选择(agent/multi_agent/roles)
976
979
  # 非交互模式下跳过内置角色/配置选择
977
- if not non_interactive and not web:
980
+ if not non_interactive:
978
981
  handle_builtin_config_selector(model_group, tool_group, config_file, task)
979
982
 
980
983
  # 初始化环境
@@ -1005,13 +1008,9 @@ def run_cli(
1005
1008
  # 在 Web 模式下注入基于 WebSocket 的输入/确认回调
1006
1009
  extra_kwargs = {}
1007
1010
  if web:
1008
- try:
1009
- from jarvis.jarvis_agent.web_bridge import web_multiline_input, web_user_confirm
1010
- extra_kwargs["multiline_inputer"] = web_multiline_input
1011
- extra_kwargs["confirm_callback"] = web_user_confirm
1012
- except Exception as e:
1013
- PrettyOutput.print(f"Web 模式初始化失败(加载 Web 桥接模块): {e}", OutputType.ERROR)
1014
- raise typer.Exit(code=1)
1011
+ # 纯 xterm 交互模式:不注入 WebBridge 的输入/确认回调,避免阻塞等待浏览器响应
1012
+ #(交互由 /terminal PTY 会话中的 jvs 进程处理)
1013
+ pass
1015
1014
 
1016
1015
  agent_manager = AgentManager(
1017
1016
  model_group=model_group,
@@ -1019,6 +1018,7 @@ def run_cli(
1019
1018
  restore_session=restore_session,
1020
1019
  use_methodology=False if disable_methodology_analysis else None,
1021
1020
  use_analysis=False if disable_methodology_analysis else None,
1021
+ non_interactive=non_interactive,
1022
1022
  **extra_kwargs,
1023
1023
  )
1024
1024
  agent = agent_manager.initialize()
@@ -1051,6 +1051,37 @@ def run_cli(
1051
1051
  enable_web_stdin_redirect()
1052
1052
  except Exception:
1053
1053
  pass
1054
+ # 记录用于交互式终端(PTY)重启的 jvs 启动命令(移除 web 相关参数)
1055
+ try:
1056
+ import sys as _sys, os as _os, json as _json
1057
+ _argv = list(_sys.argv)
1058
+ # 去掉程序名(argv[0]),并过滤 --web 相关参数
1059
+ filtered = []
1060
+ i = 1
1061
+ while i < len(_argv):
1062
+ a = _argv[i]
1063
+ if a == "--web" or a.startswith("--web="):
1064
+ i += 1
1065
+ continue
1066
+ if a == "--web-host":
1067
+ i += 2
1068
+ continue
1069
+ if a.startswith("--web-host="):
1070
+ i += 1
1071
+ continue
1072
+ if a == "--web-port":
1073
+ i += 2
1074
+ continue
1075
+ if a.startswith("--web-port="):
1076
+ i += 1
1077
+ continue
1078
+ filtered.append(a)
1079
+ i += 1
1080
+ # 使用 jvs 命令作为可执行文件,保留其余业务参数
1081
+ cmd = ["jvs"] + filtered
1082
+ _os.environ["JARVIS_WEB_LAUNCH_JSON"] = _json.dumps(cmd, ensure_ascii=False)
1083
+ except Exception:
1084
+ pass
1054
1085
  PrettyOutput.print("以 Web 模式启动,请在浏览器中打开提供的地址进行交互。", OutputType.INFO)
1055
1086
  # 启动 Web 服务(阻塞调用)
1056
1087
  start_web_server(agent_manager, host=web_host, port=web_port)
@@ -0,0 +1,143 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ import re
4
+ from typing import Any, Dict, List, Tuple
5
+
6
+ from jarvis.jarvis_agent.output_handler import OutputHandler
7
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
+ from jarvis.jarvis_utils.tag import ct, ot
9
+
10
+
11
+ class RewriteFileHandler(OutputHandler):
12
+ """
13
+ 处理整文件重写指令的输出处理器。
14
+
15
+ 指令格式:
16
+ <REWRITE file=文件路径>
17
+ 新的文件完整内容
18
+ </REWRITE>
19
+
20
+ 等价支持以下写法:
21
+ <REWRITE file=文件路径>
22
+ 新的文件完整内容
23
+ </REWRITE>
24
+
25
+ 说明:
26
+ - 该处理器用于完全重写文件内容,适用于新增文件或大范围改写
27
+ - 内部直接执行写入,提供失败回滚能力
28
+ - 支持同一响应中包含多个 REWRITE/REWRITE 块
29
+ """
30
+
31
+ def __init__(self) -> None:
32
+ # 允许 file 参数为单引号、双引号或无引号
33
+ self.rewrite_pattern_file = re.compile(
34
+ ot("REWRITE file=(?:'([^']+)'|\"([^\"]+)\"|([^>]+))")
35
+ + r"\s*"
36
+ + r"(.*?)"
37
+ + r"\s*"
38
+ + r"^"
39
+ + ct("REWRITE"),
40
+ re.DOTALL | re.MULTILINE,
41
+ )
42
+
43
+ def name(self) -> str:
44
+ """获取处理器名称,用于操作列表展示"""
45
+ return "REWRITE"
46
+
47
+ def prompt(self) -> str:
48
+ """返回用户提示,描述使用方法与格式"""
49
+ return f"""文件重写指令格式:
50
+ {ot("REWRITE file=文件路径")}
51
+ 新的文件完整内容
52
+ {ct("REWRITE")}
53
+
54
+ 注意:
55
+ - {ot("REWRITE")}、{ct("REWRITE")} 必须出现在行首,否则不生效(会被忽略)
56
+ - 整文件重写会完全替换文件内容,如需局部修改请使用 PATCH 操作
57
+ - 该操作由处理器直接执行,具备失败回滚能力"""
58
+
59
+ def can_handle(self, response: str) -> bool:
60
+ """判断响应中是否包含 REWRITE/REWRITE 指令"""
61
+ return bool(self.rewrite_pattern_file.search(response))
62
+
63
+ def handle(self, response: str, agent: Any) -> Tuple[bool, str]:
64
+ """解析并执行整文件重写指令"""
65
+ rewrites = self._parse_rewrites(response)
66
+ if not rewrites:
67
+ return False, "未找到有效的文件重写指令"
68
+
69
+ # 记录 REWRITE 操作调用统计
70
+ try:
71
+ from jarvis.jarvis_stats.stats import StatsManager
72
+
73
+ StatsManager.increment("rewrite_file", group="tool")
74
+ except Exception:
75
+ # 统计失败不影响主流程
76
+ pass
77
+
78
+ results: List[str] = []
79
+ overall_success = True
80
+
81
+ for file_path, content in rewrites:
82
+ abs_path = os.path.abspath(file_path)
83
+ original_content = None
84
+ processed = False
85
+ try:
86
+ file_exists = os.path.exists(abs_path)
87
+ if file_exists:
88
+ with open(abs_path, "r", encoding="utf-8") as rf:
89
+ original_content = rf.read()
90
+ os.makedirs(os.path.dirname(abs_path), exist_ok=True)
91
+ with open(abs_path, "w", encoding="utf-8") as wf:
92
+ wf.write(content)
93
+ processed = True
94
+ results.append(f"✅ 文件 {abs_path} 重写成功")
95
+ # 记录成功处理的文件(使用绝对路径)
96
+ if agent:
97
+ files = agent.get_user_data("files")
98
+ if files:
99
+ if abs_path not in files:
100
+ files.append(abs_path)
101
+ else:
102
+ files = [abs_path]
103
+ agent.set_user_data("files", files)
104
+ except Exception as e:
105
+ overall_success = False
106
+ # 回滚已修改内容
107
+ try:
108
+ if processed:
109
+ if original_content is None:
110
+ if os.path.exists(abs_path):
111
+ os.remove(abs_path)
112
+ else:
113
+ with open(abs_path, "w", encoding="utf-8") as wf:
114
+ wf.write(original_content)
115
+ except Exception:
116
+ pass
117
+ PrettyOutput.print(f"文件重写失败: {str(e)}", OutputType.ERROR)
118
+ results.append(f"❌ 文件 {abs_path} 重写失败: {str(e)}")
119
+
120
+ summary = "\n".join(results)
121
+ # 按现有 EditFileHandler 约定,始终返回 (False, summary) 以继续主循环
122
+ return False, summary
123
+
124
+ def _parse_rewrites(self, response: str) -> List[Tuple[str, str]]:
125
+ """
126
+ 解析响应中的 REWRITE/REWRITE 指令块。
127
+ 返回列表 [(file_path, content), ...],按在响应中的出现顺序排序
128
+ """
129
+ items: List[Tuple[str, str]] = []
130
+ matches: List[Tuple[int, Any]] = []
131
+ for m in self.rewrite_pattern_file.finditer(response):
132
+ matches.append((m.start(), m))
133
+
134
+ # 按出现顺序排序
135
+ matches.sort(key=lambda x: x[0])
136
+
137
+ for _, m in matches:
138
+ file_path = m.group(1) or m.group(2) or m.group(3) or ""
139
+ file_path = file_path.strip()
140
+ content = m.group(4)
141
+ if file_path:
142
+ items.append((file_path, content))
143
+ return items