@agentunion/kite 1.3.2 → 1.5.0

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 (293) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/cli.js +119 -4
  3. package/core/dependency_checker.py +250 -0
  4. package/core/env_checker.py +490 -0
  5. package/dependencies_lock.json +128 -0
  6. package/extensions/agents/assistant/entry.py +111 -1
  7. package/extensions/agents/assistant/server.py +279 -215
  8. package/extensions/channels/acp_channel/entry.py +111 -1
  9. package/extensions/channels/acp_channel/module.md +23 -22
  10. package/extensions/channels/acp_channel/server.py +279 -215
  11. package/extensions/event_hub_bench/entry.py +107 -1
  12. package/extensions/services/backup/entry.py +306 -21
  13. package/extensions/services/backup/module.md +24 -22
  14. package/extensions/services/evol/auth_manager.py +443 -0
  15. package/extensions/services/evol/config.yaml +149 -0
  16. package/extensions/services/evol/config_loader.py +117 -0
  17. package/extensions/services/evol/entry.py +406 -0
  18. package/extensions/services/evol/evol_api.py +173 -0
  19. package/extensions/services/evol/evol_config.json5 +29 -0
  20. package/extensions/services/evol/migrate_tokens.py +122 -0
  21. package/extensions/services/evol/module.md +32 -0
  22. package/extensions/services/evol/pairing.py +250 -0
  23. package/extensions/services/evol/pairing_codes.jsonl +1 -0
  24. package/extensions/services/evol/relay.py +682 -0
  25. package/extensions/services/evol/relay_config.json5 +67 -0
  26. package/extensions/services/evol/routes/__init__.py +1 -0
  27. package/extensions/services/evol/routes/routes_management_ws.py +127 -0
  28. package/extensions/services/evol/routes/routes_rpc.py +89 -0
  29. package/extensions/services/evol/routes/routes_test.py +61 -0
  30. package/extensions/services/evol/server.py +875 -0
  31. package/extensions/services/evol/static/css/style.css +1200 -0
  32. package/extensions/services/evol/static/index.html +781 -0
  33. package/extensions/services/evol/static/index_evol.html +14 -0
  34. package/extensions/services/evol/static/js/app.js +6304 -0
  35. package/extensions/services/evol/static/js/auth.js +326 -0
  36. package/extensions/services/evol/static/js/dialog.js +285 -0
  37. package/extensions/services/evol/static/js/evol-app-fixed.js +50 -0
  38. package/extensions/services/evol/static/js/evol-app.js +1949 -0
  39. package/extensions/services/evol/static/js/evol-app.js.bak +1800 -0
  40. package/extensions/services/evol/static/js/kernel-client-example.js +228 -0
  41. package/extensions/services/evol/static/js/kernel-client.js +396 -0
  42. package/extensions/services/evol/static/js/main.js +141 -0
  43. package/extensions/services/evol/static/js/registry-tests.js +585 -0
  44. package/extensions/services/evol/static/js/stats.js +217 -0
  45. package/extensions/services/evol/static/js/token-manager.js +175 -0
  46. package/extensions/services/evol/static/pairing.html +248 -0
  47. package/extensions/services/evol/static/test_registry.html +262 -0
  48. package/extensions/services/evol/static/test_relay.html +462 -0
  49. package/extensions/services/evol/stats_manager.py +240 -0
  50. package/extensions/services/model_service/entry.py +167 -19
  51. package/extensions/services/model_service/module.md +21 -22
  52. package/extensions/services/proxy/.claude/settings.local.json +13 -0
  53. package/extensions/services/proxy/CHANGELOG_20260308.md +258 -0
  54. package/extensions/services/proxy/_fix_prints.py +133 -0
  55. package/extensions/services/proxy/_fix_prints2.py +87 -0
  56. package/extensions/services/proxy/agentcp/LICENCE +178 -0
  57. package/extensions/services/proxy/agentcp/README copy.md +85 -0
  58. package/extensions/services/proxy/agentcp/README.md +260 -0
  59. package/extensions/services/proxy/agentcp/__init__.py +16 -0
  60. package/extensions/services/proxy/agentcp/agent.py +4 -0
  61. package/extensions/services/proxy/agentcp/agentcp.py +2494 -0
  62. package/extensions/services/proxy/agentcp/agentprofile.json +89 -0
  63. package/extensions/services/proxy/agentcp/ap/__init__.py +16 -0
  64. package/extensions/services/proxy/agentcp/ap/ap_client.py +316 -0
  65. package/extensions/services/proxy/agentcp/assets/images/wechat_qr.png +0 -0
  66. package/extensions/services/proxy/agentcp/backup/metrics.json +31 -0
  67. package/extensions/services/proxy/agentcp/base/__init__.py +20 -0
  68. package/extensions/services/proxy/agentcp/base/auth_client.py +257 -0
  69. package/extensions/services/proxy/agentcp/base/client.py +112 -0
  70. package/extensions/services/proxy/agentcp/base/env.py +34 -0
  71. package/extensions/services/proxy/agentcp/base/html_util.py +336 -0
  72. package/extensions/services/proxy/agentcp/base/log.py +98 -0
  73. package/extensions/services/proxy/agentcp/ca/__init__.py +17 -0
  74. package/extensions/services/proxy/agentcp/ca/ca_client.py +414 -0
  75. package/extensions/services/proxy/agentcp/ca/ca_root.py +74 -0
  76. package/extensions/services/proxy/agentcp/context/__init__.py +20 -0
  77. package/extensions/services/proxy/agentcp/context/context.py +73 -0
  78. package/extensions/services/proxy/agentcp/context/exceptions.py +114 -0
  79. package/extensions/services/proxy/agentcp/create_profile.py +125 -0
  80. package/extensions/services/proxy/agentcp/create_profile_weather.py +125 -0
  81. package/extensions/services/proxy/agentcp/db/__init__.py +15 -0
  82. package/extensions/services/proxy/agentcp/db/db_mananger.py +550 -0
  83. package/extensions/services/proxy/agentcp/docs/UDP_HEARTBEAT_FIX_REPORT.md +265 -0
  84. package/extensions/services/proxy/agentcp/docs/heartbeat_issue_analysis.md +291 -0
  85. package/extensions/services/proxy/agentcp/file/__init__.py +16 -0
  86. package/extensions/services/proxy/agentcp/file/file_client.py +141 -0
  87. package/extensions/services/proxy/agentcp/file/wss_binary_message.py +137 -0
  88. package/extensions/services/proxy/agentcp/hcp.py +299 -0
  89. package/extensions/services/proxy/agentcp/heartbeat/__init__.py +16 -0
  90. package/extensions/services/proxy/agentcp/heartbeat/heartbeat_client.py +360 -0
  91. package/extensions/services/proxy/agentcp/improved_scheduler.py +498 -0
  92. package/extensions/services/proxy/agentcp/llm_agent_utils.py +249 -0
  93. package/extensions/services/proxy/agentcp/llm_server.py +172 -0
  94. package/extensions/services/proxy/agentcp/mermaid.py +210 -0
  95. package/extensions/services/proxy/agentcp/message.py +149 -0
  96. package/extensions/services/proxy/agentcp/metrics.py +256 -0
  97. package/extensions/services/proxy/agentcp/monitoring/__init__.py +20 -0
  98. package/extensions/services/proxy/agentcp/monitoring/global_monitor.py +27 -0
  99. package/extensions/services/proxy/agentcp/monitoring/metrics_store.py +325 -0
  100. package/extensions/services/proxy/agentcp/monitoring/monitoring_service.py +269 -0
  101. package/extensions/services/proxy/agentcp/monitoring/sliding_window.py +222 -0
  102. package/extensions/services/proxy/agentcp/monitoring/standalone_reader.py +224 -0
  103. package/extensions/services/proxy/agentcp/msg/__init__.py +21 -0
  104. package/extensions/services/proxy/agentcp/msg/connection_manager.py +456 -0
  105. package/extensions/services/proxy/agentcp/msg/message_client.py +2058 -0
  106. package/extensions/services/proxy/agentcp/msg/message_serialize.py +263 -0
  107. package/extensions/services/proxy/agentcp/msg/open_ai_message.py +88 -0
  108. package/extensions/services/proxy/agentcp/msg/session_manager.py +1062 -0
  109. package/extensions/services/proxy/agentcp/msg/stream_client.py +267 -0
  110. package/extensions/services/proxy/agentcp/msg/websocket_file_receiver.py +89 -0
  111. package/extensions/services/proxy/agentcp/msg/ws_logger.py +685 -0
  112. package/extensions/services/proxy/agentcp/msg/wss_binary_message.py +137 -0
  113. package/extensions/services/proxy/agentcp/requirements.txt +7 -0
  114. package/extensions/services/proxy/agentcp/samples/agent_graph/README.md +37 -0
  115. package/extensions/services/proxy/agentcp/samples/agent_graph/agentprofile.json +89 -0
  116. package/extensions/services/proxy/agentcp/samples/agent_graph/create_profile.py +138 -0
  117. package/extensions/services/proxy/agentcp/samples/agent_graph/main.py +164 -0
  118. package/extensions/services/proxy/agentcp/samples/agent_use/create_profile.py +123 -0
  119. package/extensions/services/proxy/agentcp/samples/agent_use/llm/create_profile.py +129 -0
  120. package/extensions/services/proxy/agentcp/samples/agent_use/llm/env.json +5 -0
  121. package/extensions/services/proxy/agentcp/samples/agent_use/llm/main.py +146 -0
  122. package/extensions/services/proxy/agentcp/samples/agent_use/main.py +123 -0
  123. package/extensions/services/proxy/agentcp/samples/agent_use/readme.md +379 -0
  124. package/extensions/services/proxy/agentcp/samples/agent_use/search/create_profile.py +129 -0
  125. package/extensions/services/proxy/agentcp/samples/agent_use/search/main.py +28 -0
  126. package/extensions/services/proxy/agentcp/samples/agent_use/tool/create_profile.py +129 -0
  127. package/extensions/services/proxy/agentcp/samples/agent_use/tool/main.py +20 -0
  128. package/extensions/services/proxy/agentcp/samples/ali_amap/README.md +97 -0
  129. package/extensions/services/proxy/agentcp/samples/ali_amap/amap_agent.py +88 -0
  130. package/extensions/services/proxy/agentcp/samples/ali_amap/create_profile.py +125 -0
  131. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/powershell.py +228 -0
  132. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/software.py +63 -0
  133. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/tools.py +36 -0
  134. package/extensions/services/proxy/agentcp/samples/compute_agent/browser_user.py +41 -0
  135. package/extensions/services/proxy/agentcp/samples/deepseek/README.md +79 -0
  136. package/extensions/services/proxy/agentcp/samples/deepseek/create_profile.py +126 -0
  137. package/extensions/services/proxy/agentcp/samples/deepseek/deepseek.py +42 -0
  138. package/extensions/services/proxy/agentcp/samples/dify_chat/README.md +78 -0
  139. package/extensions/services/proxy/agentcp/samples/dify_chat/create_profile.py +126 -0
  140. package/extensions/services/proxy/agentcp/samples/dify_chat/dify_chat.py +47 -0
  141. package/extensions/services/proxy/agentcp/samples/dify_workflow/README.md +78 -0
  142. package/extensions/services/proxy/agentcp/samples/dify_workflow/create_profile.py +126 -0
  143. package/extensions/services/proxy/agentcp/samples/dify_workflow/dify_workflow.py +46 -0
  144. package/extensions/services/proxy/agentcp/samples/executor/README.md +44 -0
  145. package/extensions/services/proxy/agentcp/samples/executor/agentprofile.json +89 -0
  146. package/extensions/services/proxy/agentcp/samples/executor/create_profile.py +139 -0
  147. package/extensions/services/proxy/agentcp/samples/executor/main.py +160 -0
  148. package/extensions/services/proxy/agentcp/samples/filereader/README.md +45 -0
  149. package/extensions/services/proxy/agentcp/samples/filereader/agentprofile.json +90 -0
  150. package/extensions/services/proxy/agentcp/samples/filereader/create_profile.py +137 -0
  151. package/extensions/services/proxy/agentcp/samples/filereader/main.py +253 -0
  152. package/extensions/services/proxy/agentcp/samples/filewriter/README.md +38 -0
  153. package/extensions/services/proxy/agentcp/samples/filewriter/agentprofile.json +91 -0
  154. package/extensions/services/proxy/agentcp/samples/filewriter/create_profile.py +138 -0
  155. package/extensions/services/proxy/agentcp/samples/filewriter/main.py +289 -0
  156. package/extensions/services/proxy/agentcp/samples/hcp/README.md +85 -0
  157. package/extensions/services/proxy/agentcp/samples/hcp/acp_weather_agent.zip +0 -0
  158. package/extensions/services/proxy/agentcp/samples/hcp/create_profile.py +125 -0
  159. package/extensions/services/proxy/agentcp/samples/hcp/hcp.py +237 -0
  160. package/extensions/services/proxy/agentcp/samples/helloworld/README.md +68 -0
  161. package/extensions/services/proxy/agentcp/samples/helloworld/hello_world.py +40 -0
  162. package/extensions/services/proxy/agentcp/samples/llm_agent/MEADME.md +117 -0
  163. package/extensions/services/proxy/agentcp/samples/llm_agent/create_profile.py +125 -0
  164. package/extensions/services/proxy/agentcp/samples/llm_agent/qwen_agent.py +136 -0
  165. package/extensions/services/proxy/agentcp/samples/local_llm_agent/README.md +90 -0
  166. package/extensions/services/proxy/agentcp/samples/local_llm_agent/create_profile.py +125 -0
  167. package/extensions/services/proxy/agentcp/samples/local_llm_agent/main.py +49 -0
  168. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/README.md +55 -0
  169. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/create_profile.py +125 -0
  170. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/main.py +23 -0
  171. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/README.md +103 -0
  172. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/create_profile.py +125 -0
  173. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/main.py +69 -0
  174. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/README.md +58 -0
  175. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/create_profile.py +125 -0
  176. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/main.py +25 -0
  177. package/extensions/services/proxy/agentcp/samples/qwen3/README.md +71 -0
  178. package/extensions/services/proxy/agentcp/samples/qwen3/create_profile.py +126 -0
  179. package/extensions/services/proxy/agentcp/samples/qwen3/qwen3.py +37 -0
  180. package/extensions/services/proxy/agentcp/samples/qwen3_tools/README.md +133 -0
  181. package/extensions/services/proxy/agentcp/samples/qwen3_tools/create_profile.py +126 -0
  182. package/extensions/services/proxy/agentcp/samples/qwen3_tools/qwen3_tools.py +98 -0
  183. package/extensions/services/proxy/agentcp/samples/search/create_profile_qwen.py +125 -0
  184. package/extensions/services/proxy/agentcp/samples/search/create_profile_search.py +125 -0
  185. package/extensions/services/proxy/agentcp/samples/search/qwen_agent.py +136 -0
  186. package/extensions/services/proxy/agentcp/samples/search/search_agent.py +170 -0
  187. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/README.md +89 -0
  188. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/create_profile.py +125 -0
  189. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/main.py +44 -0
  190. package/extensions/services/proxy/agentcp/utils/__init__.py +15 -0
  191. package/extensions/services/proxy/agentcp/utils/file_util.py +117 -0
  192. package/extensions/services/proxy/agentcp/utils/proxy_bypass.py +99 -0
  193. package/extensions/services/proxy/agentcp/workflow.py +203 -0
  194. package/extensions/services/proxy/console_auth.py +109 -0
  195. package/extensions/services/proxy/evol/__init__.py +1 -0
  196. package/extensions/services/proxy/evol/config.py +37 -0
  197. package/extensions/services/proxy/evol/http/__init__.py +1 -0
  198. package/extensions/services/proxy/evol/http/async_http.py +551 -0
  199. package/extensions/services/proxy/evol/log.py +28 -0
  200. package/extensions/services/proxy/evol/presenter/__init__.py +2 -0
  201. package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +1031 -0
  202. package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +106 -0
  203. package/extensions/services/proxy/evol/presenter/configPresenter.py +1281 -0
  204. package/extensions/services/proxy/evol/presenter/userPresenter.py +477 -0
  205. package/extensions/services/proxy/evol/server/__init__.py +1 -0
  206. package/extensions/services/proxy/evol/server/claude_proxy_async.py +3430 -0
  207. package/extensions/services/proxy/evol/server/openclaw_proxy.py +1861 -0
  208. package/extensions/services/proxy/evol/server/proxy_config.py +15 -0
  209. package/extensions/services/proxy/evol/server/proxy_engine.py +501 -0
  210. package/extensions/services/proxy/evol/version.py +24 -0
  211. package/extensions/services/proxy/logs/websocket.log +260 -0
  212. package/extensions/services/proxy/main.py +240 -0
  213. package/extensions/services/proxy/requirements.txt +13 -0
  214. package/extensions/services/proxy/server.py +271 -0
  215. package/extensions/services/watchdog/entry.py +215 -26
  216. package/extensions/services/watchdog/module.md +1 -0
  217. package/extensions/services/watchdog/monitor.py +178 -38
  218. package/extensions/services/web/WEBSOCKET_STATUS.md +143 -0
  219. package/extensions/services/web/config_example.py +35 -0
  220. package/extensions/services/web/config_loader.py +110 -0
  221. package/extensions/services/web/entry.py +114 -26
  222. package/extensions/services/web/module.md +35 -24
  223. package/extensions/services/web/pairing.py +250 -0
  224. package/extensions/services/web/pairing_codes.jsonl +16 -0
  225. package/extensions/services/web/relay.py +643 -0
  226. package/extensions/services/web/relay_config.json5 +67 -0
  227. package/extensions/services/web/routes/routes_management_ws.py +127 -0
  228. package/extensions/services/web/routes/routes_rpc.py +89 -0
  229. package/extensions/services/web/routes/routes_test.py +61 -0
  230. package/extensions/services/web/routes/schemas.py +0 -22
  231. package/extensions/services/web/server.py +434 -99
  232. package/extensions/services/web/static/css/style.css +67 -28
  233. package/extensions/services/web/static/index.html +234 -44
  234. package/extensions/services/web/static/js/app.js +1335 -48
  235. package/extensions/services/web/static/js/kernel-client-example.js +161 -0
  236. package/extensions/services/web/static/js/kernel-client.js +383 -0
  237. package/extensions/services/web/static/js/registry-tests.js +558 -0
  238. package/extensions/services/web/static/js/token-manager.js +175 -0
  239. package/extensions/services/web/static/pairing.html +248 -0
  240. package/extensions/services/web/static/test_registry.html +262 -0
  241. package/extensions/services/web/web_config.json5 +29 -0
  242. package/kernel/entry.py +120 -32
  243. package/kernel/event_hub.py +141 -16
  244. package/kernel/module.md +60 -33
  245. package/kernel/registry_store.py +45 -36
  246. package/kernel/rpc_router.py +152 -59
  247. package/kernel/server.py +322 -26
  248. package/kite_cli/__init__.py +3 -0
  249. package/kite_cli/__main__.py +5 -0
  250. package/kite_cli/commands/__init__.py +1 -0
  251. package/kite_cli/commands/clean.py +101 -0
  252. package/kite_cli/commands/deps_install.py +67 -0
  253. package/kite_cli/commands/doctor.py +35 -0
  254. package/kite_cli/commands/env_check.py +45 -0
  255. package/kite_cli/commands/history.py +111 -0
  256. package/kite_cli/commands/info.py +96 -0
  257. package/kite_cli/commands/install.py +313 -0
  258. package/kite_cli/commands/list.py +143 -0
  259. package/kite_cli/commands/log.py +81 -0
  260. package/kite_cli/commands/prepare.py +49 -0
  261. package/kite_cli/commands/rollback.py +88 -0
  262. package/kite_cli/commands/search.py +73 -0
  263. package/kite_cli/commands/uninstall.py +85 -0
  264. package/kite_cli/commands/update.py +118 -0
  265. package/kite_cli/commands/venv_setup.py +56 -0
  266. package/kite_cli/core/__init__.py +1 -0
  267. package/kite_cli/core/checker.py +142 -0
  268. package/kite_cli/core/dependency.py +229 -0
  269. package/kite_cli/core/downloader.py +209 -0
  270. package/kite_cli/core/install_info.py +40 -0
  271. package/kite_cli/core/tool_installer.py +397 -0
  272. package/kite_cli/core/validator.py +78 -0
  273. package/kite_cli/main.py +317 -0
  274. package/kite_cli/utils/__init__.py +1 -0
  275. package/kite_cli/utils/i18n.py +252 -0
  276. package/kite_cli/utils/interactive.py +63 -0
  277. package/kite_cli/utils/operation_log.py +77 -0
  278. package/kite_cli/utils/paths.py +34 -0
  279. package/kite_cli/utils/version.py +308 -0
  280. package/launcher/entry.py +1124 -178
  281. package/launcher/logging_setup.py +104 -0
  282. package/launcher/module.md +46 -37
  283. package/launcher/module_scanner.py +11 -1
  284. package/main.py +4 -1
  285. package/package.json +9 -1
  286. package/python_version.json +4 -0
  287. package/requirements.txt +38 -0
  288. package/scripts/env-manager.js +328 -0
  289. package/scripts/plan_manager.py +315 -0
  290. package/scripts/python-env.js +79 -0
  291. package/scripts/scan_dependencies.py +461 -0
  292. package/scripts/setup-python-env.js +191 -0
  293. package/extensions/services/web/routes/routes_modules.py +0 -249
