jarvis-ai-assistant 0.2.1__py3-none-any.whl → 0.2.2__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 (30) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/jarvis.py +61 -59
  3. jarvis/jarvis_agent/main.py +42 -40
  4. jarvis/jarvis_code_agent/code_agent.py +35 -31
  5. jarvis/jarvis_code_analysis/code_review.py +73 -39
  6. jarvis/jarvis_git_squash/main.py +16 -12
  7. jarvis/jarvis_git_utils/git_commiter.py +25 -20
  8. jarvis/jarvis_methodology/main.py +34 -49
  9. jarvis/jarvis_multi_agent/main.py +28 -23
  10. jarvis/jarvis_platform/ai8.py +31 -22
  11. jarvis/jarvis_platform/kimi.py +31 -61
  12. jarvis/jarvis_platform/tongyi.py +62 -76
  13. jarvis/jarvis_platform/yuanbao.py +44 -50
  14. jarvis/jarvis_platform_manager/main.py +55 -90
  15. jarvis/jarvis_smart_shell/main.py +58 -87
  16. jarvis/jarvis_tools/cli/main.py +120 -153
  17. jarvis/jarvis_tools/registry.py +1 -7
  18. jarvis/jarvis_tools/search_web.py +12 -10
  19. jarvis/jarvis_utils/http.py +58 -79
  20. jarvis/jarvis_utils/output.py +1 -1
  21. jarvis_ai_assistant-0.2.2.dist-info/METADATA +228 -0
  22. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.2.dist-info}/RECORD +26 -29
  23. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.2.dist-info}/entry_points.txt +0 -2
  24. jarvis/jarvis_git_details/__init__.py +0 -0
  25. jarvis/jarvis_git_details/main.py +0 -265
  26. jarvis/jarvis_platform/oyi.py +0 -357
  27. jarvis_ai_assistant-0.2.1.dist-info/METADATA +0 -845
  28. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.2.dist-info}/WHEEL +0 -0
  29. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.2.dist-info}/licenses/LICENSE +0 -0
  30. {jarvis_ai_assistant-0.2.1.dist-info → jarvis_ai_assistant-0.2.2.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,25 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
- import argparse
4
3
  import os
5
4
  import sys
6
5
  from typing import Optional, Tuple
7
6
 
7
+ import typer
8
+
8
9
  from jarvis.jarvis_platform.registry import PlatformRegistry
9
10
  from jarvis.jarvis_utils.config import get_shell_name, set_config
10
11
  from jarvis.jarvis_utils.input import get_multiline_input
11
12
  from jarvis.jarvis_utils.utils import init_env
12
13
 
14
+ app = typer.Typer(
15
+ help="将自然语言要求转换为shell命令",
16
+ epilog="""
17
+ Example:
18
+ jss request "Find all Python files in the current directory"
19
+ jss install
20
+ """,
21
+ )
22
+
13
23
 
14
24
  def execute_command(command: str, should_run: bool) -> None:
15
25
  """Print command without execution"""
@@ -48,15 +58,18 @@ def _get_markers() -> Tuple[str, str]:
48
58
  )
49
59
 
50
60
 
51
- def install_jss_completion() -> int:
52
- """Install JSS fish shell command completion
61
+ @app.command("install")
62
+ def install_jss_completion(
63
+ shell: str = typer.Option("fish", help="指定shell类型(仅支持fish)"),
64
+ ) -> None:
65
+ """为fish shell安装'命令未找到'处理器,实现自然语言命令执行"""
66
+ if shell != "fish":
67
+ print(f"错误: 不支持的shell类型: {shell}, 仅支持fish")
68
+ raise typer.Exit(code=1)
53
69
 
54
- Returns:
55
- int: 0 if success, 1 if failed
56
- """
57
70
  if not _check_fish_shell():
58
71
  print("当前不是fish shell,无需安装")
59
- return 0
72
+ return
60
73
 
61
74
  config_file = _get_config_file()
62
75
  start_marker, end_marker = _get_markers()
@@ -64,13 +77,15 @@ def install_jss_completion() -> int:
64
77
  if not os.path.exists(config_file):
65
78
  print("未找到config.fish文件,将创建新文件")
66
79
  os.makedirs(os.path.dirname(config_file), exist_ok=True)
