jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +243 -139
  3. jarvis/jarvis_agent/agent_manager.py +5 -10
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +265 -15
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +113 -98
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +6 -12
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +77 -14
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +12 -21
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/task_analyzer.py +26 -4
  31. jarvis/jarvis_agent/task_manager.py +11 -27
  32. jarvis/jarvis_agent/tool_executor.py +2 -3
  33. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  34. jarvis/jarvis_agent/web_server.py +55 -20
  35. jarvis/jarvis_c2rust/__init__.py +5 -5
  36. jarvis/jarvis_c2rust/cli.py +461 -499
  37. jarvis/jarvis_c2rust/collector.py +45 -53
  38. jarvis/jarvis_c2rust/constants.py +26 -0
  39. jarvis/jarvis_c2rust/library_replacer.py +264 -132
  40. jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
  41. jarvis/jarvis_c2rust/loaders.py +207 -0
  42. jarvis/jarvis_c2rust/models.py +28 -0
  43. jarvis/jarvis_c2rust/optimizer.py +1592 -395
  44. jarvis/jarvis_c2rust/transpiler.py +1722 -1064
  45. jarvis/jarvis_c2rust/utils.py +385 -0
  46. jarvis/jarvis_code_agent/build_validation_config.py +2 -3
  47. jarvis/jarvis_code_agent/code_agent.py +394 -320
  48. jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
  61. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
  62. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
  63. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
  64. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
  65. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  66. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
  68. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
  69. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  70. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
  71. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  72. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
  73. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
  74. jarvis/jarvis_code_agent/lint.py +258 -27
  75. jarvis/jarvis_code_agent/utils.py +0 -1
  76. jarvis/jarvis_code_analysis/code_review.py +19 -24
  77. jarvis/jarvis_data/config_schema.json +53 -26
  78. jarvis/jarvis_git_squash/main.py +4 -5
  79. jarvis/jarvis_git_utils/git_commiter.py +44 -49
  80. jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
  81. jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
  82. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  83. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  84. jarvis/jarvis_methodology/main.py +32 -48
  85. jarvis/jarvis_multi_agent/__init__.py +79 -61
  86. jarvis/jarvis_multi_agent/main.py +3 -7
  87. jarvis/jarvis_platform/base.py +469 -199
  88. jarvis/jarvis_platform/human.py +7 -8
  89. jarvis/jarvis_platform/kimi.py +30 -36
  90. jarvis/jarvis_platform/openai.py +65 -27
  91. jarvis/jarvis_platform/registry.py +26 -10
  92. jarvis/jarvis_platform/tongyi.py +24 -25
  93. jarvis/jarvis_platform/yuanbao.py +31 -42
  94. jarvis/jarvis_platform_manager/main.py +66 -77
  95. jarvis/jarvis_platform_manager/service.py +8 -13
  96. jarvis/jarvis_rag/cli.py +49 -51
  97. jarvis/jarvis_rag/embedding_manager.py +13 -18
  98. jarvis/jarvis_rag/llm_interface.py +8 -9
  99. jarvis/jarvis_rag/query_rewriter.py +10 -21
  100. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  101. jarvis/jarvis_rag/reranker.py +4 -5
  102. jarvis/jarvis_rag/retriever.py +28 -30
  103. jarvis/jarvis_sec/__init__.py +220 -3520
  104. jarvis/jarvis_sec/agents.py +143 -0
  105. jarvis/jarvis_sec/analysis.py +276 -0
  106. jarvis/jarvis_sec/cli.py +29 -6
  107. jarvis/jarvis_sec/clustering.py +1439 -0
  108. jarvis/jarvis_sec/file_manager.py +427 -0
  109. jarvis/jarvis_sec/parsers.py +73 -0
  110. jarvis/jarvis_sec/prompts.py +268 -0
  111. jarvis/jarvis_sec/report.py +83 -4
  112. jarvis/jarvis_sec/review.py +453 -0
  113. jarvis/jarvis_sec/utils.py +499 -0
  114. jarvis/jarvis_sec/verification.py +848 -0
  115. jarvis/jarvis_sec/workflow.py +7 -0
  116. jarvis/jarvis_smart_shell/main.py +38 -87
  117. jarvis/jarvis_stats/cli.py +1 -1
  118. jarvis/jarvis_stats/stats.py +7 -7
  119. jarvis/jarvis_stats/storage.py +15 -21
  120. jarvis/jarvis_tools/clear_memory.py +3 -20
  121. jarvis/jarvis_tools/cli/main.py +20 -23
  122. jarvis/jarvis_tools/edit_file.py +1066 -0
  123. jarvis/jarvis_tools/execute_script.py +42 -21
  124. jarvis/jarvis_tools/file_analyzer.py +6 -9
  125. jarvis/jarvis_tools/generate_new_tool.py +11 -20
  126. jarvis/jarvis_tools/lsp_client.py +1552 -0
  127. jarvis/jarvis_tools/methodology.py +2 -3
  128. jarvis/jarvis_tools/read_code.py +1525 -87
  129. jarvis/jarvis_tools/read_symbols.py +2 -3
  130. jarvis/jarvis_tools/read_webpage.py +7 -10
  131. jarvis/jarvis_tools/registry.py +370 -181
  132. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  133. jarvis/jarvis_tools/rewrite_file.py +105 -0
  134. jarvis/jarvis_tools/save_memory.py +3 -15
  135. jarvis/jarvis_tools/search_web.py +3 -7
  136. jarvis/jarvis_tools/sub_agent.py +17 -6
  137. jarvis/jarvis_tools/sub_code_agent.py +14 -16
  138. jarvis/jarvis_tools/virtual_tty.py +54 -32
  139. jarvis/jarvis_utils/clipboard.py +7 -10
  140. jarvis/jarvis_utils/config.py +98 -63
  141. jarvis/jarvis_utils/embedding.py +5 -5
  142. jarvis/jarvis_utils/fzf.py +8 -8
  143. jarvis/jarvis_utils/git_utils.py +81 -67
  144. jarvis/jarvis_utils/input.py +24 -49
  145. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  146. jarvis/jarvis_utils/methodology.py +33 -35
  147. jarvis/jarvis_utils/utils.py +245 -202
  148. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/METADATA +205 -70
  149. jarvis_ai_assistant-0.7.8.dist-info/RECORD +218 -0
  150. jarvis/jarvis_agent/edit_file_handler.py +0 -584
  151. jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
  152. jarvis/jarvis_agent/task_planner.py +0 -496
  153. jarvis/jarvis_platform/ai8.py +0 -332
  154. jarvis/jarvis_tools/ask_user.py +0 -54
  155. jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
  156. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/WHEEL +0 -0
  157. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/entry_points.txt +0 -0
  158. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/licenses/LICENSE +0 -0
  159. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/top_level.txt +0 -0
