jarvis-ai-assistant 0.1.222__py3-none-any.whl → 0.7.0__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 (162) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +1143 -245
  3. jarvis/jarvis_agent/agent_manager.py +97 -0
  4. jarvis/jarvis_agent/builtin_input_handler.py +12 -10
  5. jarvis/jarvis_agent/config_editor.py +57 -0
  6. jarvis/jarvis_agent/edit_file_handler.py +392 -99
  7. jarvis/jarvis_agent/event_bus.py +48 -0
  8. jarvis/jarvis_agent/events.py +157 -0
  9. jarvis/jarvis_agent/file_context_handler.py +79 -0
  10. jarvis/jarvis_agent/file_methodology_manager.py +117 -0
  11. jarvis/jarvis_agent/jarvis.py +1117 -147
  12. jarvis/jarvis_agent/main.py +78 -34
  13. jarvis/jarvis_agent/memory_manager.py +195 -0
  14. jarvis/jarvis_agent/methodology_share_manager.py +174 -0
  15. jarvis/jarvis_agent/prompt_manager.py +82 -0
  16. jarvis/jarvis_agent/prompts.py +46 -9
  17. jarvis/jarvis_agent/protocols.py +4 -1
  18. jarvis/jarvis_agent/rewrite_file_handler.py +141 -0
  19. jarvis/jarvis_agent/run_loop.py +146 -0
  20. jarvis/jarvis_agent/session_manager.py +9 -9
  21. jarvis/jarvis_agent/share_manager.py +228 -0
  22. jarvis/jarvis_agent/shell_input_handler.py +23 -3
  23. jarvis/jarvis_agent/stdio_redirect.py +295 -0
  24. jarvis/jarvis_agent/task_analyzer.py +212 -0
  25. jarvis/jarvis_agent/task_manager.py +154 -0
  26. jarvis/jarvis_agent/task_planner.py +496 -0
  27. jarvis/jarvis_agent/tool_executor.py +8 -4
  28. jarvis/jarvis_agent/tool_share_manager.py +139 -0
  29. jarvis/jarvis_agent/user_interaction.py +42 -0
  30. jarvis/jarvis_agent/utils.py +54 -0
  31. jarvis/jarvis_agent/web_bridge.py +189 -0
  32. jarvis/jarvis_agent/web_output_sink.py +53 -0
  33. jarvis/jarvis_agent/web_server.py +751 -0
  34. jarvis/jarvis_c2rust/__init__.py +26 -0
  35. jarvis/jarvis_c2rust/cli.py +613 -0
  36. jarvis/jarvis_c2rust/collector.py +258 -0
  37. jarvis/jarvis_c2rust/library_replacer.py +1122 -0
  38. jarvis/jarvis_c2rust/llm_module_agent.py +1300 -0
  39. jarvis/jarvis_c2rust/optimizer.py +960 -0
  40. jarvis/jarvis_c2rust/scanner.py +1681 -0
  41. jarvis/jarvis_c2rust/transpiler.py +2325 -0
  42. jarvis/jarvis_code_agent/build_validation_config.py +133 -0
  43. jarvis/jarvis_code_agent/code_agent.py +1605 -178
  44. jarvis/jarvis_code_agent/code_analyzer/__init__.py +62 -0
  45. jarvis/jarvis_code_agent/code_analyzer/base_language.py +74 -0
  46. jarvis/jarvis_code_agent/code_analyzer/build_validator/__init__.py +44 -0
  47. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +102 -0
  48. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +59 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/detector.py +125 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +69 -0
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +38 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +44 -0
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +38 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +50 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +93 -0
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +129 -0
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +54 -0
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +154 -0
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator.py +43 -0
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +363 -0
  61. jarvis/jarvis_code_agent/code_analyzer/context_recommender.py +18 -0
  62. jarvis/jarvis_code_agent/code_analyzer/dependency_analyzer.py +132 -0
  63. jarvis/jarvis_code_agent/code_analyzer/file_ignore.py +330 -0
  64. jarvis/jarvis_code_agent/code_analyzer/impact_analyzer.py +781 -0
  65. jarvis/jarvis_code_agent/code_analyzer/language_registry.py +185 -0
  66. jarvis/jarvis_code_agent/code_analyzer/language_support.py +89 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +31 -0
  68. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +231 -0
  69. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +183 -0
  70. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +219 -0
  71. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +209 -0
  72. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +451 -0
  73. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +77 -0
  74. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +48 -0
  75. jarvis/jarvis_code_agent/lint.py +275 -13
  76. jarvis/jarvis_code_agent/utils.py +142 -0
  77. jarvis/jarvis_code_analysis/checklists/loader.py +20 -6
  78. jarvis/jarvis_code_analysis/code_review.py +583 -548
  79. jarvis/jarvis_data/config_schema.json +339 -28
  80. jarvis/jarvis_git_squash/main.py +22 -13
  81. jarvis/jarvis_git_utils/git_commiter.py +171 -55
  82. jarvis/jarvis_mcp/sse_mcp_client.py +22 -15
  83. jarvis/jarvis_mcp/stdio_mcp_client.py +4 -4
  84. jarvis/jarvis_mcp/streamable_mcp_client.py +36 -16
  85. jarvis/jarvis_memory_organizer/memory_organizer.py +753 -0
  86. jarvis/jarvis_methodology/main.py +48 -63
  87. jarvis/jarvis_multi_agent/__init__.py +302 -43
  88. jarvis/jarvis_multi_agent/main.py +70 -24
  89. jarvis/jarvis_platform/ai8.py +40 -23
  90. jarvis/jarvis_platform/base.py +210 -49
  91. jarvis/jarvis_platform/human.py +11 -1
  92. jarvis/jarvis_platform/kimi.py +82 -76
  93. jarvis/jarvis_platform/openai.py +73 -1
  94. jarvis/jarvis_platform/registry.py +8 -15
  95. jarvis/jarvis_platform/tongyi.py +115 -101
  96. jarvis/jarvis_platform/yuanbao.py +89 -63
  97. jarvis/jarvis_platform_manager/main.py +194 -132
  98. jarvis/jarvis_platform_manager/service.py +122 -86
  99. jarvis/jarvis_rag/cli.py +156 -53
  100. jarvis/jarvis_rag/embedding_manager.py +155 -12
  101. jarvis/jarvis_rag/llm_interface.py +10 -13
  102. jarvis/jarvis_rag/query_rewriter.py +63 -12
  103. jarvis/jarvis_rag/rag_pipeline.py +222 -40
  104. jarvis/jarvis_rag/reranker.py +26 -3
  105. jarvis/jarvis_rag/retriever.py +270 -14
  106. jarvis/jarvis_sec/__init__.py +3605 -0
  107. jarvis/jarvis_sec/checkers/__init__.py +32 -0
  108. jarvis/jarvis_sec/checkers/c_checker.py +2680 -0
  109. jarvis/jarvis_sec/checkers/rust_checker.py +1108 -0
  110. jarvis/jarvis_sec/cli.py +116 -0
  111. jarvis/jarvis_sec/report.py +257 -0
  112. jarvis/jarvis_sec/status.py +264 -0
  113. jarvis/jarvis_sec/types.py +20 -0
  114. jarvis/jarvis_sec/workflow.py +219 -0
  115. jarvis/jarvis_smart_shell/main.py +405 -137
  116. jarvis/jarvis_stats/__init__.py +13 -0
  117. jarvis/jarvis_stats/cli.py +387 -0
  118. jarvis/jarvis_stats/stats.py +711 -0
  119. jarvis/jarvis_stats/storage.py +612 -0
  120. jarvis/jarvis_stats/visualizer.py +282 -0
  121. jarvis/jarvis_tools/ask_user.py +1 -0
  122. jarvis/jarvis_tools/base.py +18 -2
  123. jarvis/jarvis_tools/clear_memory.py +239 -0
  124. jarvis/jarvis_tools/cli/main.py +220 -144
  125. jarvis/jarvis_tools/execute_script.py +52 -12
  126. jarvis/jarvis_tools/file_analyzer.py +17 -12
  127. jarvis/jarvis_tools/generate_new_tool.py +46 -24
  128. jarvis/jarvis_tools/read_code.py +277 -18
  129. jarvis/jarvis_tools/read_symbols.py +141 -0
  130. jarvis/jarvis_tools/read_webpage.py +86 -13
  131. jarvis/jarvis_tools/registry.py +294 -90
  132. jarvis/jarvis_tools/retrieve_memory.py +227 -0
  133. jarvis/jarvis_tools/save_memory.py +194 -0
  134. jarvis/jarvis_tools/search_web.py +62 -28
  135. jarvis/jarvis_tools/sub_agent.py +205 -0
  136. jarvis/jarvis_tools/sub_code_agent.py +217 -0
  137. jarvis/jarvis_tools/virtual_tty.py +330 -62
  138. jarvis/jarvis_utils/builtin_replace_map.py +4 -5
  139. jarvis/jarvis_utils/clipboard.py +90 -0
  140. jarvis/jarvis_utils/config.py +607 -50
  141. jarvis/jarvis_utils/embedding.py +3 -0
  142. jarvis/jarvis_utils/fzf.py +57 -0
  143. jarvis/jarvis_utils/git_utils.py +251 -29
  144. jarvis/jarvis_utils/globals.py +174 -17
  145. jarvis/jarvis_utils/http.py +58 -79
  146. jarvis/jarvis_utils/input.py +899 -153
  147. jarvis/jarvis_utils/methodology.py +210 -83
  148. jarvis/jarvis_utils/output.py +220 -137
  149. jarvis/jarvis_utils/utils.py +1906 -135
  150. jarvis_ai_assistant-0.7.0.dist-info/METADATA +465 -0
  151. jarvis_ai_assistant-0.7.0.dist-info/RECORD +192 -0
  152. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/entry_points.txt +8 -2
  153. jarvis/jarvis_git_details/main.py +0 -265
  154. jarvis/jarvis_platform/oyi.py +0 -357
  155. jarvis/jarvis_tools/edit_file.py +0 -255
  156. jarvis/jarvis_tools/rewrite_file.py +0 -195
  157. jarvis_ai_assistant-0.1.222.dist-info/METADATA +0 -767
  158. jarvis_ai_assistant-0.1.222.dist-info/RECORD +0 -110
  159. /jarvis/{jarvis_git_details → jarvis_memory_organizer}/__init__.py +0 -0
  160. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/WHEEL +0 -0
  161. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/licenses/LICENSE +0 -0
  162. {jarvis_ai_assistant-0.1.222.dist-info → jarvis_ai_assistant-0.7.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,205 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ sub_agent 工具
4
+ 将子任务交给通用 Agent 执行,并返回执行结果。
5
+
6
+ 约定:
7
+ - 必填参数:task, name, system_prompt, summary_prompt
8
+ - 可选参数:background
9
+ - 工具集:默认使用系统工具集(无需传入 use_tools)
10
+ - 继承父 Agent 的部分配置:model_group、input_handler、execute_tool_confirm、multiline_inputer、non_interactive、use_methodology、use_analysis;其他参数需显式提供
11
+ - 子Agent必须自动完成(auto_complete=True)且需要summary(need_summary=True)
12
+ """
13
+ from typing import Any, Dict
14
+ import json
15
+
16
+ from jarvis.jarvis_agent import Agent
17
+ from jarvis.jarvis_utils.globals import delete_agent
18
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
19
+
20
+
21
+ class SubAgentTool:
22
+ """
23
+ 临时创建一个通用 Agent 执行子任务,执行完立即清理。
24
+ - 不注册至全局
25
+ - 使用系统默认/全局配置
26
+ - 启用自动完成与总结
27
+ """
28
+
29
+ # 必须与文件名一致,供 ToolRegistry 自动注册
30
+ name = "sub_agent"
31
+ description = "将子任务交给通用 Agent 执行,并返回执行结果(继承父Agent部分配置:model_group、input_handler、execute_tool_confirm、multiline_inputer、non_interactive、use_methodology、use_analysis;其他参数需显式提供,自动完成并生成总结)。"
32
+ parameters = {
33
+ "type": "object",
34
+ "properties": {
35
+ "task": {
36
+ "type": "string",
37
+ "description": "要执行的子任务内容(必填)",
38
+ },
39
+ "name": {
40
+ "type": "string",
41
+ "description": "子Agent名称(必填)",
42
+ },
43
+ "background": {
44
+ "type": "string",
45
+ "description": "任务背景与已知信息(可选,将与任务一并提供给子Agent)",
46
+ },
47
+ "system_prompt": {
48
+ "type": "string",
49
+ "description": "覆盖子Agent的系统提示词(必填)",
50
+ },
51
+ "summary_prompt": {
52
+ "type": "string",
53
+ "description": "覆盖子Agent的总结提示词(必填)",
54
+ },
55
+ "non_interactive": {
56
+ "type": "boolean",
57
+ "description": "是否启用无交互模式(可选,默认继承父Agent或系统默认)",
58
+ },
59
+ },
60
+ "required": [
61
+ "task",
62
+ "name",
63
+ "system_prompt",
64
+ "summary_prompt",
65
+ ],
66
+ }
67
+
68
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
69
+ """
70
+ 执行子任务并返回结果。
71
+ 返回:
72
+ - success: 是否成功
73
+ - stdout: 子 Agent 返回的结果(字符串或JSON字符串)
74
+ - stderr: 错误信息(如有)
75
+ """
76
+ try:
77
+ task: str = str(args.get("task", "")).strip()
78
+ if not task:
79
+ return {
80
+ "success": False,
81
+ "stdout": "",
82
+ "stderr": "task 不能为空",
83
+ }
84
+
85
+ # 读取背景信息并组合任务
86
+ background: str = str(args.get("background", "")).strip()
87
+ enhanced_task = (
88
+ f"背景信息:\n{background}\n\n任务:\n{task}" if background else task
89
+ )
90
+
91
+ # 不继承父Agent,所有关键参数必须由调用方显式提供
92
+ need_summary = True
93
+ auto_complete = True
94
+
95
+ # 读取并校验必填参数
96
+ system_prompt = str(args.get("system_prompt", "")).strip()
97
+ summary_prompt = str(args.get("summary_prompt", "")).strip()
98
+ agent_name = str(args.get("name", "")).strip()
99
+
100
+ errors = []
101
+ if not system_prompt:
102
+ errors.append("system_prompt 不能为空")
103
+ if not summary_prompt:
104
+ errors.append("summary_prompt 不能为空")
105
+ if not agent_name:
106
+ errors.append("name 不能为空")
107
+ if not background:
108
+ errors.append("background 不能为空")
109
+
110
+ if errors:
111
+ return {
112
+ "success": False,
113
+ "stdout": "",
114
+ "stderr": "; ".join(errors),
115
+ }
116
+
117
+ # 基于父Agent(如有)继承部分配置后创建子Agent
118
+ parent_agent = args.get("agent", None)
119
+ parent_model_group = None
120
+ parent_execute_tool_confirm = None
121
+ parent_multiline_inputer = None
122
+ parent_non_interactive = None
123
+ parent_use_methodology = None
124
+ parent_use_analysis = None
125
+ try:
126
+ if parent_agent is not None:
127
+ if getattr(parent_agent, "model", None):
128
+ parent_model_group = getattr(parent_agent.model, "model_group", None)
129
+ parent_execute_tool_confirm = getattr(parent_agent, "execute_tool_confirm", None)
130
+ parent_multiline_inputer = getattr(parent_agent, "multiline_inputer", None)
131
+ parent_non_interactive = getattr(parent_agent, "non_interactive", None)
132
+ parent_use_methodology = getattr(parent_agent, "use_methodology", None)
133
+ parent_use_analysis = getattr(parent_agent, "use_analysis", None)
134
+ except Exception:
135
+ # 安全兜底:无法从父Agent获取配置则保持为None,使用系统默认
136
+ pass
137
+
138
+ # 可选参数:允许显式覆盖无交互模式
139
+ explicit_non_interactive = args.get("non_interactive", None)
140
+ if explicit_non_interactive is not None:
141
+ parent_non_interactive = bool(explicit_non_interactive)
142
+
143
+ agent = Agent(
144
+ system_prompt=system_prompt,
145
+ name=agent_name,
146
+ description="Temporary sub agent for executing a subtask",
147
+ model_group=parent_model_group,
148
+ summary_prompt=summary_prompt,
149
+ auto_complete=auto_complete,
150
+ use_tools=None,
151
+ execute_tool_confirm=parent_execute_tool_confirm,
152
+ need_summary=need_summary,
153
+ multiline_inputer=parent_multiline_inputer,
154
+ use_methodology=parent_use_methodology,
155
+ use_analysis=parent_use_analysis,
156
+ force_save_memory=None,
157
+ files=None,
158
+ non_interactive=parent_non_interactive,
159
+ )
160
+
161
+ # 校验子Agent所用模型是否有效,必要时回退到平台可用模型
162
+ try:
163
+ platform = getattr(agent, "model", None)
164
+ if platform:
165
+ available_models = platform.get_model_list()
166
+ if available_models:
167
+ available_names = [m for m, _ in available_models]
168
+ current_model_name = platform.name()
169
+ if current_model_name not in available_names:
170
+ PrettyOutput.print(
171
+ f"检测到子Agent模型 {current_model_name} 不存在于平台 {platform.platform_name()} 的可用模型列表,将回退到 {available_names[0]}",
172
+ OutputType.WARNING,
173
+ )
174
+ platform.set_model_name(available_names[0])
175
+ except Exception:
176
+ # 获取模型列表或设置模型失败时,保持原设置并继续,交由底层报错处理
177
+ pass
178
+
179
+ # 执行任务
180
+ result = agent.run(enhanced_task)
181
+
182
+ # 主动清理,避免污染父 Agent 的全局状态
183
+ try:
184
+ delete_agent(agent.name)
185
+ except Exception:
186
+ pass
187
+
188
+ # 规范化输出
189
+ if isinstance(result, (dict, list)):
190
+ stdout = json.dumps(result, ensure_ascii=False, indent=2)
191
+ else:
192
+ stdout = str(result) if result is not None else "任务执行完成"
193
+
194
+ return {
195
+ "success": True,
196
+ "stdout": stdout,
197
+ "stderr": "",
198
+ }
199
+
200
+ except Exception as e:
201
+ return {
202
+ "success": False,
203
+ "stdout": "",
204
+ "stderr": f"执行子任务失败: {str(e)}",
205
+ }
@@ -0,0 +1,217 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ sub_code_agent 工具
4
+ 将子任务交给 CodeAgent 执行,并返回执行结果。
5
+
6
+ 约定:
7
+ - 必填参数:task
8
+ - 可选参数:background
9
+ - 不依赖父 Agent,所有配置使用系统默认与全局变量
10
+ - 子Agent必须自动完成(auto_complete=True)且需要summary(need_summary=True)
11
+ """
12
+ from typing import Any, Dict, List
13
+
14
+ from jarvis.jarvis_code_agent.code_agent import CodeAgent
15
+ from jarvis.jarvis_utils.globals import delete_agent
16
+ from jarvis.jarvis_utils.config import set_config, get_git_check_mode
17
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
18
+
19
+
20
+ class SubCodeAgentTool:
21
+ """
22
+ 使用 CodeAgent 托管执行子任务,执行完立即清理 CodeAgent 实例。
23
+ - 不注册至全局
24
+ - 使用系统默认/全局配置
25
+ - 启用自动完成与总结
26
+ """
27
+
28
+ # 必须与文件名一致,供 ToolRegistry 自动注册
29
+ name = "sub_code_agent"
30
+ description = "将子任务交给 CodeAgent 执行,并返回执行结果(使用系统默认配置,自动完成并生成总结)。"
31
+ parameters = {
32
+ "type": "object",
33
+ "properties": {
34
+ "task": {
35
+ "type": "string",
36
+ "description": "要执行的子任务内容(必填)",
37
+ },
38
+ "background": {
39
+ "type": "string",
40
+ "description": "任务背景与已知信息(可选,将与任务一并提供给子Agent)",
41
+ },
42
+ },
43
+ "required": ["task"],
44
+ }
45
+
46
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
47
+ """
48
+ 执行代码子任务并返回结果(由 CodeAgent 托管执行)。
49
+ 返回:
50
+ - success: 是否成功
51
+ - stdout: CodeAgent 执行结果(字符串;若为 None 则返回“任务执行完成”)
52
+ - stderr: 错误信息(如有)
53
+ """
54
+ try:
55
+ task: str = str(args.get("task", "")).strip()
56
+ if not task:
57
+ return {
58
+ "success": False,
59
+ "stdout": "",
60
+ "stderr": "task 不能为空",
61
+ }
62
+
63
+
64
+ # 读取背景信息并组合任务
65
+ background: str = str(args.get("background", "")).strip()
66
+ enhanced_task = (
67
+ f"背景信息:\n{background}\n\n任务:\n{task}" if background else task
68
+ )
69
+
70
+ # 继承父Agent的模型组与工具使用集(用于覆盖默认值)
71
+ parent_agent = args.get("agent")
72
+ # 如未注入父Agent,尝试从全局获取当前或任一已注册Agent
73
+ if parent_agent is None:
74
+ try:
75
+ from jarvis.jarvis_utils import globals as G # 延迟导入避免循环
76
+
77
+ curr = getattr(G, "current_agent_name", "")
78
+ if curr:
79
+ parent_agent = getattr(G, "global_agents", {}).get(curr)
80
+ if parent_agent is None and getattr(G, "global_agents", {}):
81
+ try:
82
+ parent_agent = next(iter(G.global_agents.values()))
83
+ except Exception:
84
+ parent_agent = None
85
+ except Exception:
86
+ parent_agent = None
87
+ parent_non_interactive = getattr(parent_agent, "non_interactive", None) if parent_agent is not None else None
88
+ model_group = None
89
+ use_tools: List[str] = []
90
+ try:
91
+ if parent_agent is not None:
92
+ if getattr(parent_agent, "model", None):
93
+ model_group = getattr(parent_agent.model, "model_group", None)
94
+ parent_registry = parent_agent.get_tool_registry()
95
+ if parent_registry:
96
+ for t in parent_registry.get_all_tools():
97
+ if isinstance(t, dict) and t.get("name"):
98
+ use_tools.append(str(t["name"]))
99
+ except Exception:
100
+ pass
101
+
102
+ # 创建 CodeAgent:参数优先使用父Agent的配置(若可获取),否则使用默认
103
+ # 推断/继承 tool_group
104
+ tool_group = None
105
+ try:
106
+ if parent_agent is not None:
107
+ tool_group = getattr(parent_agent, "tool_group", tool_group)
108
+ except Exception:
109
+ pass
110
+
111
+ # 依据父Agent已启用工具集,推导 append_tools(作为在 CodeAgent 基础工具上的增量)
112
+ append_tools = None
113
+ try:
114
+ base_tools = [
115
+ "execute_script",
116
+ "search_web",
117
+ "ask_user",
118
+ "read_code",
119
+
120
+ "save_memory",
121
+ "retrieve_memory",
122
+ "clear_memory",
123
+ "sub_code_agent",
124
+ ]
125
+ if use_tools:
126
+ extras = [t for t in use_tools if t not in base_tools]
127
+ append_tools = ",".join(extras) if extras else None
128
+ except Exception:
129
+ append_tools = None
130
+
131
+ # 在子Agent中放宽 Git 配置校验,避免因严格校验导致进程退出
132
+ # 使用配置项将校验模式临时切换为 warn,构造完成后恢复原值
133
+ old_mode = None
134
+ try:
135
+ old_mode = get_git_check_mode()
136
+ set_config("JARVIS_GIT_CHECK_MODE", "warn")
137
+ code_agent = CodeAgent(
138
+ model_group=model_group,
139
+ need_summary=True,
140
+ append_tools=append_tools,
141
+ tool_group=tool_group,
142
+ non_interactive=parent_non_interactive,
143
+ )
144
+ except SystemExit as se:
145
+ # 将底层 sys.exit 转换为工具错误,避免终止进程
146
+ return {
147
+ "success": False,
148
+ "stdout": "",
149
+ "stderr": f"初始化 CodeAgent 失败(可能未配置 git 或当前非 git 仓库): {se}",
150
+ }
151
+ finally:
152
+ if old_mode is not None:
153
+ try:
154
+ set_config("JARVIS_GIT_CHECK_MODE", old_mode)
155
+ except Exception:
156
+ pass
157
+
158
+ # 子Agent需要自动完成
159
+ try:
160
+ code_agent.auto_complete = True
161
+ # 同步父Agent工具使用集(如可用)
162
+ if use_tools:
163
+ code_agent.set_use_tools(use_tools)
164
+ # 同步父Agent的模型名称(如可用),以尽量保持平台与模型一致
165
+ if (
166
+ parent_agent is not None
167
+ and getattr(parent_agent, "model", None)
168
+ and getattr(code_agent, "model", None)
169
+ ):
170
+ try:
171
+ parent_model_name = parent_agent.model.name() # type: ignore[attr-defined]
172
+ if parent_model_name:
173
+ from typing import Any
174
+ model_obj: Any = getattr(code_agent, "model", None)
175
+ if model_obj is not None:
176
+ model_obj.set_model_name(parent_model_name)
177
+ # 模型有效性校验与回退,确保父Agent模型在子Agent平台上可用
178
+ try:
179
+ available_models = model_obj.get_model_list()
180
+ if available_models:
181
+ available_names = [m for m, _ in available_models]
182
+ current_model_name = model_obj.name()
183
+ if current_model_name not in available_names:
184
+ PrettyOutput.print(
185
+ f"检测到子CodeAgent模型 {current_model_name} 不存在于平台 {model_obj.platform_name()} 的可用模型列表,将回退到 {available_names[0]}",
186
+ OutputType.WARNING,
187
+ )
188
+ model_obj.set_model_name(available_names[0])
189
+ except Exception:
190
+ # 获取模型列表或设置模型失败时,保持原设置并继续,交由底层报错处理
191
+ pass
192
+ except Exception:
193
+ pass
194
+ except Exception:
195
+ pass
196
+
197
+ # 执行子任务(无提交信息前后缀)
198
+ ret = code_agent.run(enhanced_task, prefix="", suffix="")
199
+
200
+ # 主动清理 CodeAgent 实例,避免污染父Agent的全局状态
201
+ try:
202
+ # CodeAgent 现在直接继承 Agent,所以直接使用 code_agent
203
+ delete_agent(code_agent.name)
204
+ except Exception:
205
+ pass
206
+
207
+ return {
208
+ "success": True,
209
+ "stdout": ret,
210
+ "stderr": "",
211
+ }
212
+ except Exception as e:
213
+ return {
214
+ "success": False,
215
+ "stdout": "",
216
+ "stderr": f"执行子任务失败: {str(e)}",
217
+ }