@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,477 @@
1
+ """
2
+ userPresenter - 精简版,仅保留登录和AID管理相关方法
3
+ """
4
+
5
+ import json
6
+ import logging
7
+ import os
8
+ import threading
9
+ import uuid
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ from agentcp.agentcp import AgentID
14
+
15
+ from ..config import API_BASE_URL
16
+ from ..http.async_http import AsyncHttpClient
17
+ from .configPresenter import configPresenter
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ try:
22
+ from agentcp import AgentCP
23
+ except ImportError:
24
+ AgentCP = None
25
+
26
+
27
+ class userPresenter:
28
+ _lock = threading.RLock()
29
+ _user_file_path = None
30
+ agentId: AgentID = None
31
+ _agentcp_instance = None
32
+ _agentcp_lock = threading.RLock()
33
+ _aid_initializing = False
34
+ phone: str = None
35
+ gatewayInfo = None
36
+
37
+ @classmethod
38
+ def _get_agentcp_instance(cls):
39
+ """获取持久化的 AgentCP 实例"""
40
+ with cls._agentcp_lock:
41
+ if cls._agentcp_instance is None:
42
+ evol_user_dir = Path.home() / ".evol"
43
+ evol_user_dir.mkdir(exist_ok=True)
44
+ cls._agentcp_instance = AgentCP(
45
+ evol_user_dir,
46
+ seed_password="evol_user_default_password",
47
+ debug=False,
48
+ run_proxy=False
49
+ )
50
+ return cls._agentcp_instance
51
+
52
+ @classmethod
53
+ def _cleanup_aid_before_login(cls):
54
+ """登录前清理当前的AID(用于切换用户登录)"""
55
+ with cls._agentcp_lock:
56
+ cls._aid_initializing = False
57
+ if cls.agentId is not None:
58
+ current_aid = cls.agentId.id
59
+ try:
60
+ cls.agentId.offline()
61
+ logger.info(f"登录前已下线旧AID: {current_aid}")
62
+ except Exception as e:
63
+ logger.warning(f"下线旧AID失败: {e}")
64
+ cls.agentId = None
65
+
66
+ @classmethod
67
+ def _get_user_file_path(cls):
68
+ """获取用户信息文件路径"""
69
+ if cls._user_file_path is None:
70
+ user_home = Path.home()
71
+ evol_dir = user_home / ".evol"
72
+ evol_dir.mkdir(exist_ok=True)
73
+ cls._user_file_path = evol_dir / "user_info.json"
74
+ return cls._user_file_path
75
+
76
+ @classmethod
77
+ def _create_default_user_info(cls):
78
+ """创建默认用户信息"""
79
+ return {
80
+ "username": "evol同学",
81
+ "user_id": str(uuid.uuid4())
82
+ }
83
+
84
+ @classmethod
85
+ def _read_user_file(cls):
86
+ """读取用户信息文件"""
87
+ file_path = cls._get_user_file_path()
88
+ try:
89
+ if file_path.exists():
90
+ with open(file_path, 'r', encoding='utf-8') as f:
91
+ return json.load(f)
92
+ else:
93
+ default_info = cls._create_default_user_info()
94
+ cls._write_user_file(default_info)
95
+ return default_info
96
+ except (json.JSONDecodeError, IOError):
97
+ default_info = cls._create_default_user_info()
98
+ cls._write_user_file(default_info)
99
+ return default_info
100
+
101
+ @classmethod
102
+ def _write_user_file(cls, user_info):
103
+ """写入用户信息文件"""
104
+ file_path = cls._get_user_file_path()
105
+ with open(file_path, 'w', encoding='utf-8') as f:
106
+ json.dump(user_info, f, ensure_ascii=False, indent=2)
107
+
108
+ @classmethod
109
+ def get_user_info(cls):
110
+ """获取用户信息"""
111
+ try:
112
+ with cls._lock:
113
+ user_info = cls._read_user_file()
114
+ return {
115
+ "status": "success",
116
+ "user_info": user_info
117
+ }
118
+ except Exception as e:
119
+ return {
120
+ "status": "error",
121
+ "error": f"获取用户信息失败: {str(e)}"
122
+ }
123
+
124
+ @classmethod
125
+ def is_logged_in(cls):
126
+ """判断用户是否已登录"""
127
+ token = configPresenter.get_token()
128
+ return token is not None and token != ""
129
+
130
+ @classmethod
131
+ async def send_sms_code(cls, phone: str, code_type: str = "LOGIN"):
132
+ """
133
+ 发送验证码
134
+
135
+ Args:
136
+ phone: 手机号
137
+ code_type: 验证码类型 (LOGIN, REGISTER, RESET_PWD)
138
+ """
139
+ try:
140
+ url = f"{API_BASE_URL}/api/auth/sms/send"
141
+ data = {
142
+ "phone": phone,
143
+ "codeType": code_type
144
+ }
145
+ response = await AsyncHttpClient.post(url, data=data, include_token=False)
146
+
147
+ if response.get("code") == 200:
148
+ return {"status": "success", "data": response}
149
+ else:
150
+ return {
151
+ "status": "error",
152
+ "error": response.get("msg", "发送验证码失败")
153
+ }
154
+ except Exception as e:
155
+ error_msg = str(e)
156
+ if "ssl" in error_msg.lower():
157
+ return {
158
+ "status": "error",
159
+ "error": "网络连接失败:SSL证书验证错误。"
160
+ }
161
+ return {
162
+ "status": "error",
163
+ "error": f"发送验证码失败: {error_msg}"
164
+ }
165
+
166
+ @classmethod
167
+ def _get_device_id(cls) -> str:
168
+ """获取设备ID"""
169
+ import uuid as uuid_module
170
+
171
+ device_id = configPresenter.getSetting("device_id")
172
+ if device_id and not device_id.startswith("mac_"):
173
+ return device_id
174
+
175
+ device_id = f"uuid_{uuid_module.uuid4().hex}"
176
+ configPresenter.setSetting("device_id", device_id)
177
+ return device_id
178
+
179
+ @classmethod
180
+ async def sms_login(cls, phone: str, code: str):
181
+ """
182
+ 验证码登录
183
+
184
+ Args:
185
+ phone: 手机号
186
+ code: 验证码
187
+ """
188
+ try:
189
+ cls._cleanup_aid_before_login()
190
+
191
+ url = f"{API_BASE_URL}/api/auth/sms/login"
192
+ data = {
193
+ "phone": phone,
194
+ "code": code,
195
+ "source": "evol_client",
196
+ "deviceId": cls._get_device_id()
197
+ }
198
+
199
+ response = await AsyncHttpClient.post(url, data=data, include_token=False)
200
+
201
+ if response.get("code") == 200 and response.get("data"):
202
+ data_obj = response.get("data")
203
+ token = data_obj.get("token")
204
+ user_info = data_obj.get("userInfo")
205
+
206
+ if token and user_info:
207
+ configPresenter.set_token(token)
208
+
209
+ with cls._lock:
210
+ local_user_info = {
211
+ "username": user_info.get("nickName") or user_info.get("userName"),
212
+ "user_id": str(user_info.get("userId")),
213
+ "phone": user_info.get("phone"),
214
+ "avatar": user_info.get("avatar"),
215
+ }
216
+ teams = data_obj.get("teams", [])
217
+ if teams:
218
+ local_user_info["teams"] = [
219
+ {
220
+ "team_id": team.get("teamId"),
221
+ "team_name": team.get("teamName"),
222
+ "member_role": team.get("memberRole"),
223
+ }
224
+ for team in teams
225
+ ]
226
+ cls._write_user_file(local_user_info)
227
+
228
+ # AID 初始化
229
+ aid_login_result = await cls.user_agent_login()
230
+ if aid_login_result.get("status") != "success":
231
+ logger.warning(f"用户登录成功,但AID初始化失败: {aid_login_result.get('error')}")
232
+
233
+ return {"status": "success", "data": response}
234
+ except Exception as e:
235
+ return {"status": "error", "error": f"登录失败: {str(e)}"}
236
+
237
+ @classmethod
238
+ async def user_agent_login(cls):
239
+ """用户AID登录,确保AID和服务器绑定一致"""
240
+ try:
241
+ if not cls.is_logged_in():
242
+ return {
243
+ "status": "error",
244
+ "error": "用户未登录,请先登录",
245
+ "error_code": 401
246
+ }
247
+
248
+ logger.info("开始AID登录流程")
249
+
250
+ aid_result = await cls._get_user_aid_info()
251
+
252
+ if aid_result["status"] == "error":
253
+ logger.error(f"获取AID信息失败: {aid_result['error']}")
254
+ return {
255
+ "status": "error",
256
+ "error": f"AID登录失败: {aid_result['error']}"
257
+ }
258
+ elif aid_result["data"] is None:
259
+ logger.info("服务器未返回AID,创建新AID")
260
+ return await cls._create_and_sync_aid()
261
+ else:
262
+ server_aid = aid_result["data"].get("aid")
263
+ logger.info(f"服务器返回AID: {server_aid}")
264
+ return await cls._handle_existing_aid(aid_result["data"])
265
+
266
+ except Exception as e:
267
+ logger.error(f"AID登录异常: {str(e)}")
268
+ import traceback
269
+ logger.error(f"异常堆栈: {traceback.format_exc()}")
270
+ return {"status": "error", "error": f"AID登录失败: {str(e)}"}
271
+
272
+ @classmethod
273
+ async def _get_user_aid_info(cls):
274
+ """获取用户AID信息"""
275
+ try:
276
+ url = f"{API_BASE_URL}/system/user/aid"
277
+ response = await AsyncHttpClient.get(url, include_token=True)
278
+
279
+ if response.get("code") == 200:
280
+ data = response.get("data")
281
+ if data and data.get("aid"):
282
+ return {"status": "success", "data": data}
283
+ else:
284
+ return {"status": "success", "data": None}
285
+ else:
286
+ return {
287
+ "status": "error",
288
+ "error": f"获取AID信息失败: {response.get('msg', '未知错误')}"
289
+ }
290
+ except Exception as e:
291
+ return {"status": "error", "error": f"获取AID信息失败: {str(e)}"}
292
+
293
+ @classmethod
294
+ async def _get_user_aid_detail(cls):
295
+ """获取用户AID详细信息"""
296
+ try:
297
+ url = f"{API_BASE_URL}/system/user/aid/detail"
298
+ response = await AsyncHttpClient.get(url, include_token=True)
299
+
300
+ if response.get("code") == 200 and response.get("data"):
301
+ return response["data"]
302
+ else:
303
+ return None
304
+ except Exception:
305
+ return None
306
+
307
+ @classmethod
308
+ async def _create_and_sync_aid(cls):
309
+ """创建AID并同步到服务器"""
310
+ try:
311
+ import time
312
+ import random
313
+
314
+ timestamp = int(time.time())
315
+ random_num = random.randint(0, 9)
316
+ agent_name = f"evol_{timestamp}_{random_num}"
317
+
318
+ agentcp = cls._get_agentcp_instance()
319
+ cls.agentId = agentcp.create_aid("aid.pub", agent_name)
320
+
321
+ if cls.agentId is None:
322
+ return {"status": "error", "error": "创建AID失败"}
323
+
324
+ logger.info(f"创建新AID: {cls.agentId.id}")
325
+
326
+ private_key = agentcp.read_private_key(cls.agentId.id)
327
+ pem_str = agentcp.read_certificate_pem(cls.agentId.id)
328
+
329
+ sync_data = {
330
+ "aid": cls.agentId.id,
331
+ "privateKey": private_key,
332
+ "pemStr": pem_str
333
+ }
334
+
335
+ sync_result = await cls._submit_aid_info(sync_data)
336
+ if sync_result["status"] != "success":
337
+ return sync_result
338
+
339
+ logger.info(f"AID已同步到服务器: {cls.agentId.id}")
340
+
341
+ cls.agentId.online()
342
+
343
+ if cls.agentId.is_online_success:
344
+ from evol.presenter.agentIdPresenter import evol_agentId_online
345
+ evol_agentId_online(cls.agentId)
346
+
347
+ from evol.server.claude_proxy_async import set_agent_id
348
+ set_agent_id(cls.agentId)
349
+
350
+ from evol.server.openclaw_proxy import set_openclaw_agentid
351
+ set_openclaw_agentid(cls.agentId)
352
+
353
+ return {
354
+ "status": "success",
355
+ "message": "AID创建并登录成功",
356
+ "aid": cls.agentId.id
357
+ }
358
+
359
+ except Exception as e:
360
+ logger.error(f"创建AID失败: {str(e)}")
361
+ return {"status": "error", "error": f"创建AID失败: {str(e)}"}
362
+
363
+ @classmethod
364
+ async def _handle_existing_aid(cls, aid_info):
365
+ """处理已存在的AID"""
366
+ try:
367
+ aid_id = aid_info.get("aid")
368
+ if not aid_id:
369
+ return {"status": "error", "error": "AID信息无效"}
370
+
371
+ logger.info(f"处理服务器返回的AID: {aid_id}")
372
+
373
+ if cls.agentId is not None and cls.agentId.id == aid_id:
374
+ logger.info(f"当前已加载正确的AID: {aid_id}")
375
+ return {"status": "success", "message": "AID已在线", "aid": aid_id}
376
+
377
+ agentcp = cls._get_agentcp_instance()
378
+ loaded_aid = agentcp.load_aid(aid_id)
379
+
380
+ if loaded_aid is None:
381
+ logger.warning(f"本地未找到AID: {aid_id},从服务器同步")
382
+ return await cls._sync_aid_from_server(aid_id)
383
+
384
+ if loaded_aid.id != aid_id:
385
+ return {
386
+ "status": "error",
387
+ "error": f"AID不一致,本地: {loaded_aid.id}, 服务器: {aid_id}"
388
+ }
389
+
390
+ cls.agentId = loaded_aid
391
+ cls.agentId.online()
392
+
393
+ if cls.agentId.is_online_success:
394
+ from evol.presenter.agentIdPresenter import evol_agentId_online
395
+ evol_agentId_online(cls.agentId)
396
+
397
+ from evol.server.claude_proxy_async import set_agent_id
398
+ set_agent_id(cls.agentId)
399
+
400
+ from evol.server.openclaw_proxy import set_openclaw_agentid
401
+ set_openclaw_agentid(cls.agentId)
402
+
403
+ return {"status": "success", "message": "AID登录成功", "aid": aid_id}
404
+
405
+ except Exception as e:
406
+ logger.error(f"处理现有AID失败: {str(e)}")
407
+ return {"status": "error", "error": f"处理现有AID失败: {str(e)}"}
408
+
409
+ @classmethod
410
+ async def _sync_aid_from_server(cls, aid_id):
411
+ """从服务器同步AID数据到本地"""
412
+ try:
413
+ logger.info(f"从服务器同步AID: {aid_id}")
414
+
415
+ aid_detail = await cls._get_user_aid_detail()
416
+ if not aid_detail:
417
+ return {"status": "error", "error": "从服务器获取AID详细信息失败"}
418
+
419
+ if aid_detail.get("aid") != aid_id:
420
+ return {"status": "error", "error": "服务器返回的AID不一致"}
421
+
422
+ agentcp = cls._get_agentcp_instance()
423
+
424
+ try:
425
+ agentcp.get_guest_aid("aud.pub")
426
+ except Exception:
427
+ pass
428
+
429
+ agentcp.save_aid_info(
430
+ aid_id,
431
+ "evol_user_default_password",
432
+ aid_detail.get("privateKey", ""),
433
+ aid_detail.get("pemStr", "")
434
+ )
435
+
436
+ aid_instance = agentcp.load_aid(aid_id)
437
+ if aid_instance is None:
438
+ return {"status": "error", "error": "加载同步的AID失败"}
439
+
440
+ if aid_instance.id != aid_id:
441
+ return {"status": "error", "error": "加载的AID不一致"}
442
+
443
+ cls.agentId = aid_instance
444
+ aid_instance.online()
445
+
446
+ if aid_instance.is_online_success:
447
+ from evol.presenter.agentIdPresenter import evol_agentId_online
448
+ evol_agentId_online(aid_instance)
449
+
450
+ from evol.server.claude_proxy_async import set_agent_id
451
+ set_agent_id(aid_instance)
452
+
453
+ from evol.server.openclaw_proxy import set_openclaw_agentid
454
+ set_openclaw_agentid(aid_instance)
455
+
456
+ return {"status": "success", "message": "AID同步并登录成功", "aid": aid_id}
457
+
458
+ except Exception as e:
459
+ logger.error(f"同步AID失败: {str(e)}")
460
+ return {"status": "error", "error": f"同步AID失败: {str(e)}"}
461
+
462
+ @classmethod
463
+ async def _submit_aid_info(cls, aid_data):
464
+ """提交AID信息到服务器"""
465
+ try:
466
+ url = f"{API_BASE_URL}/system/user/aid"
467
+ response = await AsyncHttpClient.post(url, data=aid_data, include_token=True)
468
+
469
+ if response.get("code") == 200:
470
+ return {"status": "success", "message": "AID信息同步成功"}
471
+ else:
472
+ return {
473
+ "status": "error",
474
+ "error": f"AID信息同步失败: {response.get('msg', '未知错误')}"
475
+ }
476
+ except Exception as e:
477
+ return {"status": "error", "error": f"AID信息同步失败: {str(e)}"}
@@ -0,0 +1 @@
1
+ # -*- coding: utf-8 -*-