@@ -9,7 +9,11 @@ DEFAULT_SUMMARY_PROMPT = """<report>
9
9
  2. 执行结果:成功/失败
10
10
  3. 关键信息:执行过程中提取的重要信息
11
11
  4. 重要发现:任何值得注意的发现
12
- 5. 后续建议:如果有的话
12
+ 5. 无效方案总结:如果当前是在修复问题,请总结尝试过但无效的方案,避免后续重复尝试
13
+ - 已尝试的方法及其失败原因
14
+ - 排除的错误假设
15
+ - 不可行的解决路径
16
+ 6. 后续建议:如果有的话
13
17
  </content>
14
18
 
15
19
  <format>
@@ -20,44 +24,198 @@ DEFAULT_SUMMARY_PROMPT = """<report>
20
24
 
21
25
  SUMMARY_REQUEST_PROMPT = """<summary_request>
22
26
  <objective>
23
- 请对当前对话历史进行简明扼要的总结,提取关键信息和重要决策点。这个总结将作为上下文继续任务,因此需要保留对后续对话至关重要的内容。
27
+ 请对当前对话历史进行精准总结,核心目标是为后续对话提供“无关键信息缺失”的上下文支撑:既要提炼核心逻辑,又要完整保留影响后续决策/操作的关键细节,确保后续对话无需回溯原始历史即可顺畅推进。
24
28
  </objective>
25
29
 
26
30
  <guidelines>
27
- 1. 提取关键信息:任务目标、已确定的事实、重要决策、达成的共识
28
- 2. 保留技术细节:命令、代码片段、文件路径、配置设置等技术细节
29
- 3. 记录任务进展:已完成的步骤、当前所处阶段、待解决的问题
30
- 4. 包含用户偏好:用户表达的明确偏好、限制条件或特殊要求
31
- 5. 省略冗余内容:问候语、重复信息、不相关的讨论
31
+ #### 一、必保保留的关键信息(按优先级排序,不可遗漏)
32
+ 1. 核心目标与边界:用户最终要完成的任务(含量化指标,如“3天内实现接口”“QPS≥1000”)、明确排除的范围(如“暂不支持批量上传”);
33
+ 2. 已确认的关键事实:技术栈(含版本,如“Python 3.9 + Django 4.2”)、环境配置(如“测试环境地址:http://test.example.com”)、数据/参数(如“数据库表名:user_info,分页大小:20条”);
34
+ 3. 重要决策与共识:双方确认的方案(如“选用JWT做身份验证”)、否定的方案(如“排除Redis集群,用单机缓存”)、决策依据(如“因团队无K8s运维经验,选择Docker Compose”);
35
+ 4. 技术细节(精准保留,不简化):
36
+ - 可直接复用的内容:完整命令(如“pip install requests==2.31.0”)、代码片段(关键逻辑,用`代码块`标注)、文件路径(如“/data/logs/app.log”)、接口地址/参数(如“POST /api/login,必填字段:phone/code”);
37
+ - 报错与调试信息:错误类型(如“IndexError”)、报错关键词(如“list index out of range”)、已尝试的有效/无效操作(如“修改索引为[-1]无效,更换httpx库报错消失”);
38
+ 5. 任务进展与待办:
39
+ - 已完成步骤(如“已完成数据库表设计,已编写登录接口草稿”);
40
+ - 待解决问题(明确优先级,如“高:跨域问题未处理;中:异常捕获逻辑待补充”);
41
+ - 待确认/待补充信息(明确责任人与需求,如“用户需提供:测试数据库账号;助手需补充:接口文档示例”);
42
+ 6. 用户偏好与约束:明确要求(如“代码需加注释”“输出JSON格式”)、限制条件(如“服务器内存4GB”“需兼容Windows 10”)、禁忌项(如“不可使用第三方ORM”)。
43
+
44
+ #### 二、可省略的冗余内容(无需保留)
45
+ - 寒暄与无关闲聊(如“您好”“谢谢”“今天天气不错”);
46
+ - 重复表述(用户多次强调的同一需求,仅保留1次核心表述);
47
+ - 临时试错/未落地的想法(如“我先试试这个思路”“可能用XX方案”,未确认的不保留);
48
+ - 与任务无关的细节(如“用户提及的其他项目经验”“无关的技术科普”)。
32
49
  </guidelines>
33
50
 
34
51
  <format>
35
- - 使用简洁、客观的语言
36
- - 按时间顺序或主题组织信息
37
- - 使用要点列表增强可读性
38
- - 总结应控制在500词以内
52
+ 1. 语言风格:简洁、客观、专业,使用编程领域规范表述(如“非阻塞IO”而非“不等待的输入输出”);
53
+ 2. 结构组织:按“核心目标→已确认事实→决策与共识→技术细节→任务进展→待办事项→用户约束”的逻辑组织(替代“时间顺序”,更贴合后续对话需求);
54
+ 3. 呈现形式:分点列出,关键技术内容用`代码块`/加粗标注,待办事项用“【优先级】+ 内容 + 责任人”明确(如“【高】补充跨域配置 - 助手”);
55
+ 4. 长度限制:严格控制在500词以内,优先压缩冗余,不压缩必保信息(若必保信息较多,可适当放宽至600词)。
39
56
  </format>
40
57
  </summary_request>
41
58
  """