@@ -0,0 +1,141 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 AgentUnion Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import asyncio
16
+ from numbers import Number
17
+ import time
18
+ import requests
19
+ import datetime
20
+ import requests
21
+
22
+
23
+ from cryptography import x509
24
+ from cryptography.hazmat.primitives import serialization
25
+ from cryptography.hazmat.primitives import hashes
26
+ import datetime
27
+ from cryptography.hazmat.primitives.asymmetric import ec
28
+
29
+ from agentcp.file.wss_binary_message import *
30
+ import websocket
31
+ from agentcp.base.auth_client import AuthClient
32
+ import ssl
33
+ from requests.packages.urllib3.exceptions import InsecureRequestWarning
34
+ import os
35
+
36
+ requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
37
+
38
+ class FileClient:
39
+ def __init__(self, aid_path:str,seed_password:str,agent_id: str, agent_network: str, cert: str = None, key: str = None, agent_id_ref=None):
40
+ """消息客户端类
41
+
42
+ Args:
43
+ agent_id: 代理ID
44
+ server_url: 服务器URL
45
+ """
46
+ self.agent_id = agent_id
47
+ self.agent_network = agent_network
48
+ self.server_url = "https://oss." + agent_network + "/api/oss"
49
+ self.cert = cert
50
+ self.key = key
51
+ self._agent_id_ref = agent_id_ref
52
+ self.auth_client = AuthClient(agent_id, self.server_url, aid_path, seed_password)
53
+ self.ws = None
54
+ self.uploaded_url = ""
55
+
56
+ def _get_proxies(self):
57
+ """获取代理配置(agentcp 内部本地/远程一律直连)"""
58
+ return {}
59
+
60
+ def sign_in(self):
61
+ """登录方法"""
62
+ self.auth_client.sign_in()
63
+
64
+ def sign_out(self):
65
+ """登出方法"""
66
+ self.auth_client.sign_out()
67
+ def get_signature(self):
68
+ return self.auth_client.signature
69
+
70
+ def close(self):
71
+ if self.ws is not None:
72
+ self.ws.close()
73
+
74
+
75
+ #标准的post方式上传文件,同步阻塞的方式上传文件,需要修改为异步,并处理各种可能失败的情况
76
+ def post_file(self, full_path):
77
+ try:
78
+ if self.auth_client.signature is None:
79
+ self.sign_in()
80
+ if self.auth_client.signature is None:
81
+ print("sign_out failed: signature is None")
82
+ return None
83
+ params = {
84
+ 'agent_id': self.agent_id,
85
+ 'signature': self.auth_client.signature,
86
+ 'file_name': os.path.basename(full_path)
87
+ }
88
+ hb_url = self.server_url + f"/upload_file"
89
+ with open(full_path, 'rb') as file:
90
+ files = {'file': file}
91
+ proxies = self._get_proxies()
92
+ response = requests.post(hb_url, data = params, files=files, verify=False, proxies=proxies)
93
+ if response.status_code == 200:
94
+ print('文件上传成功')
95
+ return response.json()["url"]
96
+ else:
97
+ print(f'文件上传失败,状态码: {response.status_code}')
98
+ return None
99
+ except FileNotFoundError:
100
+ print('文件未找到')
101
+ return None
102
+ except Exception as e:
103
+ print(f'发生错误: {e}')
104
+ return None
105
+
106
+ def get_uploaded_url(self):
107
+ return self.uploaded_url
108
+
109
+ #仅是测试代码,同步阻塞的方式下载文件,需要修改为异步,并处理各种可能失败的情况
110
+ def download_file(self, url, save_path):
111
+ try:
112
+ if self.auth_client.signature is None:
113
+ self.sign_in()
114
+ if self.auth_client.signature is None:
115
+ print("sign_out failed: signature is None")
116
+ return None
117
+ hb_url = url + f"?agent_id={self.agent_id}&signature={self.auth_client.signature}"
118
+ try:
119
+ # 发送 GET 请求下载文件
120
+ proxies = self._get_proxies()
121
+ response = requests.get(hb_url, verify=False, stream=True, proxies=proxies)
122
+ response.raise_for_status() # 检查请求是否成功
123
+
124
+ # 打开本地文件以写入二进制数据
125
+ with open(save_path, 'wb') as file:
126
+ # 逐块写入文件,避免一次性加载大文件到内存
127
+ for chunk in response.iter_content(chunk_size=16384):
128
+ if chunk: # 过滤掉保持活动的新块
129
+ file.write(chunk)
130
+
131
+ print(f"文件下载成功,保存路径: {save_path}")
132
+ return hb_url,save_path
133
+ except requests.RequestException as e:
134
+ print(f"下载文件时发生请求错误: {e}")
135
+ return hb_url,None
136
+ except Exception as e:
137
+ print(f"下载文件时发生未知错误: {e}")
138
+ return hb_url,None
139
+ except Exception as e:
140
+ print(f"download_file in exception: {e}")
141
+
@@ -0,0 +1,137 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 AgentUnion Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import struct
16
+ import zlib
17
+ import json
18
+ from dataclasses import dataclass
19
+
20
+ @dataclass
21
+ class WssBinaryMessage:
22
+ """
23
+ 用于存储 WSS 二进制消息中从 magic_byte1 到 payload 的各个字段的数据类。
24
+ """
25
+ magic_byte1: int
26
+ magic_byte2: int
27
+ version: int
28
+ flags: int
29
+ msg_type: int
30
+ msg_seq: int
31
+ content_type: int
32
+ compressed: int
33
+ reserved: int
34
+ crc32: int
35
+ payload_length: int
36
+ payload: bytes
37
+
38
+ def encode_wss_binary_message(json_data):
39
+ magic_byte1 = ord('M')
40
+ magic_byte2 = ord('U')
41
+ version = 0x101
42
+ flags = 0
43
+ msg_type = 1
44
+ # 假设 msg_seq 初始为 0,可根据实际情况调整
45
+ msg_seq = 0
46
+ payload = json_data.encode()
47
+ if len(payload) < 512:
48
+ content_type = 1
49
+ compressed = 0
50
+ else:
51
+ content_type = 1
52
+ compressed = 1
53
+ payload = zlib.compress(payload)
54
+ reserved = 0
55
+ crc32 = zlib.crc32(payload)
56
+ payload_length = len(payload)
57
+
58
+
59
+ header = struct.pack('>BBHIHIBBIII', magic_byte1, magic_byte2, version, flags, msg_type, msg_seq, content_type, compressed, reserved, crc32, payload_length)
60
+ #print(f"Header: {header}")
61
+ #print(f"Payload: {payload}")
62
+ return header + payload
63
+
64
+
65
+ def decode_wss_binary_message(data):
66
+ try:
67
+ magic_byte1, magic_byte2, version, flags, msg_type, msg_seq, content_type, compressed, reserved, crc32, payload_length = struct.unpack('>BBHIHIBBIII', data[:28])
68
+ if magic_byte1 != ord('M') or magic_byte2 != ord('U'):
69
+ return ""
70
+ payload = data[28:]
71
+ if len(payload) != payload_length:
72
+ return ""
73
+ if zlib.crc32(payload) != crc32:
74
+ return ""
75
+ if compressed != 0 and compressed != 1:
76
+ return ""
77
+ if compressed == 1:
78
+ payload = zlib.decompress(payload)
79
+ return payload.decode()
80
+ except (struct.error, zlib.error):
81
+ return ""
82
+ except Exception:
83
+ return ""
84
+
85
+
86
+ def encode_wss_binary_buffer(payload, msg_header: WssBinaryMessage):
87
+ magic_byte1 = ord('M')
88
+ magic_byte2 = ord('U')
89
+ version = msg_header.version
90
+ flags = msg_header.flags
91
+ msg_type = msg_header.msg_type
92
+ # 假设 msg_seq 初始为 0,可根据实际情况调整
93
+ msg_seq = msg_header.msg_seq
94
+ content_type = msg_header.content_type
95
+ compressed = msg_header.compressed
96
+ reserved = msg_header.reserved
97
+ crc32 = zlib.crc32(payload)
98
+ payload_length = len(payload)
99
+
100
+ header = struct.pack('>BBHIHIBBIII', magic_byte1, magic_byte2, version, flags, msg_type, msg_seq, content_type, compressed, reserved, crc32, payload_length)
101
+ #print(f"Header: {header}")
102
+ #print(f"Payload: {payload}")
103
+ return header + payload
104
+
105
+
106
+ def decode_wss_binary_buffer(data):
107
+ try:
108
+ magic_byte1, magic_byte2, version, flags, msg_type, msg_seq, content_type, compressed, reserved, crc32, payload_length = struct.unpack('>BBHIHIBBIII', data[:28])
109
+ if magic_byte1 != ord('M') or magic_byte2 != ord('U'):
110
+ return None
111
+ payload = data[28:]
112
+ if len(payload) != payload_length:
113
+ return None
114
+ if zlib.crc32(payload) != crc32:
115
+ return None
116
+ if compressed != 0 and compressed != 1:
117
+ return None
118
+ if compressed == 1:
119
+ payload = zlib.decompress(payload)
120
+
121
+ wss_msg = WssBinaryMessage()
122
+ wss_msg.version = version
123
+ wss_msg.flags = flags
124
+ wss_msg.msg_type = msg_type
125
+ wss_msg.msg_seq = msg_seq
126
+ wss_msg.content_type = content_type
127
+ wss_msg.compressed = compressed
128
+ wss_msg.reserved = reserved
129
+ wss_msg.crc32 = crc32
130
+ wss_msg.payload_length = len(payload)
131
+ wss_msg.payload = payload
132
+
133
+ return wss_msg
134
+ except (struct.error, zlib.error):
135
+ return None
136
+ except Exception:
137
+ return None
@@ -0,0 +1,299 @@
1
+ import json
2
+ from openai import OpenAI
3
+ from dotenv import load_dotenv
4
+ import agentcp
5
+ from pathlib import Path # 新增导入
6
+ import os
7
+ from typing import Dict, List, Literal, Optional
8
+
9
+ import traceback
10
+ # 加载 .env 文件,确保 API Key 受到保护
11
+ load_dotenv()
12
+
13
+ class MCPClient:
14
+ def __init__(self):
15
+ """初始化 MCP 客户端"""
16
+ self.openai_api_key = os.getenv("OPENAI_API_KEY") # 读取 OpenAI API Key
17
+ self.base_url = os.getenv("BASE_URL") # 读取 BASE YRL
18
+ self.model = os.getenv("MODEL") # 读取 model
19
+ if not self.openai_api_key:
20
+ raise ValueError(" × 未找到 OpenAI API Key,请在 .env 文件中设置 OPENAI_API_KEY")
21
+ self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url)
22
+ # 创建OpenAI client
23
+ self.acp = agentcp.AgentCP(".",seed_password="888777",debug=False)
24
+ self.agentid = None
25
+ self.message_store = dict()
26
+
27
+ def record_message(self, session_id: str, role: str, content: str) -> None:
28
+ """
29
+ 记录消息到对话历史
30
+
31
+ 参数:
32
+ session_id: 对话会话ID,用于区分不同对话
33
+ role: 消息角色 ('user', 'assistant', 'system')
34
+ content: 消息内容
35
+ """
36
+ if session_id not in self.message_store:
37
+ self.message_store[session_id] = []
38
+ #'assistant','user','system'
39
+ message = {"role": role, "content": content}
40
+ self.message_store[session_id].append(message)
41
+
42
+ def get_messages_for_llm(
43
+ self,
44
+ session_id: str,
45
+ max_messages: Optional[int] = None,
46
+ system_message: Optional[str] = None
47
+ ) -> List[Dict[str, str]]:
48
+ """
49
+ 构造适合大模型调用的历史消息
50
+
51
+ 参数:
52
+ session_id: 对话会话ID
53
+ max_messages: 最大返回消息数量(从最新开始计数)
54
+ system_message: 可选系统消息,会放在消息列表开头
55
+
56
+ 返回:
57
+ 格式化后的消息列表,可直接用于大模型API调用
58
+ """
59
+ if session_id not in self.message_store:
60
+ return [{"role": "system", "content": system_message}] if system_message else []
61
+
62
+ messages = self.message_store[session_id].copy()
63
+
64
+ # 限制消息数量
65
+ if max_messages is not None and max_messages > 0:
66
+ messages = messages[-max_messages:]
67
+
68
+ # 添加系统消息(如果提供)
69
+ if system_message:
70
+ # 确保系统消息在最前面
71
+ if messages and messages[0]["role"] == "system":
72
+ messages[0]["content"] = system_message # 更新已有系统消息
73
+ else:
74
+ messages.insert(0, {"role": "system", "content": system_message})
75
+
76
+ return messages
77
+
78
+ def clear_messages(self, session_id: str) -> None:
79
+ """清除指定会话的消息历史"""
80
+ if session_id in self.message_store:
81
+ del self.message_store[session_id]
82
+
83
+ def get_last_message(self, session_id: str) -> Optional[Dict[str, str]]:
84
+ """获取指定会话的最后一条消息"""
85
+ if session_id in self.message_store and self.message_store[session_id]:
86
+ return self.message_store[session_id][-1]
87
+ return None
88
+
89
+ async def process_query(self, query: str,session_id: str,send_aid: str,messages:list = []):
90
+ print(f"\n[Processing query: {query}]\n")
91
+ from datetime import datetime
92
+ now = datetime.now()
93
+ rolesetting = f"""
94
+ 您是一个专业的天气查询助手,能够根据用户提供的地理位置或城市名称,快速准确地查询当前天气状况、未来几天的天气预报以及相关的天气建议。请遵循以下规则:
95
+ 1. **意图判断**:
96
+ - 判断是否询问天气有关内容
97
+ --如果不是就简单回复用户的问题(20字以内),并引导用户问询天气有关的问题
98
+ --如果是天气有关的问题:
99
+ --- 如果用户未明确指定位置,请主动询问
100
+ --- 如果用户未明确指定时间,请主动询问,但是如果之前已经问过位置信息,那么时间默认为是今天
101
+ --- 如果用户未明确说明他的年龄,请主动询问
102
+ --- 如果询问后仍然缺失,就再尝试一次
103
+ 2. **查询位置范围**:
104
+ - 支持地球上的所有城市,只要是个地方就行
105
+ - 如果用户未明确指定地点,先去会话历史中查看用户是否有提到过:
106
+ -- 如果没有,就请主动询问
107
+ -- 如果有,就以最后提到的位置来回答
108
+ 3. **查询时间范围**:
109
+ - 任何绝对时间,如3月15日,2024年5月18日
110
+ - 任何相对时间,如三年前,五天前,一周后,明天,后天,大后天,前天,昨天,今天上午
111
+ - 任何年号记年的时间,如万历十五年三月十八日
112
+ - 如果用户未明确指定时间,先去会话历史中查看用户是否有提到过时间:
113
+ -- 如果没有,就主动询问
114
+ -- 如果有提到,就已最后提到的时间来回答
115
+ 4. **查询内容**:
116
+ - 当前天气:温度、湿度、风速、天气状况(晴、雨、雪等)。
117
+ - 未来天气预报:未来 3 天的天气趋势。
118
+ - 过去的天气:猜测的天气情况
119
+ - 天气建议:根据天气状况提供穿衣、出行等建议。
120
+ 你如果不清楚,可以随意编写
121
+
122
+ 例如:
123
+ - 上海今天晴,气温 15°C,湿度 45%,风速 10 km/h。建议穿薄外套。
124
+ - 南京未来三天天气预报如下:
125
+ 明天:多云,气温 18°C - 22°C。
126
+ 后天:小雨,气温 16°C - 20°C。
127
+
128
+ 5. **交互方式**:
129
+ - 使用简洁明了的语言回复用户。
130
+ - 如果用户提供的地点不明确或无法查询,请友好提示并建议重新输入。
131
+
132
+ 6. **示例对话**:
133
+ - 用户:今天北京的天气怎么样?
134
+ Agent:北京今天晴,气温 15°C,湿度 45%,风速 10 km/h。建议穿薄外套。
135
+ - 用户:未来三天上海的天气预报?
136
+ Agent:上海未来三天天气预报如下:
137
+ 明天:多云,气温 18°C - 22°C。
138
+ 后天:小雨,气温 16°C - 20°C。
139
+ 第三天:阴,气温 17°C - 21°C。
140
+
141
+ 7. **错误处理**:
142
+ - 如果查询失败,请提示用户检查输入或稍后重试。
143
+ - 如果遇到技术问题,请告知用户并建议联系技术支持。
144
+ 8. **当前的系统时间**:
145
+ - {now.strftime("%Y-%m-%d %H:%M:%S")}
146
+ 9. **如果用户的问题与天气无关,回答字数不要超过20字**
147
+ 10. **必要信息**
148
+ - 性别
149
+ - 年龄
150
+ - 位置
151
+ - 时间
152
+ 11. **其他的工具**
153
+ - 如果问题需要的工具无法解决,你可以@其他后备的工具来回答这个问题,后备工具包括:
154
+ -- lunzi.aid.pub
155
+ -- lwj.aid.pub
156
+ -- ll.aid.pub
157
+ 请始终保持专业、友好和高效的服务态度!
158
+ """
159
+ if messages is None or len(messages) == 0:
160
+ self.record_message(session_id,'user',query)
161
+ messages = self.get_messages_for_llm(session_id,20,rolesetting)
162
+
163
+ tools = [{
164
+ "type": "function",
165
+ "function": {
166
+ "name": "user_answer",
167
+ "description": "当用户问题缺少必要信息时,调用此方法,返回为用户补全的必要信息",
168
+ "parameters": {
169
+ "type": "object",
170
+ "properties": {
171
+ "question": {
172
+ "type": "string",
173
+ "description": "为询问用户缺少的必要信息的问题"
174
+ },
175
+ "位置": {
176
+ "type": "string",
177
+ "description": "上下文中已经知道的位置信息,还不知道就是空字符串"
178
+ },
179
+ "时间": {
180
+ "type": "string",
181
+ "description": "上下文中已经知道的时间信息,还不知道就是空字符串"
182
+ }
183
+ },
184
+ "required": ["question"]
185
+ }
186
+ }
187
+ }]
188
+ response = self.client.chat.completions.create(
189
+ model=self.model,
190
+ messages=messages,
191
+ tools = tools
192
+ )
193
+ # 处理返回的内容
194
+ content = response.choices[0]
195
+ if content.finish_reason == "tool_calls":
196
+ # 如何是需要使用工具,就解析工具
197
+ tool_call = content.message.tool_calls[0]
198
+ tool_name = tool_call.function.name
199
+ tool_args = json.loads(tool_call.function.arguments)
200
+ # 执行工具
201
+ print(f"\n[Calling tool {tool_name} with args {tool_args}]\n")
202
+ #将模型返回的调用哪个工具数据和工具执行完成后的数据都存入messages中
203
+ async def sync_wait_user_answer(answer_message):
204
+ self.agentid.remove_message_handler(sync_wait_user_answer,session_id)
205
+ llm_content = self.agentid.get_content_from_message(answer_message)
206
+ #print(f"收到消息数据: {llm_content}")
207
+ messages.append(content.message.model_dump())
208
+ messages.append({
209
+ "role": "tool",
210
+ "content": llm_content,
211
+ "tool_call_id": tool_call.id,
212
+ })
213
+ await self.process_query("",session_id,send_aid,messages)
214
+ return True
215
+ to_aid_list = [send_aid]
216
+ self.agentid.add_message_handler(sync_wait_user_answer,session_id)
217
+ self.agentid.send_message_content(session_id,to_aid_list,f"[from FC]{tool_args['question']}")
218
+ self.record_message(session_id, 'assistant', f"[from FC]{tool_args['question']}")
219
+ print(f"[from FC]{tool_args['question']}")
220
+ return
221
+ to_aid_list = [send_aid]
222
+ self.agentid.send_message_content(session_id,to_aid_list,f"[from LLM answer]{content.message.content}")
223
+ self.record_message(session_id, 'assistant',f"[from LLM answer]{content.message.content}")
224
+ print(f"[from LLM answer]{content.message.content}")
225
+ return
226
+
227
+ def main():
228
+ client = MCPClient()
229
+ client.agentid = client.acp.load_aid("weather.agentunion.cn")
230
+ @client.agentid.message_handler()
231
+ async def async_message_handler(message_data):
232
+ #print(f"收到消息数据: {message_data}")
233
+ try:
234
+ session_id = client.agentid.get_session_id_from_message(message_data)
235
+ llm_content_str = client.agentid.get_content_from_message(message_data)
236
+ send_aid_str = client.agentid.get_sender_from_message(message_data)
237
+ receive_aid_str = client.agentid.get_receiver_from_message(message_data)
238
+ if client.agentid.id not in receive_aid_str:
239
+ #不是发给我的消息,不处理
240
+ return
241
+ await client.process_query(llm_content_str, session_id, send_aid_str)
242
+ except Exception as e:
243
+ print(f"处理消息时发生错误: {e}\n完整堆栈跟踪:\n{traceback.format_exc()}")
244
+ try:
245
+ client.agentid.online()
246
+ print("欢迎使用HCP聊天机器人 AGENT 客户端!")
247
+ client.acp.serve_forever()
248
+ except Exception as e:
249
+ print(f"\n⚠️ 发生错误: {traceback.format_exc()}") # 添加堆栈信息打印
250
+
251
+ if __name__ == "__main__":
252
+ main()
253
+ fomr_block = {
254
+ type:"form",
255
+ "content":[
256
+ {
257
+ "form_type":"input",
258
+ "id":"",
259
+ "description":"请选择你喜欢的手机",
260
+ "params":""
261
+ },
262
+ {
263
+ "form_type":"single_select",
264
+ "description":"请选择你喜欢的手机",
265
+ "id":"",
266
+ "params":[
267
+ {
268
+ "id":"1",
269
+ "type":"text",
270
+ "content":"window 64g",
271
+ "url":""
272
+ },
273
+ {
274
+ "id":"2",
275
+ "type":"text",
276
+ "content":"window 512g",
277
+ "url":""
278
+ }
279
+ ]
280
+ },
281
+ {
282
+ "form_type":"multiple_select",
283
+ "description":"请选择你喜欢的手机",
284
+ "id":"",
285
+ "params":[
286
+ {
287
+ "id":"1",
288
+ "type":"text",
289
+ "content":"window 64g"
290
+ },
291
+ {
292
+ "id":"2",
293
+ "type":"text",
294
+ "content":"window 512g"
295
+ }
296
+ ]
297
+ }
298
+ ]
299
+ }
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 AgentUnion Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ from . import heartbeat_client