@agentunion/kite 1.4.0 → 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 (235) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/cli.js +44 -5
  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/server.py +33 -17
  7. package/extensions/channels/acp_channel/server.py +33 -17
  8. package/extensions/services/backup/entry.py +23 -16
  9. package/extensions/services/evol/auth_manager.py +443 -0
  10. package/extensions/services/evol/config.yaml +149 -0
  11. package/extensions/services/evol/config_loader.py +117 -0
  12. package/extensions/services/evol/entry.py +406 -0
  13. package/extensions/services/evol/evol_api.py +173 -0
  14. package/extensions/services/evol/evol_config.json5 +29 -0
  15. package/extensions/services/evol/migrate_tokens.py +122 -0
  16. package/extensions/services/evol/module.md +32 -0
  17. package/extensions/services/evol/pairing.py +250 -0
  18. package/extensions/services/evol/pairing_codes.jsonl +1 -0
  19. package/extensions/services/evol/relay.py +682 -0
  20. package/extensions/services/evol/relay_config.json5 +67 -0
  21. package/extensions/services/evol/routes/__init__.py +1 -0
  22. package/extensions/services/evol/routes/routes_management_ws.py +127 -0
  23. package/extensions/services/evol/routes/routes_rpc.py +89 -0
  24. package/extensions/services/evol/routes/routes_test.py +61 -0
  25. package/extensions/services/evol/server.py +875 -0
  26. package/extensions/services/evol/static/css/style.css +1200 -0
  27. package/extensions/services/evol/static/index.html +781 -0
  28. package/extensions/services/evol/static/index_evol.html +14 -0
  29. package/extensions/services/evol/static/js/app.js +6304 -0
  30. package/extensions/services/evol/static/js/auth.js +326 -0
  31. package/extensions/services/evol/static/js/dialog.js +285 -0
  32. package/extensions/services/evol/static/js/evol-app-fixed.js +50 -0
  33. package/extensions/services/evol/static/js/evol-app.js +1949 -0
  34. package/extensions/services/evol/static/js/evol-app.js.bak +1800 -0
  35. package/extensions/services/evol/static/js/kernel-client-example.js +228 -0
  36. package/extensions/services/evol/static/js/kernel-client.js +396 -0
  37. package/extensions/services/evol/static/js/main.js +141 -0
  38. package/extensions/services/evol/static/js/registry-tests.js +585 -0
  39. package/extensions/services/evol/static/js/stats.js +217 -0
  40. package/extensions/services/evol/static/js/token-manager.js +175 -0
  41. package/extensions/services/evol/static/pairing.html +248 -0
  42. package/extensions/services/evol/static/test_registry.html +262 -0
  43. package/extensions/services/evol/static/test_relay.html +462 -0
  44. package/extensions/services/evol/stats_manager.py +240 -0
  45. package/extensions/services/model_service/entry.py +23 -1
  46. package/extensions/services/proxy/.claude/settings.local.json +13 -0
  47. package/extensions/services/proxy/CHANGELOG_20260308.md +258 -0
  48. package/extensions/services/proxy/_fix_prints.py +133 -0
  49. package/extensions/services/proxy/_fix_prints2.py +87 -0
  50. package/extensions/services/proxy/agentcp/LICENCE +178 -0
  51. package/extensions/services/proxy/agentcp/README copy.md +85 -0
  52. package/extensions/services/proxy/agentcp/README.md +260 -0
  53. package/extensions/services/proxy/agentcp/__init__.py +16 -0
  54. package/extensions/services/proxy/agentcp/agent.py +4 -0
  55. package/extensions/services/proxy/agentcp/agentcp.py +2494 -0
  56. package/extensions/services/proxy/agentcp/agentprofile.json +89 -0
  57. package/extensions/services/proxy/agentcp/ap/__init__.py +16 -0
  58. package/extensions/services/proxy/agentcp/ap/ap_client.py +316 -0
  59. package/extensions/services/proxy/agentcp/assets/images/wechat_qr.png +0 -0
  60. package/extensions/services/proxy/agentcp/backup/metrics.json +31 -0
  61. package/extensions/services/proxy/agentcp/base/__init__.py +20 -0
  62. package/extensions/services/proxy/agentcp/base/auth_client.py +257 -0
  63. package/extensions/services/proxy/agentcp/base/client.py +112 -0
  64. package/extensions/services/proxy/agentcp/base/env.py +34 -0
  65. package/extensions/services/proxy/agentcp/base/html_util.py +336 -0
  66. package/extensions/services/proxy/agentcp/base/log.py +98 -0
  67. package/extensions/services/proxy/agentcp/ca/__init__.py +17 -0
  68. package/extensions/services/proxy/agentcp/ca/ca_client.py +414 -0
  69. package/extensions/services/proxy/agentcp/ca/ca_root.py +74 -0
  70. package/extensions/services/proxy/agentcp/context/__init__.py +20 -0
  71. package/extensions/services/proxy/agentcp/context/context.py +73 -0
  72. package/extensions/services/proxy/agentcp/context/exceptions.py +114 -0
  73. package/extensions/services/proxy/agentcp/create_profile.py +125 -0
  74. package/extensions/services/proxy/agentcp/create_profile_weather.py +125 -0
  75. package/extensions/services/proxy/agentcp/db/__init__.py +15 -0
  76. package/extensions/services/proxy/agentcp/db/db_mananger.py +550 -0
  77. package/extensions/services/proxy/agentcp/docs/UDP_HEARTBEAT_FIX_REPORT.md +265 -0
  78. package/extensions/services/proxy/agentcp/docs/heartbeat_issue_analysis.md +291 -0
  79. package/extensions/services/proxy/agentcp/file/__init__.py +16 -0
  80. package/extensions/services/proxy/agentcp/file/file_client.py +141 -0
  81. package/extensions/services/proxy/agentcp/file/wss_binary_message.py +137 -0
  82. package/extensions/services/proxy/agentcp/hcp.py +299 -0
  83. package/extensions/services/proxy/agentcp/heartbeat/__init__.py +16 -0
  84. package/extensions/services/proxy/agentcp/heartbeat/heartbeat_client.py +360 -0
  85. package/extensions/services/proxy/agentcp/improved_scheduler.py +498 -0
  86. package/extensions/services/proxy/agentcp/llm_agent_utils.py +249 -0
  87. package/extensions/services/proxy/agentcp/llm_server.py +172 -0
  88. package/extensions/services/proxy/agentcp/mermaid.py +210 -0
  89. package/extensions/services/proxy/agentcp/message.py +149 -0
  90. package/extensions/services/proxy/agentcp/metrics.py +256 -0
  91. package/extensions/services/proxy/agentcp/monitoring/__init__.py +20 -0
  92. package/extensions/services/proxy/agentcp/monitoring/global_monitor.py +27 -0
  93. package/extensions/services/proxy/agentcp/monitoring/metrics_store.py +325 -0
  94. package/extensions/services/proxy/agentcp/monitoring/monitoring_service.py +269 -0
  95. package/extensions/services/proxy/agentcp/monitoring/sliding_window.py +222 -0
  96. package/extensions/services/proxy/agentcp/monitoring/standalone_reader.py +224 -0
  97. package/extensions/services/proxy/agentcp/msg/__init__.py +21 -0
  98. package/extensions/services/proxy/agentcp/msg/connection_manager.py +456 -0
  99. package/extensions/services/proxy/agentcp/msg/message_client.py +2058 -0
  100. package/extensions/services/proxy/agentcp/msg/message_serialize.py +263 -0
  101. package/extensions/services/proxy/agentcp/msg/open_ai_message.py +88 -0
  102. package/extensions/services/proxy/agentcp/msg/session_manager.py +1062 -0
  103. package/extensions/services/proxy/agentcp/msg/stream_client.py +267 -0
  104. package/extensions/services/proxy/agentcp/msg/websocket_file_receiver.py +89 -0
  105. package/extensions/services/proxy/agentcp/msg/ws_logger.py +685 -0
  106. package/extensions/services/proxy/agentcp/msg/wss_binary_message.py +137 -0
  107. package/extensions/services/proxy/agentcp/requirements.txt +7 -0
  108. package/extensions/services/proxy/agentcp/samples/agent_graph/README.md +37 -0
  109. package/extensions/services/proxy/agentcp/samples/agent_graph/agentprofile.json +89 -0
  110. package/extensions/services/proxy/agentcp/samples/agent_graph/create_profile.py +138 -0
  111. package/extensions/services/proxy/agentcp/samples/agent_graph/main.py +164 -0
  112. package/extensions/services/proxy/agentcp/samples/agent_use/create_profile.py +123 -0
  113. package/extensions/services/proxy/agentcp/samples/agent_use/llm/create_profile.py +129 -0
  114. package/extensions/services/proxy/agentcp/samples/agent_use/llm/env.json +5 -0
  115. package/extensions/services/proxy/agentcp/samples/agent_use/llm/main.py +146 -0
  116. package/extensions/services/proxy/agentcp/samples/agent_use/main.py +123 -0
  117. package/extensions/services/proxy/agentcp/samples/agent_use/readme.md +379 -0
  118. package/extensions/services/proxy/agentcp/samples/agent_use/search/create_profile.py +129 -0
  119. package/extensions/services/proxy/agentcp/samples/agent_use/search/main.py +28 -0
  120. package/extensions/services/proxy/agentcp/samples/agent_use/tool/create_profile.py +129 -0
  121. package/extensions/services/proxy/agentcp/samples/agent_use/tool/main.py +20 -0
  122. package/extensions/services/proxy/agentcp/samples/ali_amap/README.md +97 -0
  123. package/extensions/services/proxy/agentcp/samples/ali_amap/amap_agent.py +88 -0
  124. package/extensions/services/proxy/agentcp/samples/ali_amap/create_profile.py +125 -0
  125. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/powershell.py +228 -0
  126. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/software.py +63 -0
  127. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/tools.py +36 -0
  128. package/extensions/services/proxy/agentcp/samples/compute_agent/browser_user.py +41 -0
  129. package/extensions/services/proxy/agentcp/samples/deepseek/README.md +79 -0
  130. package/extensions/services/proxy/agentcp/samples/deepseek/create_profile.py +126 -0
  131. package/extensions/services/proxy/agentcp/samples/deepseek/deepseek.py +42 -0
  132. package/extensions/services/proxy/agentcp/samples/dify_chat/README.md +78 -0
  133. package/extensions/services/proxy/agentcp/samples/dify_chat/create_profile.py +126 -0
  134. package/extensions/services/proxy/agentcp/samples/dify_chat/dify_chat.py +47 -0
  135. package/extensions/services/proxy/agentcp/samples/dify_workflow/README.md +78 -0
  136. package/extensions/services/proxy/agentcp/samples/dify_workflow/create_profile.py +126 -0
  137. package/extensions/services/proxy/agentcp/samples/dify_workflow/dify_workflow.py +46 -0
  138. package/extensions/services/proxy/agentcp/samples/executor/README.md +44 -0
  139. package/extensions/services/proxy/agentcp/samples/executor/agentprofile.json +89 -0
  140. package/extensions/services/proxy/agentcp/samples/executor/create_profile.py +139 -0
  141. package/extensions/services/proxy/agentcp/samples/executor/main.py +160 -0
  142. package/extensions/services/proxy/agentcp/samples/filereader/README.md +45 -0
  143. package/extensions/services/proxy/agentcp/samples/filereader/agentprofile.json +90 -0
  144. package/extensions/services/proxy/agentcp/samples/filereader/create_profile.py +137 -0
  145. package/extensions/services/proxy/agentcp/samples/filereader/main.py +253 -0
  146. package/extensions/services/proxy/agentcp/samples/filewriter/README.md +38 -0
  147. package/extensions/services/proxy/agentcp/samples/filewriter/agentprofile.json +91 -0
  148. package/extensions/services/proxy/agentcp/samples/filewriter/create_profile.py +138 -0
  149. package/extensions/services/proxy/agentcp/samples/filewriter/main.py +289 -0
  150. package/extensions/services/proxy/agentcp/samples/hcp/README.md +85 -0
  151. package/extensions/services/proxy/agentcp/samples/hcp/acp_weather_agent.zip +0 -0
  152. package/extensions/services/proxy/agentcp/samples/hcp/create_profile.py +125 -0
  153. package/extensions/services/proxy/agentcp/samples/hcp/hcp.py +237 -0
  154. package/extensions/services/proxy/agentcp/samples/helloworld/README.md +68 -0
  155. package/extensions/services/proxy/agentcp/samples/helloworld/hello_world.py +40 -0
  156. package/extensions/services/proxy/agentcp/samples/llm_agent/MEADME.md +117 -0
  157. package/extensions/services/proxy/agentcp/samples/llm_agent/create_profile.py +125 -0
  158. package/extensions/services/proxy/agentcp/samples/llm_agent/qwen_agent.py +136 -0
  159. package/extensions/services/proxy/agentcp/samples/local_llm_agent/README.md +90 -0
  160. package/extensions/services/proxy/agentcp/samples/local_llm_agent/create_profile.py +125 -0
  161. package/extensions/services/proxy/agentcp/samples/local_llm_agent/main.py +49 -0
  162. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/README.md +55 -0
  163. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/create_profile.py +125 -0
  164. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/main.py +23 -0
  165. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/README.md +103 -0
  166. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/create_profile.py +125 -0
  167. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/main.py +69 -0
  168. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/README.md +58 -0
  169. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/create_profile.py +125 -0
  170. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/main.py +25 -0
  171. package/extensions/services/proxy/agentcp/samples/qwen3/README.md +71 -0
  172. package/extensions/services/proxy/agentcp/samples/qwen3/create_profile.py +126 -0
  173. package/extensions/services/proxy/agentcp/samples/qwen3/qwen3.py +37 -0
  174. package/extensions/services/proxy/agentcp/samples/qwen3_tools/README.md +133 -0
  175. package/extensions/services/proxy/agentcp/samples/qwen3_tools/create_profile.py +126 -0
  176. package/extensions/services/proxy/agentcp/samples/qwen3_tools/qwen3_tools.py +98 -0
  177. package/extensions/services/proxy/agentcp/samples/search/create_profile_qwen.py +125 -0
  178. package/extensions/services/proxy/agentcp/samples/search/create_profile_search.py +125 -0
  179. package/extensions/services/proxy/agentcp/samples/search/qwen_agent.py +136 -0
  180. package/extensions/services/proxy/agentcp/samples/search/search_agent.py +170 -0
  181. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/README.md +89 -0
  182. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/create_profile.py +125 -0
  183. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/main.py +44 -0
  184. package/extensions/services/proxy/agentcp/utils/__init__.py +15 -0
  185. package/extensions/services/proxy/agentcp/utils/file_util.py +117 -0
  186. package/extensions/services/proxy/agentcp/utils/proxy_bypass.py +99 -0
  187. package/extensions/services/proxy/agentcp/workflow.py +203 -0
  188. package/extensions/services/proxy/console_auth.py +109 -0
  189. package/extensions/services/proxy/evol/__init__.py +1 -0
  190. package/extensions/services/proxy/evol/config.py +37 -0
  191. package/extensions/services/proxy/evol/http/__init__.py +1 -0
  192. package/extensions/services/proxy/evol/http/async_http.py +551 -0
  193. package/extensions/services/proxy/evol/log.py +28 -0
  194. package/extensions/services/proxy/evol/presenter/__init__.py +2 -0
  195. package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +1031 -0
  196. package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +106 -0
  197. package/extensions/services/proxy/evol/presenter/configPresenter.py +1281 -0
  198. package/extensions/services/proxy/evol/presenter/userPresenter.py +477 -0
  199. package/extensions/services/proxy/evol/server/__init__.py +1 -0
  200. package/extensions/services/proxy/evol/server/claude_proxy_async.py +3430 -0
  201. package/extensions/services/proxy/evol/server/openclaw_proxy.py +1861 -0
  202. package/extensions/services/proxy/evol/server/proxy_config.py +15 -0
  203. package/extensions/services/proxy/evol/server/proxy_engine.py +501 -0
  204. package/extensions/services/proxy/evol/version.py +24 -0
  205. package/extensions/services/proxy/logs/websocket.log +260 -0
  206. package/extensions/services/proxy/main.py +240 -0
  207. package/extensions/services/proxy/requirements.txt +13 -0
  208. package/extensions/services/proxy/server.py +271 -0
  209. package/extensions/services/watchdog/entry.py +42 -16
  210. package/extensions/services/watchdog/module.md +1 -0
  211. package/extensions/services/watchdog/monitor.py +34 -4
  212. package/extensions/services/web/module.md +1 -1
  213. package/extensions/services/web/server.py +30 -18
  214. package/extensions/services/web/static/js/token-manager.js +10 -10
  215. package/kernel/entry.py +1 -1
  216. package/kernel/module.md +25 -1
  217. package/kernel/registry_store.py +2 -26
  218. package/kernel/rpc_router.py +36 -10
  219. package/kernel/server.py +106 -17
  220. package/kite_cli/commands/deps_install.py +67 -0
  221. package/kite_cli/commands/env_check.py +45 -0
  222. package/kite_cli/commands/prepare.py +49 -0
  223. package/kite_cli/commands/venv_setup.py +56 -0
  224. package/kite_cli/main.py +29 -1
  225. package/launcher/entry.py +306 -21
  226. package/launcher/module.md +9 -0
  227. package/launcher/module_scanner.py +11 -1
  228. package/main.py +4 -1
  229. package/package.json +8 -1
  230. package/python_version.json +4 -0
  231. package/requirements.txt +38 -0
  232. package/scripts/env-manager.js +328 -0
  233. package/scripts/python-env.js +79 -0
  234. package/scripts/scan_dependencies.py +461 -0
  235. package/scripts/setup-python-env.js +191 -0