42
59
 
43
60
 
44
- TASK_ANALYSIS_PROMPT = f"""<task_analysis>
45
- <request>
46
- 当前任务已结束,请按以下步骤分析该任务:
47
-
48
- 第一步:记忆值得保存的信息
61
+ def get_task_analysis_prompt(
62
+ has_save_memory: bool = False,
63
+ has_generate_new_tool: bool = False
64
+ ) -> str:
65
+ """根据配置返回任务分析提示词
66
+
67
+ 参数:
68
+ has_save_memory: 是否有 save_memory 工具(工具可用性)
69
+ has_generate_new_tool: 是否有 generate_new_tool 工具
70
+ """
71
+ # 第一步:记忆保存部分
72
+ if not has_save_memory:
73
+ # 如果没有 save_memory 工具,说明无法保存记忆
74
+ memory_step = """第一步:记忆值得保存的信息
75
+ 1. 识别任务中的关键信息和知识点
76
+ 2. 评估是否有值得保存的项目长期记忆或全局长期记忆
77
+ 3. 注意:当前环境不支持 save_memory 工具,无法保存记忆。请直接说明识别到的关键信息即可。"""
78
+ else:
79
+ # 有 save_memory 工具
80
+ memory_step = """第一步:记忆值得保存的信息
49
81
  1. 识别任务中的关键信息和知识点
50
82
  2. 评估是否有值得保存的项目长期记忆或全局长期记忆
51
- 3. 使用 save_memory 工具保存有价值的信息:
83
+ 3. 如果有价值,使用 save_memory 工具保存有价值的信息:
52
84
  - project_long_term: 保存与当前项目相关的长期信息(如项目配置、架构决策、开发规范等)
53
- - global_long_term: 保存通用的信息、用户偏好、知识或方法(如技术知识、最佳实践、用户习惯等)
54
-
55
- 第二步:分析任务解决方案
85
+ - global_long_term: 保存通用的信息、用户偏好、知识或方法(如技术知识、最佳实践、用户习惯等)"""
86
+
87
+ # 第二步:工具/方法论分析部分
88
+ if has_generate_new_tool:
89
+ solution_step = """第二步:分析任务解决方案
90
+ 1. 检查现有工具或方法论是否已经可以完成该任务,如果可以,直接说明即可,无需生成新内容
91
+ 2. 如果现有工具/方法论不足,评估当前任务是否可以通过编写新工具来自动化解决
92
+ 3. 如果可以通过工具解决,请使用 generate_new_tool 工具创建新工具:
93
+ - 使用 generate_new_tool 工具,传入 tool_name 和 tool_code 参数
94
+ - tool_code 应包含完整的工具类定义,遵循工具代码要求
95
+ 4. 如果无法通过编写通用工具完成,评估当前的执行流程是否可以总结为通用方法论
96
+ 5. 如果以上都不可行,给出详细理由"""
97
+ else:
98
+ solution_step = """第二步:分析任务解决方案
56
99
  1. 检查现有工具或方法论是否已经可以完成该任务,如果可以,直接说明即可,无需生成新内容
57
100
  2. 如果现有工具/方法论不足,评估当前任务是否可以通过编写新工具来自动化解决
