Undefined-bot 2.1.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.
- Undefined/__init__.py +3 -0
- Undefined/__main__.py +6 -0
- Undefined/ai.py +1215 -0
- Undefined/config.py +371 -0
- Undefined/end_summary_storage.py +48 -0
- Undefined/faq.py +244 -0
- Undefined/handlers.py +1247 -0
- Undefined/injection_response_agent.py +131 -0
- Undefined/main.py +126 -0
- Undefined/memory.py +120 -0
- Undefined/onebot.py +512 -0
- Undefined/rate_limit.py +130 -0
- Undefined/render.py +123 -0
- Undefined/scheduled_task_storage.py +88 -0
- Undefined/services/__init__.py +1 -0
- Undefined/services/queue_manager.py +206 -0
- Undefined/skills/README.md +53 -0
- Undefined/skills/__init__.py +10 -0
- Undefined/skills/agents/README.md +144 -0
- Undefined/skills/agents/__init__.py +116 -0
- Undefined/skills/agents/entertainment_agent/config.json +17 -0
- Undefined/skills/agents/entertainment_agent/handler.py +220 -0
- Undefined/skills/agents/entertainment_agent/intro.md +25 -0
- Undefined/skills/agents/entertainment_agent/prompt.md +20 -0
- Undefined/skills/agents/entertainment_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/entertainment_agent/tools/ai_draw_one/config.json +34 -0
- Undefined/skills/agents/entertainment_agent/tools/ai_draw_one/handler.py +62 -0
- Undefined/skills/agents/entertainment_agent/tools/ai_study_helper/config.json +22 -0
- Undefined/skills/agents/entertainment_agent/tools/ai_study_helper/handler.py +35 -0
- Undefined/skills/agents/entertainment_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/entertainment_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/entertainment_agent/tools/horoscope/config.json +24 -0
- Undefined/skills/agents/entertainment_agent/tools/horoscope/handler.py +141 -0
- Undefined/skills/agents/entertainment_agent/tools/minecraft_skin/config.json +43 -0
- Undefined/skills/agents/entertainment_agent/tools/minecraft_skin/handler.py +55 -0
- Undefined/skills/agents/entertainment_agent/tools/novel_search/config.json +25 -0
- Undefined/skills/agents/entertainment_agent/tools/novel_search/handler.py +31 -0
- Undefined/skills/agents/entertainment_agent/tools/renjian/config.json +12 -0
- Undefined/skills/agents/entertainment_agent/tools/renjian/handler.py +30 -0
- Undefined/skills/agents/entertainment_agent/tools/wenchang_dijun/config.json +12 -0
- Undefined/skills/agents/entertainment_agent/tools/wenchang_dijun/handler.py +44 -0
- Undefined/skills/agents/file_analysis_agent/__init__.py +1 -0
- Undefined/skills/agents/file_analysis_agent/config.json +21 -0
- Undefined/skills/agents/file_analysis_agent/handler.py +248 -0
- Undefined/skills/agents/file_analysis_agent/intro.md +22 -0
- Undefined/skills/agents/file_analysis_agent/prompt.md +36 -0
- Undefined/skills/agents/file_analysis_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/file_analysis_agent/tools/analyze_code/config.json +17 -0
- Undefined/skills/agents/file_analysis_agent/tools/analyze_code/handler.py +427 -0
- Undefined/skills/agents/file_analysis_agent/tools/analyze_multimodal/config.json +25 -0
- Undefined/skills/agents/file_analysis_agent/tools/analyze_multimodal/handler.py +178 -0
- Undefined/skills/agents/file_analysis_agent/tools/cleanup_temp/config.json +16 -0
- Undefined/skills/agents/file_analysis_agent/tools/cleanup_temp/handler.py +35 -0
- Undefined/skills/agents/file_analysis_agent/tools/detect_file_type/config.json +17 -0
- Undefined/skills/agents/file_analysis_agent/tools/detect_file_type/handler.py +221 -0
- Undefined/skills/agents/file_analysis_agent/tools/download_file/config.json +21 -0
- Undefined/skills/agents/file_analysis_agent/tools/download_file/handler.py +124 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_archive/config.json +25 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_archive/handler.py +190 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_docx/config.json +17 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_docx/handler.py +78 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_pdf/config.json +21 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_pdf/handler.py +67 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_pptx/config.json +17 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_pptx/handler.py +73 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_xlsx/config.json +17 -0
- Undefined/skills/agents/file_analysis_agent/tools/extract_xlsx/handler.py +101 -0
- Undefined/skills/agents/file_analysis_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/file_analysis_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/file_analysis_agent/tools/read_text_file/config.json +21 -0
- Undefined/skills/agents/file_analysis_agent/tools/read_text_file/handler.py +90 -0
- Undefined/skills/agents/info_agent/config.json +17 -0
- Undefined/skills/agents/info_agent/handler.py +220 -0
- Undefined/skills/agents/info_agent/intro.md +22 -0
- Undefined/skills/agents/info_agent/prompt.md +27 -0
- Undefined/skills/agents/info_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/info_agent/tools/baiduhot/config.json +18 -0
- Undefined/skills/agents/info_agent/tools/baiduhot/handler.py +49 -0
- Undefined/skills/agents/info_agent/tools/base64/config.json +22 -0
- Undefined/skills/agents/info_agent/tools/base64/handler.py +44 -0
- Undefined/skills/agents/info_agent/tools/douyinhot/config.json +18 -0
- Undefined/skills/agents/info_agent/tools/douyinhot/handler.py +53 -0
- Undefined/skills/agents/info_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/info_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/info_agent/tools/gold_price/config.json +12 -0
- Undefined/skills/agents/info_agent/tools/gold_price/handler.py +58 -0
- Undefined/skills/agents/info_agent/tools/hash/config.json +22 -0
- Undefined/skills/agents/info_agent/tools/hash/handler.py +43 -0
- Undefined/skills/agents/info_agent/tools/history/config.json +12 -0
- Undefined/skills/agents/info_agent/tools/history/handler.py +37 -0
- Undefined/skills/agents/info_agent/tools/net_check/config.json +17 -0
- Undefined/skills/agents/info_agent/tools/net_check/handler.py +117 -0
- Undefined/skills/agents/info_agent/tools/news_tencent/config.json +17 -0
- Undefined/skills/agents/info_agent/tools/news_tencent/handler.py +38 -0
- Undefined/skills/agents/info_agent/tools/qq_level_query/config.json +29 -0
- Undefined/skills/agents/info_agent/tools/qq_level_query/handler.py +48 -0
- Undefined/skills/agents/info_agent/tools/speed/config.json +17 -0
- Undefined/skills/agents/info_agent/tools/speed/handler.py +37 -0
- Undefined/skills/agents/info_agent/tools/tcping/config.json +21 -0
- Undefined/skills/agents/info_agent/tools/tcping/handler.py +53 -0
- Undefined/skills/agents/info_agent/tools/weather_query/config.json +22 -0
- Undefined/skills/agents/info_agent/tools/weather_query/handler.py +207 -0
- Undefined/skills/agents/info_agent/tools/weibohot/config.json +18 -0
- Undefined/skills/agents/info_agent/tools/weibohot/handler.py +49 -0
- Undefined/skills/agents/info_agent/tools/whois/config.json +17 -0
- Undefined/skills/agents/info_agent/tools/whois/handler.py +63 -0
- Undefined/skills/agents/naga_code_analysis_agent/config.json +17 -0
- Undefined/skills/agents/naga_code_analysis_agent/handler.py +222 -0
- Undefined/skills/agents/naga_code_analysis_agent/intro.md +17 -0
- Undefined/skills/agents/naga_code_analysis_agent/prompt.md +19 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/glob/config.json +17 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/glob/handler.py +37 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/list_directory/config.json +17 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/list_directory/handler.py +31 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/read_file/config.json +17 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/read_file/handler.py +66 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/read_naga_intro/config.json +12 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/read_naga_intro/handler.py +327 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/search_file_content/config.json +25 -0
- Undefined/skills/agents/naga_code_analysis_agent/tools/search_file_content/handler.py +46 -0
- Undefined/skills/agents/scheduler_agent/__init__.py +1 -0
- Undefined/skills/agents/scheduler_agent/config.json +17 -0
- Undefined/skills/agents/scheduler_agent/handler.py +218 -0
- Undefined/skills/agents/scheduler_agent/intro.md +17 -0
- Undefined/skills/agents/scheduler_agent/prompt.md +67 -0
- Undefined/skills/agents/scheduler_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/scheduler_agent/tools/create_schedule_task/config.json +37 -0
- Undefined/skills/agents/scheduler_agent/tools/create_schedule_task/handler.py +68 -0
- Undefined/skills/agents/scheduler_agent/tools/delete_schedule_task/config.json +19 -0
- Undefined/skills/agents/scheduler_agent/tools/delete_schedule_task/handler.py +26 -0
- Undefined/skills/agents/scheduler_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/scheduler_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/scheduler_agent/tools/list_schedule_tasks/config.json +11 -0
- Undefined/skills/agents/scheduler_agent/tools/list_schedule_tasks/handler.py +47 -0
- Undefined/skills/agents/scheduler_agent/tools/update_schedule_task/config.json +39 -0
- Undefined/skills/agents/scheduler_agent/tools/update_schedule_task/handler.py +46 -0
- Undefined/skills/agents/social_agent/config.json +17 -0
- Undefined/skills/agents/social_agent/handler.py +220 -0
- Undefined/skills/agents/social_agent/intro.md +17 -0
- Undefined/skills/agents/social_agent/prompt.md +19 -0
- Undefined/skills/agents/social_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/social_agent/tools/bilibili_search/config.json +21 -0
- Undefined/skills/agents/social_agent/tools/bilibili_search/handler.py +68 -0
- Undefined/skills/agents/social_agent/tools/bilibili_user_info/config.json +17 -0
- Undefined/skills/agents/social_agent/tools/bilibili_user_info/handler.py +68 -0
- Undefined/skills/agents/social_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/social_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/social_agent/tools/music_global_search/config.json +21 -0
- Undefined/skills/agents/social_agent/tools/music_global_search/handler.py +47 -0
- Undefined/skills/agents/social_agent/tools/music_info_get/config.json +22 -0
- Undefined/skills/agents/social_agent/tools/music_info_get/handler.py +35 -0
- Undefined/skills/agents/social_agent/tools/music_lyrics/config.json +22 -0
- Undefined/skills/agents/social_agent/tools/music_lyrics/handler.py +26 -0
- Undefined/skills/agents/social_agent/tools/video_random_recommend/config.json +21 -0
- Undefined/skills/agents/social_agent/tools/video_random_recommend/handler.py +21 -0
- Undefined/skills/agents/web_agent/config.json +17 -0
- Undefined/skills/agents/web_agent/handler.py +221 -0
- Undefined/skills/agents/web_agent/intro.md +14 -0
- Undefined/skills/agents/web_agent/prompt.md +16 -0
- Undefined/skills/agents/web_agent/tools/__init__.py +1 -0
- Undefined/skills/agents/web_agent/tools/crawl_webpage/config.json +21 -0
- Undefined/skills/agents/web_agent/tools/crawl_webpage/handler.py +102 -0
- Undefined/skills/agents/web_agent/tools/get_current_time/config.json +12 -0
- Undefined/skills/agents/web_agent/tools/get_current_time/handler.py +5 -0
- Undefined/skills/agents/web_agent/tools/web_search/config.json +21 -0
- Undefined/skills/agents/web_agent/tools/web_search/handler.py +29 -0
- Undefined/skills/tools/README.md +85 -0
- Undefined/skills/tools/__init__.py +120 -0
- Undefined/skills/tools/debug/config.json +17 -0
- Undefined/skills/tools/debug/handler.py +35 -0
- Undefined/skills/tools/end/config.json +17 -0
- Undefined/skills/tools/end/handler.py +24 -0
- Undefined/skills/tools/get_current_time/config.json +12 -0
- Undefined/skills/tools/get_current_time/handler.py +5 -0
- Undefined/skills/tools/get_forward_msg/config.json +17 -0
- Undefined/skills/tools/get_forward_msg/handler.py +131 -0
- Undefined/skills/tools/get_group_member_info/config.json +38 -0
- Undefined/skills/tools/get_group_member_info/handler.py +142 -0
- Undefined/skills/tools/get_messages_by_time/config.json +30 -0
- Undefined/skills/tools/get_messages_by_time/handler.py +128 -0
- Undefined/skills/tools/get_picture/config.json +45 -0
- Undefined/skills/tools/get_picture/handler.py +191 -0
- Undefined/skills/tools/get_recent_messages/config.json +30 -0
- Undefined/skills/tools/get_recent_messages/handler.py +88 -0
- Undefined/skills/tools/qq_like/config.json +22 -0
- Undefined/skills/tools/qq_like/handler.py +58 -0
- Undefined/skills/tools/render_html/config.json +26 -0
- Undefined/skills/tools/render_html/handler.py +39 -0
- Undefined/skills/tools/render_latex/config.json +26 -0
- Undefined/skills/tools/render_latex/handler.py +78 -0
- Undefined/skills/tools/render_markdown/config.json +26 -0
- Undefined/skills/tools/render_markdown/handler.py +63 -0
- Undefined/skills/tools/save_memory/config.json +17 -0
- Undefined/skills/tools/save_memory/handler.py +17 -0
- Undefined/skills/tools/send_message/config.json +21 -0
- Undefined/skills/tools/send_message/handler.py +60 -0
- Undefined/skills/tools/send_private_message/config.json +21 -0
- Undefined/skills/tools/send_private_message/handler.py +35 -0
- Undefined/utils/__init__.py +0 -0
- Undefined/utils/common.py +186 -0
- Undefined/utils/history.py +284 -0
- Undefined/utils/scheduler.py +286 -0
- Undefined/utils/sender.py +140 -0
- undefined_bot-2.1.0.dist-info/METADATA +259 -0
- undefined_bot-2.1.0.dist-info/RECORD +211 -0
- undefined_bot-2.1.0.dist-info/WHEEL +4 -0
- undefined_bot-2.1.0.dist-info/entry_points.txt +2 -0
- undefined_bot-2.1.0.dist-info/licenses/LICENSE +7 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import aiohttp
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Dict, Any, cast
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
API_KEY = os.getenv("WEATHER_API_KEY", "")
|
|
9
|
+
BASE_URL = "https://api.seniverse.com/v3"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def fetch_data(url: str, params: Dict[str, Any]) -> Dict[str, Any]:
|
|
13
|
+
if not API_KEY:
|
|
14
|
+
logger.error("WEATHER_API_KEY 未设置")
|
|
15
|
+
return {"error": "天气服务未配置API密钥"}
|
|
16
|
+
|
|
17
|
+
params["key"] = API_KEY
|
|
18
|
+
params["language"] = "zh-Hans"
|
|
19
|
+
params["unit"] = "c"
|
|
20
|
+
|
|
21
|
+
async with aiohttp.ClientSession() as session:
|
|
22
|
+
async with session.get(url, params=params) as response:
|
|
23
|
+
if response.status != 200:
|
|
24
|
+
error_text = await response.text()
|
|
25
|
+
logger.error(f"天气 API 错误: {response.status} - {error_text}")
|
|
26
|
+
return {"error": f"API请求失败: {response.status}"}
|
|
27
|
+
json_data = await response.json()
|
|
28
|
+
return cast(Dict[str, Any], json_data)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
async def get_weather_now(location: str) -> str:
|
|
32
|
+
url = f"{BASE_URL}/weather/now.json"
|
|
33
|
+
data = await fetch_data(url, {"location": location})
|
|
34
|
+
|
|
35
|
+
if "error" in data:
|
|
36
|
+
return str(data["error"])
|
|
37
|
+
|
|
38
|
+
if not data.get("results"):
|
|
39
|
+
return "未找到该城市的天气信息。"
|
|
40
|
+
|
|
41
|
+
results = cast(list[dict[str, Any]], data["results"])
|
|
42
|
+
result = results[0]
|
|
43
|
+
loc = cast(dict[str, Any], result["location"])
|
|
44
|
+
now = cast(dict[str, Any], result["now"])
|
|
45
|
+
update_time = str(result["last_update"]).split("T")[1].split("+")[0]
|
|
46
|
+
|
|
47
|
+
msg = [f"【{loc['name']} 天气实况】"]
|
|
48
|
+
|
|
49
|
+
if "text" in now:
|
|
50
|
+
msg.append(f"天气: {now['text']}")
|
|
51
|
+
if "temperature" in now:
|
|
52
|
+
msg.append(f"温度: {now['temperature']}°C")
|
|
53
|
+
|
|
54
|
+
if "feels_like" in now:
|
|
55
|
+
msg.append(f"体感: {now['feels_like']}°C")
|
|
56
|
+
if "humidity" in now:
|
|
57
|
+
msg.append(f"湿度: {now['humidity']}%")
|
|
58
|
+
if "wind_direction" in now:
|
|
59
|
+
wind_dir = str(now["wind_direction"])
|
|
60
|
+
if "wind_direction_degree" in now:
|
|
61
|
+
wind_dir += f" ({now['wind_direction_degree']}°)"
|
|
62
|
+
msg.append(f"风向: {wind_dir}")
|
|
63
|
+
elif "wind_direction_degree" in now:
|
|
64
|
+
msg.append(f"风向: {now['wind_direction_degree']}°")
|
|
65
|
+
|
|
66
|
+
if "wind_speed" in now:
|
|
67
|
+
msg.append(f"风速: {now['wind_speed']}km/h")
|
|
68
|
+
if "wind_scale" in now:
|
|
69
|
+
msg.append(f"风力等级: {now['wind_scale']}")
|
|
70
|
+
if "visibility" in now:
|
|
71
|
+
msg.append(f"能见度: {now['visibility']}km")
|
|
72
|
+
|
|
73
|
+
msg.append(f"更新时间: {update_time}")
|
|
74
|
+
|
|
75
|
+
return "\n".join(msg)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
async def get_weather_forecast(location: str) -> str:
|
|
79
|
+
url = f"{BASE_URL}/weather/daily.json"
|
|
80
|
+
# start=0 包括今天。days=5 为请求的范围。
|
|
81
|
+
data = await fetch_data(url, {"location": location, "start": "0", "days": "5"})
|
|
82
|
+
|
|
83
|
+
if "error" in data:
|
|
84
|
+
return str(data["error"])
|
|
85
|
+
|
|
86
|
+
if not data.get("results"):
|
|
87
|
+
return "未找到该城市的天气预报。"
|
|
88
|
+
|
|
89
|
+
results = cast(list[dict[str, Any]], data["results"])
|
|
90
|
+
result = results[0]
|
|
91
|
+
loc_name = str(result["location"]["name"])
|
|
92
|
+
daily_data = cast(list[dict[str, Any]], result["daily"])
|
|
93
|
+
|
|
94
|
+
msg = [f"【{loc_name} 未来天气预报】"]
|
|
95
|
+
for day in daily_data:
|
|
96
|
+
date = day.get("date", "未知日期")
|
|
97
|
+
text_day = day.get("text_day")
|
|
98
|
+
text_night = day.get("text_night")
|
|
99
|
+
high = day.get("high")
|
|
100
|
+
low = day.get("low")
|
|
101
|
+
precip = day.get("precip")
|
|
102
|
+
wind_scale = day.get("wind_scale")
|
|
103
|
+
|
|
104
|
+
day_info = [f"{date}:"]
|
|
105
|
+
if text_day and text_night:
|
|
106
|
+
weather_str = (
|
|
107
|
+
text_day if text_day == text_night else f"{text_day}转{text_night}"
|
|
108
|
+
)
|
|
109
|
+
day_info.append(str(weather_str))
|
|
110
|
+
elif text_day:
|
|
111
|
+
day_info.append(str(text_day))
|
|
112
|
+
|
|
113
|
+
if low is not None and high is not None:
|
|
114
|
+
day_info.append(f"{low}~{high}°C")
|
|
115
|
+
|
|
116
|
+
if precip:
|
|
117
|
+
day_info.append(f"降水概率{precip}%")
|
|
118
|
+
|
|
119
|
+
if wind_scale:
|
|
120
|
+
day_info.append(f"风力{wind_scale}级")
|
|
121
|
+
|
|
122
|
+
msg.append(" ".join(day_info))
|
|
123
|
+
|
|
124
|
+
return "\n".join(msg)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
async def get_life_suggestion(location: str) -> str:
|
|
128
|
+
url = f"{BASE_URL}/life/suggestion.json"
|
|
129
|
+
data = await fetch_data(url, {"location": location})
|
|
130
|
+
|
|
131
|
+
if "error" in data:
|
|
132
|
+
return str(data["error"])
|
|
133
|
+
|
|
134
|
+
if not data.get("results"):
|
|
135
|
+
return "未找到该城市的生活指数信息。"
|
|
136
|
+
|
|
137
|
+
results = cast(list[dict[str, Any]], data["results"])
|
|
138
|
+
result = results[0]
|
|
139
|
+
loc_name = str(result["location"]["name"])
|
|
140
|
+
suggestion = cast(dict[str, Any], result.get("suggestion", {}))
|
|
141
|
+
|
|
142
|
+
label_map = {
|
|
143
|
+
"ac": "空调开启",
|
|
144
|
+
"air_pollution": "空气扩散",
|
|
145
|
+
"airing": "晾晒",
|
|
146
|
+
"allergy": "过敏",
|
|
147
|
+
"beer": "啤酒",
|
|
148
|
+
"boating": "划船",
|
|
149
|
+
"car_washing": "洗车",
|
|
150
|
+
"chill": "风寒",
|
|
151
|
+
"comfort": "舒适度",
|
|
152
|
+
"dating": "约会",
|
|
153
|
+
"dressing": "穿衣",
|
|
154
|
+
"fishing": "钓鱼",
|
|
155
|
+
"flu": "感冒",
|
|
156
|
+
"hair_dressing": "美发",
|
|
157
|
+
"kiteflying": "放风筝",
|
|
158
|
+
"makeup": "化妆",
|
|
159
|
+
"mood": "心情",
|
|
160
|
+
"morning_sport": "晨练",
|
|
161
|
+
"night_life": "夜生活",
|
|
162
|
+
"road_condition": "路况",
|
|
163
|
+
"shopping": "购物",
|
|
164
|
+
"sport": "运动",
|
|
165
|
+
"sunscreen": "防晒",
|
|
166
|
+
"traffic": "交通",
|
|
167
|
+
"travel": "旅游",
|
|
168
|
+
"umbrella": "雨伞",
|
|
169
|
+
"uv": "紫外线",
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
msg = [f"【{loc_name} 生活指数】"]
|
|
173
|
+
|
|
174
|
+
for key, info_raw in suggestion.items():
|
|
175
|
+
info = cast(dict[str, Any], info_raw)
|
|
176
|
+
if not info or not info.get("brief"):
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
label = label_map.get(key, key)
|
|
180
|
+
brief = info["brief"]
|
|
181
|
+
msg.append(f"{label}: {brief}")
|
|
182
|
+
|
|
183
|
+
if len(msg) == 1:
|
|
184
|
+
return f"【{loc_name}】暂无生活指数信息。"
|
|
185
|
+
|
|
186
|
+
return "\n".join(msg)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
|
|
190
|
+
location = args.get("location")
|
|
191
|
+
query_type = args.get("query_type", "now")
|
|
192
|
+
|
|
193
|
+
if not location:
|
|
194
|
+
return "请提供城市名称。"
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
if query_type == "forecast":
|
|
198
|
+
return await get_weather_forecast(location)
|
|
199
|
+
elif query_type == "life":
|
|
200
|
+
return await get_life_suggestion(location)
|
|
201
|
+
else:
|
|
202
|
+
# 默认为当前天气
|
|
203
|
+
return await get_weather_now(location)
|
|
204
|
+
|
|
205
|
+
except Exception as e:
|
|
206
|
+
logger.exception(f"天气查询工具出错: {e}")
|
|
207
|
+
return f"查询出错: {str(e)}"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "weibohot",
|
|
5
|
+
"description": "获取微博热搜排行榜,实时返回当前热门话题和趋势。",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"limit": {
|
|
10
|
+
"type": "integer",
|
|
11
|
+
"description": "返回的热搜数量,默认10",
|
|
12
|
+
"default": 10
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"required": []
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
import logging
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
|
|
8
|
+
limit = args.get("limit", 10)
|
|
9
|
+
|
|
10
|
+
if limit < 1 or limit > 50:
|
|
11
|
+
return "❌ 热搜数量必须在 1-50 之间"
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
async with httpx.AsyncClient(timeout=15.0) as client:
|
|
15
|
+
logger.info(f"获取微博热搜,数量: {limit}")
|
|
16
|
+
|
|
17
|
+
response = await client.get("https://v2.xxapi.cn/api/weibohot")
|
|
18
|
+
response.raise_for_status()
|
|
19
|
+
data = response.json()
|
|
20
|
+
|
|
21
|
+
if data.get("code") != 200:
|
|
22
|
+
return f"获取微博热搜失败: {data.get('msg')}"
|
|
23
|
+
|
|
24
|
+
hot_list = data.get("data", [])
|
|
25
|
+
if not hot_list:
|
|
26
|
+
return "暂无热搜数据"
|
|
27
|
+
|
|
28
|
+
result = f"【微博热搜 TOP {min(limit, len(hot_list))}】\n\n"
|
|
29
|
+
|
|
30
|
+
for idx, item in enumerate(hot_list[:limit], 1):
|
|
31
|
+
title = item.get("title", "")
|
|
32
|
+
hot = item.get("hot", "")
|
|
33
|
+
url = item.get("url", "")
|
|
34
|
+
result += f"{idx}. {title}\n"
|
|
35
|
+
result += f" 热度: {hot}\n"
|
|
36
|
+
if url:
|
|
37
|
+
result += f" 链接: {url}\n"
|
|
38
|
+
result += "\n"
|
|
39
|
+
|
|
40
|
+
return result
|
|
41
|
+
|
|
42
|
+
except httpx.TimeoutException:
|
|
43
|
+
return "请求超时,请稍后重试"
|
|
44
|
+
except httpx.HTTPStatusError as e:
|
|
45
|
+
logger.error(f"HTTP 错误: {e}")
|
|
46
|
+
return f"获取微博热搜失败: {e}"
|
|
47
|
+
except Exception as e:
|
|
48
|
+
logger.exception(f"获取微博热搜失败: {e}")
|
|
49
|
+
return f"获取微博热搜失败: {e}"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "whois",
|
|
5
|
+
"description": "查询域名的Whois信息,包括注册商、注册人、注册时间、到期时间、DNS服务器等信息。",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"domain": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "需要查询的域名,例如:example.com"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": ["domain"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
import logging
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
|
|
8
|
+
domain = args.get("domain")
|
|
9
|
+
|
|
10
|
+
if not domain:
|
|
11
|
+
return "❌ 域名不能为空"
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
async with httpx.AsyncClient(timeout=15.0) as client:
|
|
15
|
+
params = {"domain": domain}
|
|
16
|
+
logger.info(f"查询Whois信息: {domain}")
|
|
17
|
+
|
|
18
|
+
response = await client.get("https://v2.xxapi.cn/api/whois", params=params)
|
|
19
|
+
response.raise_for_status()
|
|
20
|
+
data = response.json()
|
|
21
|
+
|
|
22
|
+
if data.get("code") != 200:
|
|
23
|
+
return f"查询Whois失败: {data.get('msg')}"
|
|
24
|
+
|
|
25
|
+
whois_data = data.get("data", {})
|
|
26
|
+
result = f"【{domain} Whois信息】\n\n"
|
|
27
|
+
|
|
28
|
+
domain_name = whois_data.get("Domain Name", "")
|
|
29
|
+
registrar = whois_data.get("Sponsoring Registrar", "")
|
|
30
|
+
registrar_url = whois_data.get("Registrar URL", "")
|
|
31
|
+
registrant = whois_data.get("Registrant", "")
|
|
32
|
+
registrant_email = whois_data.get("Registrant Contact Email", "")
|
|
33
|
+
registration_time = whois_data.get("Registration Time", "")
|
|
34
|
+
expiration_time = whois_data.get("Expiration Time", "")
|
|
35
|
+
dns_servers = whois_data.get("DNS Serve", [])
|
|
36
|
+
|
|
37
|
+
if domain_name:
|
|
38
|
+
result += f"域名: {domain_name}\n"
|
|
39
|
+
if registrar:
|
|
40
|
+
result += f"注册商: {registrar}\n"
|
|
41
|
+
if registrar_url:
|
|
42
|
+
result += f"注册商URL: {registrar_url}\n"
|
|
43
|
+
if registrant:
|
|
44
|
+
result += f"注册人: {registrant}\n"
|
|
45
|
+
if registrant_email:
|
|
46
|
+
result += f"注册人邮箱: {registrant_email}\n"
|
|
47
|
+
if registration_time:
|
|
48
|
+
result += f"注册时间: {registration_time}\n"
|
|
49
|
+
if expiration_time:
|
|
50
|
+
result += f"到期时间: {expiration_time}\n"
|
|
51
|
+
if dns_servers:
|
|
52
|
+
result += f"DNS服务器: {', '.join(dns_servers)}\n"
|
|
53
|
+
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
except httpx.TimeoutException:
|
|
57
|
+
return "请求超时,请稍后重试"
|
|
58
|
+
except httpx.HTTPStatusError as e:
|
|
59
|
+
logger.error(f"HTTP 错误: {e}")
|
|
60
|
+
return f"查询Whois失败: {e}"
|
|
61
|
+
except Exception as e:
|
|
62
|
+
logger.exception(f"查询Whois失败: {e}")
|
|
63
|
+
return f"查询Whois失败: {e}"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "naga_code_analysis_agent",
|
|
5
|
+
"description": "NagaAgent代码分析助手,提供针对NagaAgent项目的文件读取、目录浏览、内容搜索、文件匹配等功能,用于理解和分析代码库。",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"prompt": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "分析需求'"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": ["prompt"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
from typing import Any, Dict, Callable
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import importlib.util
|
|
4
|
+
import json
|
|
5
|
+
import asyncio
|
|
6
|
+
import aiofiles
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AgentToolRegistry:
|
|
13
|
+
"""Agent 内部的工具注册表"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, tools_dir: Path) -> None:
|
|
16
|
+
self.tools_dir: Path = tools_dir
|
|
17
|
+
self._tools_schema: list[dict[str, Any]] = []
|
|
18
|
+
self._tools_handlers: dict[str, Callable[..., Any]] = {}
|
|
19
|
+
self.load_tools()
|
|
20
|
+
|
|
21
|
+
def load_tools(self) -> None:
|
|
22
|
+
"""加载 agent 专属工具"""
|
|
23
|
+
if not self.tools_dir.exists():
|
|
24
|
+
logger.warning(f"Agent 工具目录不存在: {self.tools_dir}")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
for item in self.tools_dir.iterdir():
|
|
28
|
+
if item.is_dir() and not item.name.startswith("_"):
|
|
29
|
+
self._load_tool_from_dir(item)
|
|
30
|
+
|
|
31
|
+
logger.info(
|
|
32
|
+
f"Agent 加载了 {len(self._tools_schema)} 个工具: {list(self._tools_handlers.keys())}"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def _load_tool_from_dir(self, tool_dir: Path) -> None:
|
|
36
|
+
"""从目录加载工具"""
|
|
37
|
+
config_path: Path = tool_dir / "config.json"
|
|
38
|
+
handler_path: Path = tool_dir / "handler.py"
|
|
39
|
+
|
|
40
|
+
if not config_path.exists() or not handler_path.exists():
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
45
|
+
config: dict[str, Any] = json.load(f)
|
|
46
|
+
|
|
47
|
+
if "function" not in config or "name" not in config.get("function", {}):
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
tool_name: str = config["function"]["name"]
|
|
51
|
+
|
|
52
|
+
spec = importlib.util.spec_from_file_location(
|
|
53
|
+
f"agent_tools.{tool_name}", handler_path
|
|
54
|
+
)
|
|
55
|
+
if spec is None or spec.loader is None:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
module = importlib.util.module_from_spec(spec)
|
|
59
|
+
spec.loader.exec_module(module)
|
|
60
|
+
|
|
61
|
+
if not hasattr(module, "execute"):
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
self._tools_schema.append(config)
|
|
65
|
+
self._tools_handlers[tool_name] = module.execute
|
|
66
|
+
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"从 {tool_dir} 加载工具失败: {e}")
|
|
69
|
+
|
|
70
|
+
def get_tools_schema(self) -> list[dict[str, Any]]:
|
|
71
|
+
"""获取工具 schema"""
|
|
72
|
+
return self._tools_schema
|
|
73
|
+
|
|
74
|
+
async def execute_tool(
|
|
75
|
+
self, tool_name: str, args: dict[str, Any], context: dict[str, Any]
|
|
76
|
+
) -> str:
|
|
77
|
+
"""执行工具"""
|
|
78
|
+
handler = self._tools_handlers.get(tool_name)
|
|
79
|
+
if not handler:
|
|
80
|
+
return f"未找到工具: {tool_name}"
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
if asyncio.iscoroutinefunction(handler):
|
|
84
|
+
result = await handler(args, context)
|
|
85
|
+
else:
|
|
86
|
+
result = handler(args, context)
|
|
87
|
+
return str(result)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.exception(f"执行工具 {tool_name} 时出错")
|
|
90
|
+
return f"执行工具 {tool_name} 时出错: {str(e)}"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
async def _load_prompt() -> str:
|
|
94
|
+
"""从 prompt.md 文件加载系统提示词"""
|
|
95
|
+
prompt_path: Path = Path(__file__).parent / "prompt.md"
|
|
96
|
+
if prompt_path.exists():
|
|
97
|
+
async with aiofiles.open(prompt_path, "r", encoding="utf-8") as f:
|
|
98
|
+
return await f.read()
|
|
99
|
+
return _get_default_prompt()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _get_default_prompt() -> str:
|
|
103
|
+
"""默认提示词(当文件不存在时)"""
|
|
104
|
+
return "你是一个专业的代码分析助手..."
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
async def execute(args: Dict[str, Any], context: Dict[str, Any]) -> str:
|
|
108
|
+
"""执行 code_analysis_agent"""
|
|
109
|
+
user_prompt: str = args.get("prompt", "")
|
|
110
|
+
|
|
111
|
+
if not user_prompt:
|
|
112
|
+
return "请提供您的分析需求"
|
|
113
|
+
|
|
114
|
+
agent_tools_dir: Path = Path(__file__).parent / "tools"
|
|
115
|
+
tool_registry = AgentToolRegistry(agent_tools_dir)
|
|
116
|
+
|
|
117
|
+
tools: list[dict[str, Any]] = tool_registry.get_tools_schema()
|
|
118
|
+
|
|
119
|
+
ai_client = context.get("ai_client")
|
|
120
|
+
if not ai_client:
|
|
121
|
+
return "AI client 未在上下文中提供"
|
|
122
|
+
|
|
123
|
+
agent_config = ai_client.agent_config
|
|
124
|
+
|
|
125
|
+
system_prompt: str = await _load_prompt()
|
|
126
|
+
|
|
127
|
+
messages: list[dict[str, Any]] = [
|
|
128
|
+
{"role": "system", "content": system_prompt},
|
|
129
|
+
{
|
|
130
|
+
"role": "user",
|
|
131
|
+
"content": f"用户需求:{user_prompt}\n\n请选择合适的工具来满足用户需求。",
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
max_iterations: int = 20
|
|
136
|
+
iteration: int = 0
|
|
137
|
+
conversation_ended: bool = False
|
|
138
|
+
|
|
139
|
+
while iteration < max_iterations and not conversation_ended:
|
|
140
|
+
iteration += 1
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
response = await ai_client._http_client.post(
|
|
144
|
+
agent_config.api_url,
|
|
145
|
+
headers={
|
|
146
|
+
"Authorization": f"Bearer {agent_config.api_key}",
|
|
147
|
+
"Content-Type": "application/json",
|
|
148
|
+
},
|
|
149
|
+
json=ai_client._build_request_body(
|
|
150
|
+
model_config=agent_config,
|
|
151
|
+
messages=messages,
|
|
152
|
+
max_tokens=agent_config.max_tokens,
|
|
153
|
+
tools=tools if tools else None,
|
|
154
|
+
tool_choice="auto",
|
|
155
|
+
),
|
|
156
|
+
)
|
|
157
|
+
response.raise_for_status()
|
|
158
|
+
result: dict[str, Any] = response.json()
|
|
159
|
+
|
|
160
|
+
choice: dict[str, Any] = result.get("choices", [{}])[0]
|
|
161
|
+
message: dict[str, Any] = choice.get("message", {})
|
|
162
|
+
content: str = message.get("content") or ""
|
|
163
|
+
tool_calls: list[dict[str, Any]] = message.get("tool_calls", [])
|
|
164
|
+
|
|
165
|
+
if content.strip() and tool_calls:
|
|
166
|
+
content = ""
|
|
167
|
+
|
|
168
|
+
if not tool_calls:
|
|
169
|
+
return content
|
|
170
|
+
|
|
171
|
+
messages.append(
|
|
172
|
+
{"role": "assistant", "content": content, "tool_calls": tool_calls}
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# 准备并发执行工具
|
|
176
|
+
tool_tasks = []
|
|
177
|
+
tool_call_ids = []
|
|
178
|
+
|
|
179
|
+
for tool_call in tool_calls:
|
|
180
|
+
call_id: str = tool_call.get("id", "")
|
|
181
|
+
function: dict[str, Any] = tool_call.get("function", {})
|
|
182
|
+
function_name: str = function.get("name", "")
|
|
183
|
+
function_args_str: str = function.get("arguments", "{}")
|
|
184
|
+
|
|
185
|
+
logger.info(f"Agent 正在准备工具: {function_name}")
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
function_args: dict[str, Any] = json.loads(function_args_str)
|
|
189
|
+
except json.JSONDecodeError:
|
|
190
|
+
function_args = {}
|
|
191
|
+
|
|
192
|
+
tool_call_ids.append(call_id)
|
|
193
|
+
tool_tasks.append(
|
|
194
|
+
tool_registry.execute_tool(function_name, function_args, context)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# 并发执行
|
|
198
|
+
if tool_tasks:
|
|
199
|
+
logger.info(f"Agent 正在并发执行 {len(tool_tasks)} 个工具")
|
|
200
|
+
results = await asyncio.gather(*tool_tasks, return_exceptions=True)
|
|
201
|
+
|
|
202
|
+
for i, tool_result in enumerate(results):
|
|
203
|
+
call_id = tool_call_ids[i]
|
|
204
|
+
content_str: str = ""
|
|
205
|
+
if isinstance(tool_result, Exception):
|
|
206
|
+
content_str = f"错误: {str(tool_result)}"
|
|
207
|
+
else:
|
|
208
|
+
content_str = str(tool_result)
|
|
209
|
+
|
|
210
|
+
messages.append(
|
|
211
|
+
{
|
|
212
|
+
"role": "tool",
|
|
213
|
+
"tool_call_id": call_id,
|
|
214
|
+
"content": content_str,
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
logger.exception(f"Agent 执行失败: {e}")
|
|
220
|
+
return f"处理失败: {e}"
|
|
221
|
+
|
|
222
|
+
return "达到最大迭代次数"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# NagaAgent代码分析助手
|
|
2
|
+
|
|
3
|
+
## 能力
|
|
4
|
+
- **文件读取**:读取指定文件的内容
|
|
5
|
+
- **目录列表**:列出指定目录下的结构
|
|
6
|
+
- **内容搜索**:支持正则表达式的文件内容搜索
|
|
7
|
+
- **文件查找**:使用 glob 模式查找匹配文件
|
|
8
|
+
- **项目介绍**:获取 NagaAgent 项目的详细文档
|
|
9
|
+
|
|
10
|
+
## 适用场景
|
|
11
|
+
- **仅当**用户明确询问有关 "NagaAgent" 自身架构、代码或实现细节时使用
|
|
12
|
+
- 一般代码分析请使用 `file_analysis_agent`
|
|
13
|
+
|
|
14
|
+
## 参数说明
|
|
15
|
+
- `file_path`: 文件路径(相对工作目录)
|
|
16
|
+
- `dir_path`: 目录路径
|
|
17
|
+
- `pattern`: 搜索的正则模式或 Glob 模式
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
你是一个专业的代码分析助手,专门帮助用户理解和分析代码库。
|
|
2
|
+
|
|
3
|
+
你的任务是根据用户需求,选择合适的工具来完成任务:
|
|
4
|
+
|
|
5
|
+
1. **读取文件内容** → read_file
|
|
6
|
+
2. **列出目录结构** → list_directory
|
|
7
|
+
3. **搜索文件内容** → search_file_content
|
|
8
|
+
4. **按模式查找文件** → glob
|
|
9
|
+
5. **了解 NagaAgent 项目** → read_naga_intro
|
|
10
|
+
|
|
11
|
+
注意事项:
|
|
12
|
+
- 文件路径都是相对于工作目录的
|
|
13
|
+
- 搜索支持正则表达式
|
|
14
|
+
- 如果文件内容过长会被截断
|
|
15
|
+
- 保持回答简洁,聚焦于用户需要的信息
|
|
16
|
+
|
|
17
|
+
如果用户需求不明确,请先询问用户澄清问题。
|
|
18
|
+
|
|
19
|
+
如果问题涉及时间,立刻调用时间工具获取。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Code Analysis Agent Tools
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "glob",
|
|
5
|
+
"description": "查找匹配模式的文件。路径是相对于当前工作目录的。",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"pattern": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "文件模式(如 **/*.py, code/**/*.py)"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": ["pattern"]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|