@@ -0,0 +1,326 @@
1
+ // Auth functions
2
+
3
+ let countdown = 0;
4
+ let countdownTimer = null;
5
+
6
+ async function sendSMS() {
7
+ const phone = document.getElementById('phone').value.trim();
8
+ const errorMsg = document.getElementById('error-msg');
9
+ const sendBtn = document.getElementById('send-code-btn');
10
+
11
+ if (!phone || !/^1[3-9]\d{9}$/.test(phone)) {
12
+ errorMsg.textContent = '请输入正确的手机号';
13
+ return;
14
+ }
15
+
16
+ errorMsg.textContent = '';
17
+ sendBtn.disabled = true;
18
+
19
+ try {
20
+ const response = await fetch('/api/send_sms', {
21
+ method: 'POST',
22
+ headers: { 'Content-Type': 'application/json' },
23
+ body: JSON.stringify({ phone })
24
+ });
25
+
26
+ const result = await response.json();
27
+
28
+ if (result.success) {
29
+ startCountdown();
30
+ } else {
31
+ errorMsg.textContent = result.msg || '发送失败';
32
+ sendBtn.disabled = false;
33
+ }
34
+ } catch (error) {
35
+ errorMsg.textContent = '网络错误';
36
+ sendBtn.disabled = false;
37
+ }
38
+ }
39
+
40
+ function startCountdown() {
41
+ countdown = 60;
42
+ const sendBtn = document.getElementById('send-code-btn');
43
+
44
+ countdownTimer = setInterval(() => {
45
+ countdown--;
46
+ sendBtn.textContent = `${countdown}秒后重试`;
47
+
48
+ if (countdown <= 0) {
49
+ clearInterval(countdownTimer);
50
+ sendBtn.textContent = '发送验证码';
51
+ sendBtn.disabled = false;
52
+ }
53
+ }, 1000);
54
+ }
55
+
56
+ async function verifyLogin() {
57
+ const phone = document.getElementById('phone').value.trim();
58
+ const code = document.getElementById('code').value.trim();
59
+ const errorMsg = document.getElementById('error-msg');
60
+ const loginBtn = document.getElementById('login-btn');
61
+
62
+ if (!phone || !code) {
63
+ errorMsg.textContent = '请输入手机号和验证码';
64
+ return;
65
+ }
66
+
67
+ if (!/^\d{6}$/.test(code)) {
68
+ errorMsg.textContent = '验证码格式不正确';
69
+ return;
70
+ }
71
+
72
+ errorMsg.textContent = '';
73
+ loginBtn.disabled = true;
74
+ loginBtn.textContent = '登录中...';
75
+
76
+ try {
77
+ const deviceInfo = {
78
+ deviceId: getDeviceId(),
79
+ deviceName: getDeviceName()
80
+ };
81
+
82
+ const response = await fetch('/api/verify_sms', {
83
+ method: 'POST',
84
+ headers: { 'Content-Type': 'application/json' },
85
+ body: JSON.stringify({ phone, code, deviceInfo })
86
+ });
87
+
88
+ const result = await response.json();
89
+
90
+ if (result.success) {
91
+ localStorage.setItem('evol_kite_token', result.kiteToken);
92
+ showUserInfo(result.userInfo);
93
+ } else {
94
+ errorMsg.textContent = result.msg || '登录失败';
95
+ loginBtn.disabled = false;
96
+ loginBtn.textContent = '登录';
97
+ }
98
+ } catch (error) {
99
+ errorMsg.textContent = '网络错误';
100
+ loginBtn.disabled = false;
101
+ loginBtn.textContent = '登录';
102
+ }
103
+ }
104
+
105
+ async function loadUserInfo() {
106
+ const kiteToken = localStorage.getItem('evol_kite_token');
107
+ if (!kiteToken) {
108
+ return;
109
+ }
110
+
111
+ try {
112
+ const response = await fetch('/api/get_user_info', {
113
+ method: 'POST',
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: JSON.stringify({ kiteToken })
116
+ });
117
+
118
+ const result = await response.json();
119
+
120
+ if (result.success) {
121
+ showUserInfo(result.data);
122
+ } else if (result.code === 'INVALID_TOKEN') {
123
+ // Token 失效,但不自动清除,让用户看到提示
124
+ console.warn('Evol token invalid, but kiteToken still valid');
125
+ // 抛出错误让调用方处理
126
+ throw new Error('EVOL_TOKEN_INVALID');
127
+ }
128
+ } catch (error) {
129
+ console.error('Failed to load user info:', error);
130
+ // 重新抛出错误让调用方处理
131
+ throw error;
132
+ }
133
+ }
134
+
135
+ async function refreshUserInfo() {
136
+ const btn = event.target;
137
+ btn.disabled = true;
138
+ btn.textContent = '刷新中...';
139
+
140
+ await loadUserInfo();
141
+
142
+ btn.disabled = false;
143
+ btn.textContent = '刷新';
144
+ }
145
+
146
+ function showUserInfo(data) {
147
+ document.getElementById('login-form').classList.add('hidden');
148
+ document.getElementById('user-info').classList.remove('hidden');
149
+
150
+ const userInfo = data.userInfo || data;
151
+ const accountInfo = data.accountInfo || {};
152
+ const teamInfo = data.teamInfo || {};
153
+ const gatewayInfo = data.gatewayInfo || {};
154
+ const creditsPackage = accountInfo.creditsPackageSummary || {};
155
+
156
+ // 计算积分百分比
157
+ const creditsPercent = accountInfo.creditsLimit > 0
158
+ ? ((accountInfo.credits / accountInfo.creditsLimit) * 100).toFixed(1)
159
+ : 0;
160
+
161
+ // 计算预计恢复时间
162
+ const remainingCredits = accountInfo.creditsLimit - accountInfo.credits;
163
+ const recoveryHours = accountInfo.creditsRecoveryRate > 0
164
+ ? (remainingCredits / accountInfo.creditsRecoveryRate).toFixed(1)
165
+ : 0;
166
+
167
+ const html = `
168
+ <div class="panel">
169
+ <h3 class="panel-title">👤 用户信息</h3>
170
+ <div class="breakdown-list">
171
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
172
+ <div>
173
+ <div class="info-label">昵称</div>
174
+ <div class="info-value">${userInfo.nickName || '未设置'}</div>
175
+ </div>
176
+ <div>
177
+ <div class="info-label">手机</div>
178
+ <div class="info-value">${userInfo.phone}</div>
179
+ </div>
180
+ <div>
181
+ <div class="info-label">用户ID</div>
182
+ <div class="info-value">${userInfo.userId || '-'}</div>
183
+ </div>
184
+ <div>
185
+ <div class="info-label">AID</div>
186
+ <div class="info-value" style="font-size: 12px;">${userInfo.aid || '-'}</div>
187
+ </div>
188
+ </div>
189
+ </div>
190
+ </div>
191
+
192
+ <div class="panel">
193
+ <h3 class="panel-title">💎 账户信息</h3>
194
+ <div class="breakdown-list">
195
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
196
+ <div>
197
+ <div class="info-label">VIP类型</div>
198
+ <div class="info-value">${accountInfo.vipTypeName || '-'}</div>
199
+ </div>
200
+ <div>
201
+ <div class="info-label">VIP到期</div>
202
+ <div class="info-value">${accountInfo.vipExpireTime ? new Date(accountInfo.vipExpireTime).toLocaleDateString() : '-'}</div>
203
+ </div>
204
+ <div>
205
+ <div class="info-label">剩余天数</div>
206
+ <div class="info-value">${accountInfo.vipRemainingDays || 0} 天</div>
207
+ </div>
208
+ <div>
209
+ <div class="info-label">账户余额</div>
210
+ <div class="info-value">¥${accountInfo.balance || 0}</div>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <div class="panel">
217
+ <h3 class="panel-title">⚡ 积分信息</h3>
218
+ <div style="margin-bottom: 16px;">
219
+ <div class="info-label" style="margin-bottom: 8px;">当前积分: ${accountInfo.credits || 0} / ${accountInfo.creditsLimit || 0} (${creditsPercent}%)</div>
220
+ <div style="width: 100%; height: 20px; background: var(--gray-200); border-radius: 10px; overflow: hidden;">
221
+ <div style="height: 100%; width: ${creditsPercent}%; background: linear-gradient(90deg, #1890ff, #40a9ff); transition: width 0.3s;"></div>
222
+ </div>
223
+ </div>
224
+ <div class="breakdown-list">
225
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
226
+ <div>
227
+ <div class="info-label">恢复速率</div>
228
+ <div class="info-value">${accountInfo.creditsRecoveryRate || 0} 积分/小时</div>
229
+ </div>
230
+ <div>
231
+ <div class="info-label">预计恢复满</div>
232
+ <div class="info-value">${recoveryHours} 小时</div>
233
+ </div>
234
+ <div>
235
+ <div class="info-label">最后恢复</div>
236
+ <div class="info-value" style="font-size: 12px;">${accountInfo.lastRecoveryTime ? new Date(accountInfo.lastRecoveryTime).toLocaleString() : '-'}</div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+
242
+ <div class="panel">
243
+ <h3 class="panel-title">📦 积分包详情</h3>
244
+ <div class="breakdown-list">
245
+ <ul class="breakdown-list">
246
+ <li><span class="breakdown-label">总包数</span><span class="breakdown-value">${creditsPackage.totalPackageCount || 0}</span></li>
247
+ <li><span class="breakdown-label">通用积分</span><span class="breakdown-value">${creditsPackage.generalCredits || 0}</span></li>
248
+ <li><span class="breakdown-label">Chatbot</span><span class="breakdown-value">${creditsPackage.chatbotCredits || 0}</span></li>
249
+ <li><span class="breakdown-label">Codex</span><span class="breakdown-value">${creditsPackage.codexCredits || 0}</span></li>
250
+ <li><span class="breakdown-label">Claude Code</span><span class="breakdown-value">${creditsPackage.claudeCodeCredits || 0}</span></li>
251
+ <li><span class="breakdown-label">Gemini</span><span class="breakdown-value">${creditsPackage.geminiCredits || 0}</span></li>
252
+ <li><span class="breakdown-label">OpenClaw</span><span class="breakdown-value">${creditsPackage.openclawCredits || 0}</span></li>
253
+ </ul>
254
+ </div>
255
+ </div>
256
+
257
+ <div class="panel">
258
+ <h3 class="panel-title">👥 团队信息</h3>
259
+ <div class="breakdown-list">
260
+ <ul class="breakdown-list">
261
+ <li><span class="breakdown-label">当前团队</span><span class="breakdown-value">${teamInfo.currentTeamName || '个人账户'}</span></li>
262
+ <li><span class="breakdown-label">角色</span><span class="breakdown-value">${getRoleName(teamInfo.currentTeamRole)}</span></li>
263
+ <li><span class="breakdown-label">所属团队数</span><span class="breakdown-value">${teamInfo.teams ? teamInfo.teams.length : 0}</span></li>
264
+ </ul>
265
+ ${teamInfo.teams && teamInfo.teams.length > 0 ? `
266
+ <details style="margin-top: 12px;">
267
+ <summary style="cursor: pointer; color: var(--primary); font-size: 13px;">查看所有团队</summary>
268
+ <ul style="margin-top: 8px; list-style: none;">
269
+ ${teamInfo.teams.map(t => `
270
+ <li style="padding: 4px 0; font-size: 13px; color: var(--gray-600);">
271
+ ${t.teamName} - ${getRoleName(t.memberRole)} (${t.memberCount}人)
272
+ </li>
273
+ `).join('')}
274
+ </ul>
275
+ </details>
276
+ ` : ''}
277
+ </div>
278
+ </div>
279
+
280
+ <div class="panel">
281
+ <h3 class="panel-title">🔌 网关信息</h3>
282
+ <div class="breakdown-list">
283
+ <ul class="breakdown-list">
284
+ <li><span class="breakdown-label">网关名称</span><span class="breakdown-value">${gatewayInfo.gatewayName || '-'}</span></li>
285
+ <li><span class="breakdown-label">API Key</span><span class="breakdown-value" style="font-family: monospace; font-size: 12px;">${gatewayInfo.apiKey || '-'}</span></li>
286
+ <li><span class="breakdown-label">Base URL</span><span class="breakdown-value" style="font-family: monospace; font-size: 12px;">${gatewayInfo.modelBaseUrl || '-'}</span></li>
287
+ <li><span class="breakdown-label">状态</span><span class="breakdown-value">${gatewayInfo.apiKeyEnabled ? '<span class="badge-success">✅ 已启用</span>' : '<span class="badge-error">❌ 已禁用</span>'}</span></li>
288
+ </ul>
289
+ </div>
290
+ </div>
291
+ `;
292
+
293
+ document.getElementById('user-details').innerHTML = html;
294
+ }
295
+
296
+ function getRoleName(role) {
297
+ const roles = {
298
+ '0': '创建者',
299
+ '1': '管理员',
300
+ '2': '普通成员'
301
+ };
302
+ return roles[role] || '未知';
303
+ }
304
+
305
+ function logout() {
306
+ localStorage.removeItem('evol_kite_token');
307
+ document.getElementById('login-form').classList.remove('hidden');
308
+ document.getElementById('user-info').classList.add('hidden');
309
+ document.getElementById('phone').value = '';
310
+ document.getElementById('code').value = '';
311
+ }
312
+
313
+ function getDeviceId() {
314
+ let deviceId = localStorage.getItem('evol_device_id');
315
+ if (!deviceId) {
316
+ deviceId = 'device_' + Math.random().toString(36).substr(2, 9) + '_' + Date.now();
317
+ localStorage.setItem('evol_device_id', deviceId);
318
+ }
319
+ return deviceId;
320
+ }
321
+
322
+ function getDeviceName() {
323
+ return navigator.userAgent.includes('Windows') ? 'Windows PC' :
324
+ navigator.userAgent.includes('Mac') ? 'Mac' :
325
+ navigator.userAgent.includes('Linux') ? 'Linux' : 'Unknown';
326
+ }
@@ -0,0 +1,285 @@
1
+ /**
2
+ * 自定义对话框组件
3
+ * 替代系统的 alert() 和 confirm()
4
+ */
5
+
6
+ class Dialog {
7
+ constructor() {
8
+ this.container = null;
9
+ this.tipContainer = null;
10
+ this.init();
11
+ }
12
+
13
+ init() {
14
+ // 创建对话框容器
15
+ this.container = document.createElement('div');
16
+ this.container.id = 'custom-dialog-container';
17
+ this.container.style.cssText = `
18
+ position: fixed;
19
+ top: 0;
20
+ left: 0;
21
+ width: 100%;
22
+ height: 100%;
23
+ background: rgba(0, 0, 0, 0.5);
24
+ display: none;
25
+ align-items: center;
26
+ justify-content: center;
27
+ z-index: 10000;
28
+ `;
29
+ document.body.appendChild(this.container);
30
+
31
+ // 创建 tip 提示容器
32
+ this.tipContainer = document.createElement('div');
33
+ this.tipContainer.id = 'custom-tip-container';
34
+ this.tipContainer.style.cssText = `
35
+ position: fixed;
36
+ top: 80px;
37
+ left: 50%;
38
+ transform: translateX(-50%);
39
+ z-index: 10001;
40
+ pointer-events: none;
41
+ `;
42
+ document.body.appendChild(this.tipContainer);
43
+ }
44
+
45
+ show(options) {
46
+ const {
47
+ title = '提示',
48
+ message = '',
49
+ type = 'alert', // 'alert' or 'confirm'
50
+ confirmText = '确定',
51
+ cancelText = '取消',
52
+ onConfirm = () => {},
53
+ onCancel = () => {}
54
+ } = options;
55
+
56
+ // 创建对话框内容
57
+ const dialog = document.createElement('div');
58
+ dialog.style.cssText = `
59
+ background: white;
60
+ border-radius: 8px;
61
+ padding: 24px;
62
+ min-width: 320px;
63
+ max-width: 480px;
64
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
65
+ `;
66
+
67
+ // 标题
68
+ const titleEl = document.createElement('h3');
69
+ titleEl.textContent = title;
70
+ titleEl.style.cssText = `
71
+ margin: 0 0 16px 0;
72
+ font-size: 18px;
73
+ font-weight: 600;
74
+ color: #333;
75
+ `;
76
+
77
+ // 消息
78
+ const messageEl = document.createElement('p');
79
+ messageEl.textContent = message;
80
+ messageEl.style.cssText = `
81
+ margin: 0 0 24px 0;
82
+ font-size: 14px;
83
+ color: #666;
84
+ line-height: 1.5;
85
+ `;
86
+
87
+ // 按钮容器
88
+ const buttonsEl = document.createElement('div');
89
+ buttonsEl.style.cssText = `
90
+ display: flex;
91
+ justify-content: flex-end;
92
+ gap: 12px;
93
+ `;
94
+
95
+ // 取消按钮(仅 confirm 类型显示)
96
+ if (type === 'confirm') {
97
+ const cancelBtn = document.createElement('button');
98
+ cancelBtn.textContent = cancelText;
99
+ cancelBtn.style.cssText = `
100
+ padding: 8px 16px;
101
+ border: 1px solid #ddd;
102
+ border-radius: 4px;
103
+ background: white;
104
+ color: #666;
105
+ font-size: 14px;
106
+ cursor: pointer;
107
+ transition: all 0.2s;
108
+ `;
109
+ cancelBtn.onmouseover = () => {
110
+ cancelBtn.style.background = '#f5f5f5';
111
+ };
112
+ cancelBtn.onmouseout = () => {
113
+ cancelBtn.style.background = 'white';
114
+ };
115
+ cancelBtn.onclick = () => {
116
+ this.hide();
117
+ onCancel();
118
+ };
119
+ buttonsEl.appendChild(cancelBtn);
120
+ }
121
+
122
+ // 确定按钮
123
+ const confirmBtn = document.createElement('button');
124
+ confirmBtn.textContent = confirmText;
125
+ confirmBtn.style.cssText = `
126
+ padding: 8px 16px;
127
+ border: none;
128
+ border-radius: 4px;
129
+ background: #007bff;
130
+ color: white;
131
+ font-size: 14px;
132
+ cursor: pointer;
133
+ transition: all 0.2s;
134
+ `;
135
+ confirmBtn.onmouseover = () => {
136
+ confirmBtn.style.background = '#0056b3';
137
+ };
138
+ confirmBtn.onmouseout = () => {
139
+ confirmBtn.style.background = '#007bff';
140
+ };
141
+ confirmBtn.onclick = () => {
142
+ this.hide();
143
+ onConfirm();
144
+ };
145
+ buttonsEl.appendChild(confirmBtn);
146
+
147
+ // 组装对话框
148
+ dialog.appendChild(titleEl);
149
+ dialog.appendChild(messageEl);
150
+ dialog.appendChild(buttonsEl);
151
+
152
+ // 清空容器并添加新对话框
153
+ this.container.innerHTML = '';
154
+ this.container.appendChild(dialog);
155
+ this.container.style.display = 'flex';
156
+
157
+ // 点击背景关闭(仅 alert 类型)
158
+ if (type === 'alert') {
159
+ this.container.onclick = (e) => {
160
+ if (e.target === this.container) {
161
+ this.hide();
162
+ }
163
+ };
164
+ }
165
+ }
166
+
167
+ hide() {
168
+ this.container.style.display = 'none';
169
+ this.container.innerHTML = '';
170
+ }
171
+
172
+ alert(message, title = '提示') {
173
+ return new Promise((resolve) => {
174
+ this.show({
175
+ title,
176
+ message,
177
+ type: 'alert',
178
+ onConfirm: resolve
179
+ });
180
+ });
181
+ }
182
+
183
+ confirm(message, title = '确认') {
184
+ return new Promise((resolve) => {
185
+ this.show({
186
+ title,
187
+ message,
188
+ type: 'confirm',
189
+ onConfirm: () => resolve(true),
190
+ onCancel: () => resolve(false)
191
+ });
192
+ });
193
+ }
194
+
195
+ tip(message, type = 'success', duration = 2000) {
196
+ const tip = document.createElement('div');
197
+
198
+ // 根据类型设置颜色
199
+ const colors = {
200
+ success: { bg: '#52c41a', icon: '✓' },
201
+ error: { bg: '#ff4d4f', icon: '✗' },
202
+ warning: { bg: '#faad14', icon: '⚠' },
203
+ info: { bg: '#1890ff', icon: 'ℹ' }
204
+ };
205
+ const color = colors[type] || colors.info;
206
+
207
+ tip.style.cssText = `
208
+ background: ${color.bg};
209
+ color: white;
210
+ padding: 12px 20px;
211
+ border-radius: 4px;
212
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
213
+ margin-bottom: 12px;
214
+ display: flex;
215
+ align-items: center;
216
+ gap: 8px;
217
+ font-size: 14px;
218
+ pointer-events: auto;
219
+ animation: tipSlideIn 0.3s ease-out;
220
+ `;
221
+
222
+ tip.innerHTML = `
223
+ <span style="font-size: 16px; font-weight: bold;">${color.icon}</span>
224
+ <span>${message}</span>
225
+ `;
226
+
227
+ // 添加动画样式
228
+ if (!document.getElementById('tip-animation-style')) {
229
+ const style = document.createElement('style');
230
+ style.id = 'tip-animation-style';
231
+ style.textContent = `
232
+ @keyframes tipSlideIn {
233
+ from {
234
+ opacity: 0;
235
+ transform: translateY(-20px);
236
+ }
237
+ to {
238
+ opacity: 1;
239
+ transform: translateY(0);
240
+ }
241
+ }
242
+ @keyframes tipSlideOut {
243
+ from {
244
+ opacity: 1;
245
+ transform: translateY(0);
246
+ }
247
+ to {
248
+ opacity: 0;
249
+ transform: translateY(-20px);
250
+ }
251
+ }
252
+ `;
253
+ document.head.appendChild(style);
254
+ }
255
+
256
+ this.tipContainer.appendChild(tip);
257
+
258
+ // 自动移除
259
+ setTimeout(() => {
260
+ tip.style.animation = 'tipSlideOut 0.3s ease-out';
261
+ setTimeout(() => {
262
+ tip.remove();
263
+ }, 300);
264
+ }, duration);
265
+ }
266
+
267
+ success(message, duration = 2000) {
268
+ this.tip(message, 'success', duration);
269
+ }
270
+
271
+ error(message, duration = 3000) {
272
+ this.tip(message, 'error', duration);
273
+ }
274
+
275
+ warning(message, duration = 2500) {
276
+ this.tip(message, 'warning', duration);
277
+ }
278
+
279
+ info(message, duration = 2000) {
280
+ this.tip(message, 'info', duration);
281
+ }
282
+ }
283
+
284
+ // 全局实例
285
+ window.dialog = new Dialog();
@@ -0,0 +1,50 @@
1
+ // 在 sendSMS 按钮事件监听器中添加更详细的错误处理
2
+ document.getElementById('btn-send-code').addEventListener('click', async () => {
3
+ const phone = document.getElementById('login-phone').value.trim();
4
+
5
+ // 验证手机号格式
6
+ if (!phone) {
7
+ showMessage('请输入手机号', 'error');
8
+ return;
9
+ }
10
+
11
+ if (!/^1[3-9]\d{9}$/.test(phone)) {
12
+ showMessage('请输入有效的中国大陆手机号(11位,以1开头)', 'error');
13
+ return;
14
+ }
15
+
16
+ const btn = document.getElementById('btn-send-code');
17
+ btn.disabled = true;
18
+ btn.textContent = '发送中...';
19
+
20
+ try {
21
+ const data = await app.sendSMS(phone);
22
+ console.log('SMS response:', data); // 调试日志
23
+
24
+ if (data.success) {
25
+ showMessage('验证码已发送,请查收短信', 'success');
26
+ let countdown = 60;
27
+ const timer = setInterval(() => {
28
+ countdown--;
29
+ btn.textContent = countdown + '秒后重试';
30
+ if (countdown <= 0) {
31
+ clearInterval(timer);
32
+ btn.disabled = false;
33
+ btn.textContent = '发送验证码';
34
+ }
35
+ }, 1000);
36
+ } else {
37
+ // 显示详细的错误信息
38
+ const errorMsg = data.msg || data.message || '发送失败,请稍后重试';
39
+ showMessage('发送失败: ' + errorMsg, 'error');
40
+ console.error('SMS error:', data);
41
+ btn.disabled = false;
42
+ btn.textContent = '发送验证码';
43
+ }
44
+ } catch (err) {
45
+ console.error('SMS request error:', err);
46
+ showMessage('网络错误: ' + err.message, 'error');
47
+ btn.disabled = false;
48
+ btn.textContent = '发送验证码';
49
+ }
50
+ });