58
- 3. 如果可以通过工具解决,请设计并提供工具代码
101
+ 3. 如果可以通过工具解决,请设计并提供工具代码(注意:当前环境不支持 generate_new_tool 工具,需要手动创建工具文件)
59
102
  4. 如果无法通过编写通用工具完成,评估当前的执行流程是否可以总结为通用方法论
60
- 5. 如果以上都不可行,给出详细理由
103
+ 5. 如果以上都不可行,给出详细理由"""
104
+
105
+ # 输出要求部分
106
+ if has_generate_new_tool:
107
+ output_requirements = f"""<output_requirements>
108
+ 根据分析结果,输出以下三种情况之一:
109
+ 1. 如果现有工具/方法论可以解决,直接输出说明:
110
+ 已有工具/方法论可以解决该问题,无需创建新内容。
111
+ 可用的工具/方法论:[列出工具名称或方法论名称]
112
+ 使用方法:[简要说明如何使用]
113
+ 2. 工具创建(如果需要创建新工具):
114
+ {ot("TOOL_CALL")}
115
+ {{
116
+ "want": "创建新工具来解决XXX问题",
117
+ "name": "generate_new_tool",
118
+ "arguments": {{
119
+ "tool_name": "工具名称",
120
+ "tool_code": `# -*- coding: utf-8 -*-
121
+ from typing import Dict, Any
122
+
123
+ class 工具名称:
124
+ name = "工具名称"
125
+ description = "Tool description"
126
+ parameters = {{
127
+ "type": "object",
128
+ "properties": {{
129
+ # 参数定义
130
+ }},
131
+ "required": []
132
+ }}
133
+ @staticmethod
134
+ def check() -> bool:
135
+ return True
136
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
137
+ try:
138
+ # 使用print显示执行过程
139
+ print("ℹ️ 开始执行操作...")
140
+ # 实现逻辑
141
+ # ...
142
+ print("✅ 操作已完成")
143
+ return {{
144
+ "success": True,
145
+ "stdout": "结果输出",
146
+ "stderr": ""
147
+ }}
148
+ except Exception as e:
149
+ print(f"❌ 操作失败: {{str(e)}}")
150
+ return {{
151
+ "success": False,
152
+ "stdout": "",
153
+ "stderr": f"操作失败: {{str(e)}}"
154
+ }}`
155
+ }}
156
+ }}
157
+ {ct("TOOL_CALL")}
158
+
159
+ 注意:tool_code 参数推荐使用 ||| 或 ``` 分隔符包裹多行代码,直接换行无需转义,支持保留缩进。
160
+ 3. 方法论创建(如果需要创建新方法论):
161
+ {ot("TOOL_CALL")}
162
+ {{
163
+ "want": "添加/更新xxxx的方法论",
164
+ "name": "methodology",
165
+ "arguments": {{
166
+ "operation": "add/update",
167
+ "problem_type": "方法论类型,不要过于细节,也不要过于泛化",
168
+ "content": |||
169
+ 方法论内容
170
+ 可以包含多行内容
171
+ 推荐使用 ||| 或 ``` 分隔符包裹多行字符串,直接换行无需转义,支持保留缩进
172
+ 包含"双引号"和'单引号'都无需转义
173
+ |||
174
+ }}
175
+ }}
176
+ {ct("TOOL_CALL")}
177
+
178
+ 注意:如果 content 参数包含多行内容,推荐使用 ||| 或 ``` 分隔符包裹,直接换行无需转义,支持保留缩进。
179
+ 如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
180
+ </output_requirements>"""
181
+ else:
182
+ output_requirements = f"""<output_requirements>
183
+ 根据分析结果,输出以下三种情况之一:
184
+ 1. 如果现有工具/方法论可以解决,直接输出说明:
185
+ 已有工具/方法论可以解决该问题,无需创建新内容。
186
+ 可用的工具/方法论:[列出工具名称或方法论名称]
187
+ 使用方法:[简要说明如何使用]
188
+ 2. 工具创建(如果需要创建新工具):
189
+ 注意:当前环境不支持 generate_new_tool 工具。如果需要创建新工具,请提供完整的工具代码和说明,用户需要手动创建工具文件。
190
+ 3. 方法论创建(如果需要创建新方法论):
191
+ {ot("TOOL_CALL")}
192
+ {{
193
+ "want": "添加/更新xxxx的方法论",
194
+ "name": "methodology",
195
+ "arguments": {{
196
+ "operation": "add/update",
197
+ "problem_type": "方法论类型,不要过于细节,也不要过于泛化",
198
+ "content": |||
199
+ 方法论内容
200
+ 可以包含多行内容
201
+ 推荐使用 ||| 或 ``` 分隔符包裹多行字符串,直接换行无需转义,支持保留缩进
202
+ 包含"双引号"和'单引号'都无需转义
203
+ |||
204
+ }}
205
+ }}
206
+ {ct("TOOL_CALL")}
207
+
208
+ 注意:如果 content 参数包含多行内容,推荐使用 ||| 或 ``` 分隔符包裹,直接换行无需转义,支持保留缩进。
209
+ 如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
210
+ </output_requirements>"""
211
+
212
+ return f"""<task_analysis>
213
+ <request>
214
+ 当前任务已结束,请按以下步骤分析该任务:
215
+
216
+ {memory_step}
217
+
218
+ {solution_step}
61
219
 
62
220
  请根据分析结果采取相应行动。
63
221
 
@@ -67,159 +225,23 @@ TASK_ANALYSIS_PROMPT = f"""<task_analysis>
67
225
  - 不要在一次响应中同时调用多个工具(如同时保存记忆和创建工具/方法论)
68
226
  </request>
69
227
  <evaluation_criteria>
70
- 现有资源评估:
71
- 1. 现有工具 - 检查系统中是否已有可以完成该任务的工具
72
- 2. 现有方法论 - 检查是否已有适用于该任务的方法论
73
- 3. 组合使用 - 评估现有工具和方法论组合使用是否可以解决问题
74
- 工具评估标准:
75
- 1. 通用性 - 该工具是否可以解决一类问题,而不仅仅是当前特定问题
76
- 2. 自动化 - 该工具是否可以减少人工干预,提高效率
77
- 3. 可靠性 - 该工具是否可以在不同场景下稳定工作
78
- 4. 简单性 - 该工具是否易于使用,参数设计是否合理
79
- 方法论评估标准:
80
- 1. 方法论应聚焦于通用且可重复的解决方案流程
81
- 2. 方法论应该具备足够的通用性,可应用于同类问题
82
- 3. 特别注意用户在执行过程中提供的修正、反馈和改进建议
83
- 4. 如果用户明确指出了某个解决步骤的优化方向,这应该被纳入方法论
84
- 5. 方法论应面向未来复用,总结“下次遇到同类问题应该如何处理”的通用流程与检查清单,避免局限于本次执行细节
228
+ 现有资源评估: 检查现有工具/方法论/组合使用是否可解决问题
229
+ 工具评估: 通用性、自动化、可靠性、简单性
230
+ 方法论评估: 聚焦通用可重复流程,纳入用户反馈,面向未来复用
85
231
  </evaluation_criteria>
86
232
  <tool_requirements>
87
233
  工具代码要求:
88
- 1. 工具类名应与工具名称保持一致
89
- 2. 必须包含name、description、parameters属性
90
- 3. 必须实现execute方法处理输入参数
91
- 4. 可选实现check方法验证环境
92
- 5. 工具描述应详细说明用途、适用场景和使用示例
93
- 6. 参数定义应遵循JSON Schema格式
94
- 7. 不要包含特定任务的细节,保持通用性
95
- 工具设计关键点:
96
- 1. **使用PrettyOutput打印执行过程**:强烈建议在工具中使用PrettyOutput显示执行过程,
97
- 这样用户可以了解工具在做什么,提升用户体验。示例:
98
- ```python
99
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
100
- # 执行中打印信息
101
- PrettyOutput.print("正在处理数据...", OutputType.INFO)
102
- # 成功信息
103
- PrettyOutput.print("操作成功完成", OutputType.SUCCESS)
104
- # 警告信息
105
- PrettyOutput.print("发现潜在问题", OutputType.WARNING)
106
- # 错误信息
107
- PrettyOutput.print("操作失败", OutputType.ERROR)
108
- ```
109
- 2. **结构化返回结果**:工具应该始终返回结构化的结果字典,包含以下字段:
110
- - success: 布尔值,表示操作是否成功
111
- - stdout: 字符串,包含工具的主要输出内容
112
- - stderr: 字符串,包含错误信息(如果有)
113
- 3. **异常处理**:工具应该妥善处理可能发生的异常,并在失败时清理已创建的资源
114
- ```python
115
- try:
116
- # 执行逻辑
117
- return {{
118
- "success": True,
119
- "stdout": "成功结果",
120
- "stderr": ""
121
- }}
122
- except Exception as e:
123
- PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
124
- # 清理资源(如果有创建)
125
- return {{
126
- "success": False,
127
- "stdout": "",
128
- "stderr": f"操作失败: {{str(e)}}"
129
- }}
130
- ```
131
- 4. **在工具中调用大模型**:如果工具需要调用大模型来完成子任务(例如,生成代码、分析文本等),为了避免干扰主对话流程,建议创建一个独立的大模型实例。
132
- ```python
133
- # 通过 agent 实例获取模型配置
134
- agent = args.get("agent")
135
- if not agent:
136
- return {{"success": False, "stderr": "Agent not found."}}
137
-
138
- current_model = agent.model
139
- platform_name = current_model.platform_name()
140
- model_name = current_model.name()
141
-
142
- # 创建独立的模型实例
143
- from jarvis.jarvis_platform.registry import PlatformRegistry
144
- llm = PlatformRegistry().create_platform(platform_name)
145
- if not llm:
146
- return {{"success": False, "stderr": f"Platform {{platform_name}} not found."}}
147
-
148
- llm.set_model_name(model_name)
149
- llm.set_suppress_output(True) # 工具内的调用通常不需要流式输出
150
-
151
- # 使用新实例调用大模型
152
- PrettyOutput.print("正在执行子任务...", OutputType.INFO)
153
- response = llm.chat_until_success("你的提示词")
154
- PrettyOutput.print("子任务完成", OutputType.SUCCESS)
155
- ```
234
+ 1. 工具类名与工具名称一致,包含name、description、parameters属性,实现execute方法
235
+ 2. 参数定义遵循JSON Schema,工具调用使用Jsonnet格式(支持 ||| 或 ``` 分隔符多行字符串、尾随逗号)
236
+ 3. 使用print显示执行过程,返回{{success, stdout, stderr}}结构化结果
237
+ 4. 妥善处理异常,失败时清理资源。如需调用大模型,创建独立实例避免干扰主流程
156
238
  </tool_requirements>