80
+ with open(config_file, "w") as f:
81
+ f.write("")
67
82
 
68
83
  with open(config_file, "r") as f:
69
84
  content = f.read()
70
85
 
71
86
  if start_marker in content:
72
87
  print("JSS fish completion已安装,请执行: source ~/.config/fish/config.fish")
73
- return 0
88
+ return
74
89
 
75
90
  with open(config_file, "a") as f:
76
91
  f.write(
@@ -90,32 +105,34 @@ end
90
105
  """
91
106
  )
92
107
  print("JSS fish completion已安装,请执行: source ~/.config/fish/config.fish")
93
- return 0
94
108
 
95
109
 
96
- def uninstall_jss_completion() -> int:
97
- """Uninstall JSS fish shell command completion
110
+ @app.command("uninstall")
111
+ def uninstall_jss_completion(
112
+ shell: str = typer.Option("fish", help="指定shell类型(仅支持fish)"),
113
+ ) -> None:
114
+ """卸载JSS fish shell'命令未找到'处理器"""
115
+ if shell != "fish":
116
+ print(f"错误: 不支持的shell类型: {shell}, 仅支持fish")
117
+ raise typer.Exit(code=1)
98
118
 
99
- Returns:
100
- int: 0 if success, 1 if failed
101
- """
102
119
  if not _check_fish_shell():
103
120
  print("当前不是fish shell,无需卸载")
104
- return 0
121
+ return
105
122
 
106
123
  config_file = _get_config_file()
107
124
  start_marker, end_marker = _get_markers()
108
125
 
109
126
  if not os.path.exists(config_file):
110
127
  print("未找到JSS fish completion配置,无需卸载")
111
- return 0
128
+ return
112
129
 
113
130
  with open(config_file, "r") as f:
114
131
  content = f.read()
115
132
 
116
133
  if start_marker not in content:
117
134
  print("未找到JSS fish completion配置,无需卸载")
118
- return 0
135
+ return
119
136
 
120
137
  new_content = content.split(start_marker)[0] + content.split(end_marker)[-1]
121
138
 
@@ -123,7 +140,6 @@ def uninstall_jss_completion() -> int:
123
140
  f.write(new_content)
124
141
 
125
142
  print("JSS fish completion已卸载,请执行: source ~/.config/fish/config.fish")
126
- return 0
127
143
 
128
144
 
129
145
  def process_request(request: str) -> Optional[str]:
@@ -175,85 +191,40 @@ def process_request(request: str) -> Optional[str]:
175
191
  return None
176
192
 
177
193
 
178
- def main() -> int:
179
- # 创建参数解析器
180
- init_env("")
181
-
182
- set_config("JARVIS_PRINT_PROMPT", "false")
183
-
184
- parser = argparse.ArgumentParser(
185
- description="将自然语言要求转换为shell命令",
186
- formatter_class=argparse.RawDescriptionHelpFormatter,
187
- epilog="""
188
- Example:
189
- %(prog)s request "Find all Python files in the current directory"
190
- %(prog)s install
191
- """,
194
+ @app.command("request")
195
+ def request_command(
196
+ request: Optional[str] = typer.Argument(
197
+ None, help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
192
198
  )
193
-
194
- # 创建子命令解析器
195
- subparsers = parser.add_subparsers(dest="command", required=True)
196
-
197
- # request子命令
198
- request_parser = subparsers.add_parser(
199
- "request", help="描述您想要执行的操作(用自然语言描述)"
200
- )
201
- request_parser.add_argument(
202
- "request",
203
- nargs="?", # 设置为可选参数
204
- help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取",
205
- )
206
-
207
- # install子命令
208
- install_parser = subparsers.add_parser(
209
- "install", help="安装JSS fish shell命令补全功能"
210
- )
211
- install_parser.add_argument(
212
- "--shell", choices=["fish"], default="fish", help="指定shell类型(仅支持fish)"
213
- )
214
-
215
- # 添加uninstall子命令
216
- uninstall_parser = subparsers.add_parser(
217
- "uninstall", help="卸载JSS fish shell命令补全功能"
218
- )
219
- uninstall_parser.add_argument(
220
- "--shell", choices=["fish"], default="fish", help="指定shell类型(仅支持fish)"
221
- )
222
-
223
- # 解析参数
224
- args = parser.parse_args()
225
-
199
+ ):
200
+ """描述您想要执行的操作(用自然语言描述)"""
226
201
  should_run = False
227
-
228
- # 处理install命令
229
- if args.command == "install":
230
- if args.shell != "fish":
231
- print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
232
- return 1
233
- return install_jss_completion()
234
-
235
- # 处理uninstall命令
236
- if args.command == "uninstall":
237
- if args.shell != "fish":
238
- print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
239
- return 1
240
- return uninstall_jss_completion()
241
-
242
- # 处理request命令
243
- if not args.request:
202
+ if not request:
244
203
  # 检查是否在交互式终端中运行
245
- args.request = get_multiline_input(tip="请输入您要执行的功能:")
204
+ request = get_multiline_input(tip="请输入您要执行的功能:")
246
205
  should_run = True
206
+
247
207
  # 处理请求
248
- command = process_request(args.request)
208
+ command = process_request(request)
249
209
 
250
210
  # 输出结果
251
211
  if command:
252
212
  execute_command(command, should_run) # 显示并执行命令
253
- return 0
254
213
  else:
255
- return 1
214
+ raise typer.Exit(code=1)
215
+
216
+
217
+ def cli():
218
+ """Typer application entry point"""
219
+ init_env("")
220
+ set_config("JARVIS_PRINT_PROMPT", "false")
221
+ app()
222
+
223
+
224
+ def main():
225
+ """Main entry point for the script"""
226
+ cli()
256
227
 
257
228
 
258
229
  if __name__ == "__main__":
259
- sys.exit(main())
230
+ main()
@@ -1,178 +1,145 @@
1
1
  import sys
2
+ import json
3
+ from typing import Optional
4
+
5
+ import typer
6
+ from tabulate import tabulate
2
7
 
3
8
  from jarvis.jarvis_tools.registry import ToolRegistry
4
9
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
5
10
  from jarvis.jarvis_utils.utils import init_env
6
11
 
12
+ app = typer.Typer(help="Jarvis 工具系统命令行界面")
7
13
 
8
- def main() -> int:
9
- """
10
- 命令行工具入口,提供工具列表查看和工具调用功能
11
-
12
- 功能:
13
- 1. 列出所有可用工具 (list命令)
14
- 2. 调用指定工具 (call命令)
15
-
16
- 参数:
17
- 通过命令行参数传递,包括:
18
- - list: 列出工具
19
- --json: 以JSON格式输出
20
- --detailed: 显示详细信息
21
- - call: 调用工具
22
- tool_name: 工具名称
23
- --args: 工具参数(JSON格式)
24
- --args-file: 从文件加载工具参数
25
-
26
- 返回值:
27
- int: 0表示成功,非0表示错误
28
- """
29
- import argparse
30
- import json
31
-
32
- init_env("欢迎使用 Jarvis-Tools,您的工具系统已准备就绪!")
33
-
34
- parser = argparse.ArgumentParser(description="Jarvis 工具系统命令行界面")
35
- subparsers = parser.add_subparsers(dest="command", help="命令")
36
14
 
37
- # 列出工具子命令
38
- list_parser = subparsers.add_parser("list", help="列出所有可用工具")
39
- list_parser.add_argument("--json", action="store_true", help="以JSON格式输出")
40
- list_parser.add_argument("--detailed", action="store_true", help="显示详细信息")
41
-
42
- # 调用工具子命令
43
- call_parser = subparsers.add_parser("call", help="调用指定工具")
44
- call_parser.add_argument("tool_name", help="要调用的工具名称")
45
- call_parser.add_argument("--args", type=str, help="工具参数 (JSON格式)")
46
- call_parser.add_argument(
47
- "--args-file", type=str, help="从文件加载工具参数 (JSON格式)"
48
- )
49
-
50
- # 统计子命令
51
- stat_parser = subparsers.add_parser("stat", help="显示工具调用统计信息")
52
- stat_parser.add_argument("--json", action="store_true", help="以JSON格式输出")
53
-
54
- args = parser.parse_args()
55
-
56
- # 初始化工具注册表
15
+ @app.command("list")
16
+ def list_tools(
17
+ as_json: bool = typer.Option(False, "--json", help="以JSON格式输出"),
18
+ detailed: bool = typer.Option(False, "--detailed", help="显示详细信息"),
19
+ ):
20
+ """列出所有可用工具"""
57
21
  registry = ToolRegistry()
22
+ tools = registry.get_all_tools()
58
23
 
59
- if args.command == "list":
60
- tools = registry.get_all_tools() # 从注册表获取所有工具信息
61
-
62
- if args.json:
63
- if args.detailed:
64
- print(
65
- json.dumps(tools, indent=2, ensure_ascii=False)
66
- ) # 输出完整JSON格式
67
- else:
68
- simple_tools = [
69
- {"name": t["name"], "description": t["description"]} for t in tools
70
- ] # 简化工具信息
71
- print(json.dumps(simple_tools, indent=2, ensure_ascii=False))
24
+ if as_json:
25
+ if detailed:
26
+ print(json.dumps(tools, indent=2, ensure_ascii=False))
72
27
  else:
73
- PrettyOutput.section("可用工具列表", OutputType.SYSTEM) # 使用美化输出
74
- for tool in tools:
75
- print(f"\n✅ {tool['name']}")
76
- print(f" 描述: {tool['description']}")
77
- if args.detailed:
78
- print(f" 参数:")
79
- print(tool["parameters"]) # 显示详细参数信息
80
-
81
- elif args.command == "stat":
82
- from tabulate import tabulate
83
-
84
- stats = registry._get_tool_stats()
85
- tools = registry.get_all_tools()
86
-
87
- # 构建统计表格数据
88
- table_data = []
28
+ simple_tools = [
29
+ {"name": t["name"], "description": t["description"]} for t in tools
30
+ ]
31
+ print(json.dumps(simple_tools, indent=2, ensure_ascii=False))
32
+ else:
33
+ PrettyOutput.section("可用工具列表", OutputType.SYSTEM)
89
34
  for tool in tools:
90
- name = tool["name"]
91
- count = stats.get(name, 0)
92
- table_data.append([name, count])
35
+ print(f"\n✅ {tool['name']}")
36
+ print(f" 描述: {tool['description']}")
37
+ if detailed:
38
+ print(" 参数:")
39
+ print(tool["parameters"])
93
40
 
94
- # 按调用次数降序排序
95
- table_data.sort(key=lambda x: x[1], reverse=True)
96
41
 
97
- if args.json:
98
- print(json.dumps(dict(table_data), indent=2))
99
- else:
100
- PrettyOutput.section("工具调用统计", OutputType.SYSTEM)
101
- print(
102
- tabulate(table_data, headers=["工具名称", "调用次数"], tablefmt="grid")
103
- )
42
+ @app.command("stat")
43
+ def stat_tools(as_json: bool = typer.Option(False, "--json", help="以JSON格式输出")):
44
+ """显示工具调用统计信息"""
45
+ registry = ToolRegistry()
46
+ stats = registry._get_tool_stats()
47
+ tools = registry.get_all_tools()
48
+
49
+ table_data = []
50
+ for tool in tools:
51
+ name = tool["name"]
52
+ count = stats.get(name, 0)
53
+ table_data.append([name, count])
104
54
 
105
- return 0
106
-
107
- elif args.command == "call":
108
- tool_name = args.tool_name
109
- tool_obj = registry.get_tool(tool_name)
110
-
111
- if not tool_obj:
112
- PrettyOutput.print(f"错误: 工具 '{tool_name}' 不存在", OutputType.ERROR)
113
- available_tools = ", ".join([t["name"] for t in registry.get_all_tools()])
114
- print(f"可用工具: {available_tools}")
115
- return 1
116
-
117
- # 获取参数: 支持从命令行直接传入或从文件加载
118
- tool_args = {}
119
- if args.args:
120
- try:
121
- tool_args = json.loads(args.args) # 解析JSON格式参数
122
- except json.JSONDecodeError:
123
- PrettyOutput.print("错误: 参数必须是有效的JSON格式", OutputType.ERROR)
124
- return 1
125
-
126
- elif args.args_file:
127
- try:
128
- with open(args.args_file, "r", encoding="utf-8") as f:
129
- tool_args = json.load(f) # 从文件加载JSON参数
130
- except (json.JSONDecodeError, FileNotFoundError) as e:
131
- PrettyOutput.print(
132
- f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR
133
- )
134
- return 1
135
-
136
- # 检查必需参数是否完整
137
- required_params = tool_obj.parameters.get("required", [])
138
- missing_params = [p for p in required_params if p not in tool_args]
139
-
140
- if missing_params:
55
+ table_data.sort(key=lambda x: x[1], reverse=True)
56
+
57
+ if as_json:
58
+ print(json.dumps(dict(table_data), indent=2))
59
+ else:
60
+ PrettyOutput.section("工具调用统计", OutputType.SYSTEM)
61
+ print(tabulate(table_data, headers=["工具名称", "调用次数"], tablefmt="grid"))
62
+
63
+
64
+ @app.command("call")
65
+ def call_tool(
66
+ tool_name: str = typer.Argument(..., help="要调用的工具名称"),
67
+ args: Optional[str] = typer.Option(None, "--args", help="工具参数 (JSON格式)"),
68
+ args_file: Optional[str] = typer.Option(
69
+ None, "--args-file", help="从文件加载工具参数 (JSON格式)"
70
+ ),
71
+ ):
72
+ """调用指定工具"""
73
+ registry = ToolRegistry()
74
+ tool_obj = registry.get_tool(tool_name)
75
+
76
+ if not tool_obj:
77
+ PrettyOutput.print(f"错误: 工具 '{tool_name}' 不存在", OutputType.ERROR)
78
+ available_tools = ", ".join([t["name"] for t in registry.get_all_tools()])
79
+ print(f"可用工具: {available_tools}")
80
+ raise typer.Exit(code=1)
81
+
82
+ tool_args = {}
83
+ if args:
84
+ try:
85
+ tool_args = json.loads(args)
86
+ except json.JSONDecodeError:
87
+ PrettyOutput.print("错误: 参数必须是有效的JSON格式", OutputType.ERROR)
88
+ raise typer.Exit(code=1)
89
+ elif args_file:
90
+ try:
91
+ with open(args_file, "r", encoding="utf-8") as f:
92
+ tool_args = json.load(f)
93
+ except (json.JSONDecodeError, FileNotFoundError) as e:
141
94
  PrettyOutput.print(
142
- f"错误: 缺少必需参数: {', '.join(missing_params)}", OutputType.ERROR
95
+ f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR
143
96
  )
144
- print("\n参数说明:")
145
- params = tool_obj.parameters.get("properties", {})
146
- for param_name in required_params:
147
- param_info = params.get(param_name, {})
148
- desc = param_info.get("description", "无描述")
149
- print(f" - {param_name}: {desc}")
150
- return 1
151
-
152
- # 执行工具并处理结果
153
- result = registry.execute_tool(tool_name, tool_args)
154
-
155
- # 显示执行结果
156
- if result["success"]:
157
- PrettyOutput.section(f"工具 {tool_name} 执行成功", OutputType.SUCCESS)
158
- else:
159
- PrettyOutput.section(f"工具 {tool_name} 执行失败", OutputType.ERROR)
97
+ raise typer.Exit(code=1)
98
+
99
+ required_params = tool_obj.parameters.get("required", [])
100
+ missing_params = [p for p in required_params if p not in tool_args]
101
+
102
+ if missing_params:
103
+ PrettyOutput.print(
104
+ f"错误: 缺少必需参数: {', '.join(missing_params)}", OutputType.ERROR
105
+ )
106
+ print("\n参数说明:")
107
+ params = tool_obj.parameters.get("properties", {})
108
+ for param_name in required_params:
109
+ param_info = params.get(param_name, {})
110
+ desc = param_info.get("description", "无描述")
111
+ print(f" - {param_name}: {desc}")
112
+ raise typer.Exit(code=1)
113
+
114
+ result = registry.execute_tool(tool_name, tool_args)
115
+
116
+ if result["success"]:
117
+ PrettyOutput.section(f"工具 {tool_name} 执行成功", OutputType.SUCCESS)
118
+ else:
119
+ PrettyOutput.section(f"工具 {tool_name} 执行失败", OutputType.ERROR)
160
120
 
161
- if result.get("stdout"):
162
- print("\n输出:")
163
- print(result["stdout"])
121
+ if result.get("stdout"):
122
+ print("\n输出:")
123
+ print(result["stdout"])
164
124
 
165
- if result.get("stderr"):
166
- PrettyOutput.print("\n错误:", OutputType.ERROR)
167
- print(result["stderr"])
125
+ if result.get("stderr"):
126
+ PrettyOutput.print("\n错误:", OutputType.ERROR)
127
+ print(result["stderr"])
168
128
 
169
- return 0 if result["success"] else 1
129
+ if not result["success"]:
130
+ raise typer.Exit(code=1)
131
+
132
+
133
+ def cli():
134
+ """Typer application entry point"""
135
+ init_env("欢迎使用 Jarvis-Tools,您的工具系统已准备就绪!")
136
+ app()
170
137
 
171
- else:
172
- parser.print_help()
173
138
 
174
- return 0
139
+ def main():
140
+ """Main entry point for the script"""
141
+ cli()
175
142
 
176
143
 
177
144
  if __name__ == "__main__":
178
- sys.exit(main())
145
+ main()
@@ -594,13 +594,7 @@ class ToolRegistry(OutputHandlerProtocol):
594
594
  OutputType.INFO,
595
595
  )
596
596
  PrettyOutput.print(fixed_content, OutputType.TOOL)
597
- if user_confirm("这是纠正后的,是否需要执行?", default=True):
598
- data = temp_data
599
- else:
600
- return (
601
- {},
602
- f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
603
- )
597
+ data = temp_data
604
598
  except (yaml.YAMLError, EOFError, KeyboardInterrupt):
605
599
  # Even after fixing, it's not valid YAML, or user cancelled.
606
600
  # Fall through to the original error.
@@ -2,9 +2,13 @@
2
2
  """A tool for searching the web."""
3
3
  from typing import Any, Dict
4
4
 
5
- import httpx
6
- from markdownify import markdownify as md
7
- from ddgs import DDGS
5
+ import requests
6
+ from markdownify import markdownify as md # type: ignore
7
+
8
+ # pylint: disable=import-error,missing-module-docstring
9
+ # fmt: off
10
+ from ddgs import DDGS # type: ignore[import-not-found]
11
+ # fmt: on
8
12
 
9
13
  from jarvis.jarvis_agent import Agent
10
14
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -53,18 +57,18 @@ class SearchWebTool:
53
57
  f"📄 ({visited_count + 1}/10) 正在抓取: {title} ({url})",
54
58
  OutputType.INFO,
55
59
  )
56
- response = http_get(url, timeout=10.0, follow_redirects=True)
57
- content = md(response.text, strip=['script', 'style'])
60
+ response = http_get(url, timeout=10.0, allow_redirects=True)
61
+ content = md(response.text, strip=["script", "style"])
58
62
  if content:
59
63
  full_content += content + "\n\n"
60
64
  visited_urls.append(url)
61
65
  visited_count += 1
62
- except httpx.HTTPStatusError as e:
66
+ except requests.exceptions.HTTPError as e:
63
67
  PrettyOutput.print(
64
68
  f"⚠️ HTTP错误 {e.response.status_code} 访问 {url}",
65
69
  OutputType.WARNING,
66
70
  )
67
- except httpx.RequestError as e:
71
+ except requests.exceptions.RequestException as e:
68
72
  PrettyOutput.print(f"⚠️ 请求错误: {e}", OutputType.WARNING)
69
73
 
70
74
  if not full_content.strip():
@@ -75,9 +79,7 @@ class SearchWebTool:
75
79
  }
76
80
 
77
81
  url_list_str = "\n".join(f" - {u}" for u in visited_urls)
78
- PrettyOutput.print(
79
- f"🔍 已成功访问并处理以下URL:\n{url_list_str}", OutputType.INFO
80
- )
82
+ PrettyOutput.print(f"🔍 已成功访问并处理以下URL:\n{url_list_str}", OutputType.INFO)
81
83
 
82
84
  PrettyOutput.print("🧠 正在总结内容...", OutputType.INFO)
83
85
  summary_prompt = f"请为查询“{query}”总结以下内容:\n\n{full_content}"