157
239
  <methodology_requirements>
158
- 方法论格式要求:
159
- 1. 问题重述: 简明扼要的问题归纳,不含特定细节
160
- 2. 可复用解决流程: 面向“下次遇到同类问题”的步骤化方案(列出每步可用的工具),避免与本次特定上下文绑定
161
- 3. 注意事项: 执行中可能遇到的常见问题和注意点,尤其是用户指出的问题
162
- 4. 可选步骤: 对于有多种解决路径的问题,标注出可选步骤和适用场景
240
+ 方法论格式: 问题重述、可复用解决流程(步骤化+工具)、注意事项、可选步骤
163
241
  </methodology_requirements>
164
- <output_requirements>
165
- 根据分析结果,输出以下三种情况之一:
166
- 1. 如果现有工具/方法论可以解决,直接输出说明:
167
- 已有工具/方法论可以解决该问题,无需创建新内容。
168
- 可用的工具/方法论:[列出工具名称或方法论名称]
169
- 使用方法:[简要说明如何使用]
170
- 2. 工具创建(如果需要创建新工具):
171
- {ot("TOOL_CALL")}
172
- want: 创建新工具来解决XXX问题
173
- name: generate_new_tool
174
- arguments:
175
- tool_name: 工具名称
176
- tool_code: |2
177
- # -*- coding: utf-8 -*-
178
- from typing import Dict, Any
179
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
180
- class 工具名称:
181
- name = "工具名称"
182
- description = "Tool description"
183
- parameters = {{
184
- "type": "object",
185
- "properties": {{
186
- # 参数定义
187
- }},
188
- "required": []
189
- }}
190
- @staticmethod
191
- def check() -> bool:
192
- return True
193
- def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
194
- try:
195
- # 使用PrettyOutput显示执行过程
196
- PrettyOutput.print("开始执行操作...", OutputType.INFO)
197
- # 实现逻辑
198
- # ...
199
- PrettyOutput.print("操作已完成", OutputType.SUCCESS)
200
- return {{
201
- "success": True,
202
- "stdout": "结果输出",
203
- "stderr": ""
204
- }}
205
- except Exception as e:
206
- PrettyOutput.print(f"操作失败: {{str(e)}}", OutputType.ERROR)
207
- return {{
208
- "success": False,
209
- "stdout": "",
210
- "stderr": f"操作失败: {{str(e)}}"
211
- }}
212
- {ct("TOOL_CALL")}
213
- 3. 方法论创建(如果需要创建新方法论):
214
- {ot("TOOL_CALL")}
215
- want: 添加/更新xxxx的方法论
216
- name: methodology
217
- arguments:
218
- operation: add/update
219
- problem_type: 方法论类型,不要过于细节,也不要过于泛化
220
- content: |2
221
- 方法论内容
222
- {ct("TOOL_CALL")}
223
- 如果以上三种情况都不适用,则直接输出原因分析,不要使用工具调用格式。
224
- </output_requirements>
242
+ {output_requirements}
225
243
  </task_analysis>"""
244
+
245
+
246
+ # 为了向后兼容,保留原来的常量(使用默认参数,假设有 save_memory 工具)
247
+ TASK_ANALYSIS_PROMPT = get_task_analysis_prompt(has_save_memory=True)
@@ -1,33 +1,29 @@
1
- # -*- coding: utf-8 -*-
2
1
  from typing import Any, Protocol, Tuple, runtime_checkable
3
2
 
4
3
 
5
4
  @runtime_checkable
6
5
  class OutputHandlerProtocol(Protocol):
7
6
  """
8
- Defines the interface for an output handler, which is responsible for
9
- processing the model's response, typically to execute a tool.
7
+ 定义输出处理器的接口,该处理器负责处理模型的响应,通常用于执行工具。
10
8
  """
11
9
 
12
10
  def name(self) -> str:
13
- """Returns the name of the handler."""
11
+ """返回处理器的名称。"""
14
12
  ...
15
13
 
16
14
  def can_handle(self, response: str) -> bool:
17
- """Determines if this handler can process the given response."""
15
+ """判断此处理器能否处理给定的响应。"""
18
16
  ...
19
17
 
20
18
  def prompt(self) -> str:
21
- """Returns the prompt snippet that describes the handler's functionality."""
19
+ """返回描述处理器功能的提示片段。"""
22
20
  ...
23
21
 
24
22
  def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
25
23
  """
26
- Handles the response, executing the associated logic.
24
+ 处理响应,执行相关逻辑。
27
25
 
28
- Returns:
29
- A tuple containing a boolean (whether to return) and the result.
26
+ 返回:
27
+ 一个元组,包含一个布尔值(是否返回)和结果。
30
28
  """
31
- ...
32
-
33
- __all__ = ["OutputHandlerProtocol"]
29
+ ...
@@ -11,10 +11,9 @@ import os
11
11
  from enum import Enum
12
12
  from typing import Any, TYPE_CHECKING
13
13
 
14
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
15
14
  from jarvis.jarvis_agent.events import BEFORE_TOOL_CALL, AFTER_TOOL_CALL
16
15
  from jarvis.jarvis_agent.utils import join_prompts, is_auto_complete, normalize_next_action
17
- from jarvis.jarvis_utils.config import get_auto_summary_rounds
16
+ from jarvis.jarvis_utils.config import get_max_input_token_count, get_conversation_turn_threshold
18
17
 
19
18
  if TYPE_CHECKING:
20
19
  # 仅用于类型标注,避免运行时循环依赖
@@ -26,12 +25,10 @@ class AgentRunLoop:
26
25
  self.agent = agent
27
26
  self.conversation_rounds = 0
28
27
  self.tool_reminder_rounds = int(os.environ.get("JARVIS_TOOL_REMINDER_ROUNDS", 20))
29
- # 基于轮次的自动总结阈值:优先使用 Agent 入参,否则回落到全局配置(默认20轮)
30
- self.auto_summary_rounds = (
31
- self.agent.auto_summary_rounds
32
- if getattr(self.agent, "auto_summary_rounds", None) is not None
33
- else get_auto_summary_rounds()
34
- )
28
+ # 基于剩余token数量的自动总结阈值:当剩余token低于输入窗口的20%时触发
29
+ max_input_tokens = get_max_input_token_count(self.agent.model_group)
30
+ self.summary_remaining_token_threshold = int(max_input_tokens * 0.2)
31
+ self.conversation_turn_threshold = get_conversation_turn_threshold()
35
32
 
36
33
  def run(self) -> Any:
37
34
  """主运行循环(委派到传入的 agent 实例的方法与属性)"""
@@ -44,15 +41,20 @@ class AgentRunLoop:
44
41
  self.agent.session.addon_prompt = join_prompts(
45
42
  [self.agent.session.addon_prompt, self.agent.get_tool_usage_prompt()]
46
43
  )
47
- # 基于轮次的自动总结判断:达到阈值后执行一次总结与历史清理
48
- if self.conversation_rounds >= self.auto_summary_rounds:
44
+ # 基于剩余token数量或对话轮次的自动总结判断
45
+ remaining_tokens = self.agent.model.get_remaining_token_count()
46
+ should_summarize = (
47
+ remaining_tokens <= self.summary_remaining_token_threshold or
48
+ self.conversation_rounds > self.conversation_turn_threshold
49
+ )
50
+ if should_summarize:
49
51
  summary_text = self.agent._summarize_and_clear_history()
50
52
  if summary_text:
51
53
  # 将摘要作为下一轮的附加提示加入,从而维持上下文连续性
52
54
  self.agent.session.addon_prompt = join_prompts(
53
55
  [self.agent.session.addon_prompt, summary_text]
54
56
  )
55
- # 重置轮次计数与对话长度计数器,开始新一轮周期
57
+ # 重置轮次计数(用于工具提醒)与对话长度计数器(用于摘要触发),开始新一轮周期
56
58
  self.conversation_rounds = 0
57
59
  self.agent.session.conversation_length = 0
58
60
 
@@ -75,6 +77,25 @@ class AgentRunLoop:
75
77
  ag.session.prompt = ""
76
78
  run_input_handlers = False
77
79
 
80
+ # 检查是否包含 <!!!SUMMARY!!!> 标记,触发总结并清空历史
81
+ if "<!!!SUMMARY!!!>" in current_response:
82
+ print("ℹ️ 检测到 <!!!SUMMARY!!!> 标记,正在触发总结并清空历史...")
83
+ # 移除标记,避免在后续处理中出现
84
+ current_response = current_response.replace("<!!!SUMMARY!!!>", "").strip()
85
+ # 触发总结并清空历史
86
+ summary_text = ag._summarize_and_clear_history()
87
+ if summary_text:
88
+ # 将摘要作为下一轮的附加提示加入,从而维持上下文连续性
89
+ ag.session.addon_prompt = join_prompts(
90
+ [ag.session.addon_prompt, summary_text]
91
+ )
92
+ # 重置轮次计数(用于工具提醒)与对话长度计数器(用于摘要触发),开始新一轮周期
93
+ self.conversation_rounds = 0
94
+ ag.session.conversation_length = 0
95
+ # 如果响应中还有其他内容,继续处理;否则继续下一轮
96
+ if not current_response:
97
+ continue
98
+
78
99
  # 处理中断
79
100
  interrupt_result = ag._handle_run_interrupt(current_response)
80
101
  if (
@@ -88,7 +109,7 @@ class AgentRunLoop:
88
109
  return interrupt_result
89
110
 
90
111
  # 处理工具调用
91
- # 广播工具调用前事件(不影响主流程)
112
+ # 非关键流程:广播工具调用前事件(用于日志、监控等)
92
113
  try:
93
114
  ag.event_bus.emit(
94
115
  BEFORE_TOOL_CALL,
@@ -101,13 +122,32 @@ class AgentRunLoop:
101
122
 
102
123
  # 如果工具要求立即返回结果(例如 SEND_MESSAGE 需要将字典返回给上层),直接返回该结果
103
124
  if need_return:
125
+ ag._no_tool_call_count = 0
104
126
  return tool_prompt
105
127
 
106
128
  # 将上一个提示和工具提示安全地拼接起来(仅当工具结果为字符串时)
107
129
  safe_tool_prompt = tool_prompt if isinstance(tool_prompt, str) else ""
130
+
108
131
  ag.session.prompt = join_prompts([ag.session.prompt, safe_tool_prompt])
109
132
 
110
- # 广播工具调用后的事件(不影响主流程)
133
+ # 关键流程:直接调用 after_tool_call 回调函数
134
+ try:
135
+ # 获取所有订阅了 AFTER_TOOL_CALL 事件的回调
136
+ listeners = ag.event_bus._listeners.get(AFTER_TOOL_CALL, [])
137
+ for callback in listeners:
138
+ try:
139
+ callback(
140
+ agent=ag,
141
+ current_response=current_response,
142
+ need_return=need_return,
143
+ tool_prompt=tool_prompt,
144
+ )
145
+ except Exception:
146
+ pass
147
+ except Exception:
148
+ pass
149
+
150
+ # 非关键流程:广播工具调用后的事件(用于日志、监控等)
111
151
  try:
112
152
  ag.event_bus.emit(
113
153
  AFTER_TOOL_CALL,
@@ -121,10 +161,12 @@ class AgentRunLoop:
121
161
 
122
162
  # 检查是否需要继续
123
163
  if ag.session.prompt or ag.session.addon_prompt:
164
+ ag._no_tool_call_count = 0
124
165
  continue
125
166
 
126
167
  # 检查自动完成
127
168
  if ag.auto_complete and is_auto_complete(current_response):
169
+ ag._no_tool_call_count = 0
128
170
  # 先运行_complete_task,触发记忆整理/事件等副作用,再决定返回值
129
171
  result = ag._complete_task(auto_completed=True)
130
172
  # 若不需要summary,则将最后一条LLM输出作为返回值
@@ -132,6 +174,27 @@ class AgentRunLoop:
132
174
  return current_response
133
175
  return result
134
176
 
177
+
178
+ # 检查是否有工具调用:如果tool_prompt不为空,说明有工具被调用
179
+ has_tool_call = bool(safe_tool_prompt and safe_tool_prompt.strip())
180
+
181
+ # 在非交互模式下,跟踪连续没有工具调用的次数
182
+ if ag.non_interactive:
183
+ if has_tool_call:
184
+ # 有工具调用,重置计数器
185
+ ag._no_tool_call_count = 0
186
+ else:
187
+ # 没有工具调用,增加计数器
188
+ ag._no_tool_call_count += 1
189
+ # 如果连续5次没有工具调用,添加工具使用提示
190
+ if ag._no_tool_call_count >= 5:
191
+ tool_usage_prompt = ag.get_tool_usage_prompt()
192
+ ag.session.addon_prompt = join_prompts(
193
+ [ag.session.addon_prompt, tool_usage_prompt]
194
+ )
195
+ # 重置计数器,避免重复添加
196
+ ag._no_tool_call_count = 0
197
+
135
198
  # 获取下一步用户输入
136
199
  next_action = ag._get_next_user_action()
137
200
  action = normalize_next_action(next_action)
@@ -142,5 +205,5 @@ class AgentRunLoop:
142
205
  return ag._complete_task(auto_completed=False)
143
206
 
144
207
  except Exception as e:
145
- PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
208
+ print(f"任务失败: {str(e)}")
146
209
  return f"Task failed: {str(e)}"
@@ -2,7 +2,6 @@
2
2
  import os
3
3
  from typing import Any, Dict, Optional, TYPE_CHECKING
4
4
 
5
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
5
 
7
6
  if TYPE_CHECKING:
8
7
  from jarvis.jarvis_platform.base import BasePlatform
@@ -61,9 +60,9 @@ class SessionManager:
61
60
  if self.model.restore(session_file):
62
61
  try:
63
62
  os.remove(session_file)
64
- PrettyOutput.print("会话已恢复,并已删除会话文件。", OutputType.SUCCESS)
63
+ print("会话已恢复,并已删除会话文件。")
65
64
  except OSError as e:
66
- PrettyOutput.print(f"删除会话文件失败: {e}", OutputType.ERROR)
65
+ print(f"删除会话文件失败: {e}")
67
66
  return True
68
67
  return False
69
68