@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,585 @@
1
+ /**
2
+ * Kite 注册中心全面测试套件
3
+ *
4
+ * 测试覆盖:
5
+ * 1. 所有模块的 RPC 方法注册
6
+ * 2. 所有模块的事件发布/订阅注册
7
+ * 3. 注册中心核心功能
8
+ * 4. 缓存机制
9
+ */
10
+
11
+ // 测试配置
12
+ const TEST_CONFIG = {
13
+ modules: ['launcher', 'kernel', 'watchdog', 'backup', 'web', 'assistant', 'acp_channel'],
14
+ timeout: 5000
15
+ };
16
+
17
+ // 测试结果统计
18
+ const TEST_STATS = {
19
+ total: 0,
20
+ passed: 0,
21
+ failed: 0,
22
+ skipped: 0
23
+ };
24
+
25
+ // ============================================================
26
+ // 测试工具函数
27
+ // ============================================================
28
+
29
+ function logTest(message, type = 'info') {
30
+ const output = document.getElementById('test-output');
31
+ if (!output) return;
32
+
33
+ const colors = {
34
+ 'info': '#9cdcfe',
35
+ 'pass': '#4ec9b0',
36
+ 'fail': '#f48771',
37
+ 'skip': '#ce9178',
38
+ 'section': '#dcdcaa',
39
+ 'subsection': '#c586c0'
40
+ };
41
+
42
+ const color = colors[type] || colors.info;
43
+ const prefix = type === 'pass' ? '✓ ' : type === 'fail' ? '✗ ' : type === 'skip' ? '⊘ ' : '';
44
+
45
+ // 为测试结果(pass/fail/skip)添加时间戳
46
+ let timestampPrefix = '';
47
+ if (type === 'pass' || type === 'fail' || type === 'skip') {
48
+ const now = new Date();
49
+ const timestamp = now.toISOString().replace('T', ' ').substring(0, 23); // YYYY-MM-DD HH:MM:SS.mmm
50
+ timestampPrefix = `[${timestamp}] `;
51
+ }
52
+
53
+ output.innerHTML += `<span style="color:${color}">${timestampPrefix}${prefix}${message}</span>\n`;
54
+ output.scrollTop = output.scrollHeight;
55
+ }
56
+
57
+ function assert(condition, message) {
58
+ TEST_STATS.total++;
59
+ if (condition) {
60
+ TEST_STATS.passed++;
61
+ logTest(message, 'pass');
62
+ return true;
63
+ } else {
64
+ TEST_STATS.failed++;
65
+ logTest(message, 'fail');
66
+ return false;
67
+ }
68
+ }
69
+
70
+ function skip(message) {
71
+ TEST_STATS.skipped++;
72
+ logTest(message, 'skip');
73
+ }
74
+
75
+ async function testRpcMethod(module, field, methodName) {
76
+ try {
77
+ const result = await kernelClient.call('registry.lookup', {
78
+ field: field,
79
+ module: module
80
+ });
81
+
82
+ if (result.results && result.results.length > 0) {
83
+ const value = result.results[0].value;
84
+ const actualMethod = typeof value === 'string' ? value : value.method;
85
+ return assert(
86
+ actualMethod === methodName,
87
+ `${module}.${methodName}: 注册正确 (${field})`
88
+ );
89
+ } else {
90
+ return assert(false, `${module}.${methodName}: 未找到注册`);
91
+ }
92
+ } catch (err) {
93
+ return assert(false, `${module}.${methodName}: 查询失败 - ${err.message}`);
94
+ }
95
+ }
96
+
97
+ async function testEvent(module, eventPath, eventName) {
98
+ try {
99
+ const result = await kernelClient.call('registry.lookup', {
100
+ field: eventPath,
101
+ module: module
102
+ });
103
+
104
+ return assert(
105
+ result.results && result.results.length > 0,
106
+ `${module}: 事件 ${eventName} 已注册`
107
+ );
108
+ } catch (err) {
109
+ return assert(false, `${module}: 事件 ${eventName} 查询失败 - ${err.message}`);
110
+ }
111
+ }
112
+
113
+ // ============================================================
114
+ // 主测试入口
115
+ // ============================================================
116
+
117
+ async function runAllTests() {
118
+ const output = document.getElementById('test-output');
119
+ if (!output) return;
120
+
121
+ // 重置统计
122
+ TEST_STATS.total = 0;
123
+ TEST_STATS.passed = 0;
124
+ TEST_STATS.failed = 0;
125
+ TEST_STATS.skipped = 0;
126
+
127
+ output.textContent = '';
128
+ logTest('='.repeat(70), 'info');
129
+ logTest('Kite 注册中心全面测试套件', 'section');
130
+ logTest('='.repeat(70), 'info');
131
+ logTest('', 'info');
132
+
133
+ try {
134
+ // 等待 kernelClient 连接和认证
135
+ if (!kernelClient) {
136
+ logTest('错误: kernelClient 未初始化', 'fail');
137
+ return;
138
+ }
139
+
140
+ if (!kernelClient.connected || !kernelClient.authenticated) {
141
+ logTest('等待 Kernel 连接和认证...', 'info');
142
+
143
+ // 等待最多 10 秒
144
+ const maxWait = 10000;
145
+ const startTime = Date.now();
146
+
147
+ while ((!kernelClient.connected || !kernelClient.authenticated) && (Date.now() - startTime < maxWait)) {
148
+ await new Promise(resolve => setTimeout(resolve, 100));
149
+ }
150
+
151
+ if (!kernelClient.connected || !kernelClient.authenticated) {
152
+ logTest('错误: Kernel 连接或认证超时', 'fail');
153
+ logTest(` connected: ${kernelClient.connected}, authenticated: ${kernelClient.authenticated}`, 'info');
154
+ return;
155
+ }
156
+
157
+ logTest('✓ Kernel 已连接并认证', 'pass');
158
+ logTest('', 'info');
159
+ }
160
+
161
+ // 1. 核心功能测试
162
+ await testRegistryCore();
163
+
164
+ // 2. Launcher 模块测试
165
+ await testLauncherModule();
166
+
167
+ // 3. Kernel 模块测试
168
+ await testKernelModule();
169
+
170
+ // 4. Watchdog 模块测试
171
+ await testWatchdogModule();
172
+
173
+ // 5. Backup 模块测试
174
+ await testBackupModule();
175
+
176
+ // 6. Web 模块测试
177
+ await testWebModule();
178
+
179
+ // 7. Assistant 模块测试 (如果存在)
180
+ await testAssistantModule();
181
+
182
+ // 8. ACP Channel 模块测试 (如果存在)
183
+ await testAcpChannelModule();
184
+
185
+ // 9. 缓存机制测试
186
+ await testCacheMechanism();
187
+
188
+ // 10. 事件订阅测试
189
+ await testEventSubscription();
190
+
191
+ // 总结
192
+ logTest('', 'info');
193
+ logTest('='.repeat(70), 'info');
194
+ logTest('测试完成', 'section');
195
+ logTest('='.repeat(70), 'info');
196
+ logTest(`总计: ${TEST_STATS.total} | 通过: ${TEST_STATS.passed} | 失败: ${TEST_STATS.failed} | 跳过: ${TEST_STATS.skipped}`, 'info');
197
+
198
+ if (TEST_STATS.failed === 0) {
199
+ logTest('', 'info');
200
+ logTest('🎉 所有测试通过!Kite 实例运行正常。', 'pass');
201
+ } else {
202
+ logTest('', 'info');
203
+ logTest(`⚠️ 有 ${TEST_STATS.failed} 个测试失败,请检查相关模块。`, 'fail');
204
+ }
205
+
206
+ // 保存日志到服务器
207
+ logTest('', 'info');
208
+ logTest('正在保存测试日志到服务器...', 'info');
209
+ await saveTestLogToServer(output.textContent);
210
+
211
+ } catch (err) {
212
+ logTest('', 'info');
213
+ logTest(`测试套件执行失败: ${err.message}`, 'fail');
214
+ console.error(err);
215
+
216
+ // 即使失败也保存日志
217
+ try {
218
+ await saveTestLogToServer(output.textContent);
219
+ } catch (saveErr) {
220
+ console.error('保存日志失败:', saveErr);
221
+ }
222
+ }
223
+ }
224
+
225
+ /**
226
+ * 保存测试日志到服务器
227
+ */
228
+ async function saveTestLogToServer(content) {
229
+ try {
230
+ const response = await fetch('/api/save_test_log', {
231
+ method: 'POST',
232
+ headers: {
233
+ 'Content-Type': 'application/json'
234
+ },
235
+ body: JSON.stringify({
236
+ content: content,
237
+ test_name: 'registry_test'
238
+ })
239
+ });
240
+
241
+ if (!response.ok) {
242
+ throw new Error(`HTTP ${response.status}`);
243
+ }
244
+
245
+ const result = await response.json();
246
+ logTest(`✓ 日志已保存到服务器: ${result.log_path}`, 'pass');
247
+ logTest(` 时间: ${result.timestamp}`, 'info');
248
+
249
+ } catch (err) {
250
+ logTest(`✗ 保存日志失败: ${err.message}`, 'fail');
251
+ }
252
+ }
253
+
254
+ // ============================================================
255
+ // 1. 注册中心核心功能测试
256
+ // ============================================================
257
+
258
+ async function testRegistryCore() {
259
+ logTest('【1】注册中心核心功能测试', 'section');
260
+ logTest('', 'info');
261
+
262
+ // 测试 registry.lookup 基本功能
263
+ try {
264
+ const result = await kernelClient.call('registry.lookup', {});
265
+ assert(
266
+ result.results && Array.isArray(result.results),
267
+ 'registry.lookup: 返回结果数组'
268
+ );
269
+ assert(
270
+ typeof result.last_update_time === 'number',
271
+ 'registry.lookup: 返回 last_update_time'
272
+ );
273
+ } catch (err) {
274
+ assert(false, `registry.lookup: 基本调用失败 - ${err.message}`);
275
+ }
276
+
277
+ // 测试 registry.get 功能
278
+ try {
279
+ const result = await kernelClient.call('registry.get', {
280
+ path: 'launcher.module_id'
281
+ });
282
+ assert(
283
+ result.value === 'launcher',
284
+ 'registry.get: 精确查询 launcher.module_id'
285
+ );
286
+ } catch (err) {
287
+ assert(false, `registry.get: 查询失败 - ${err.message}`);
288
+ }
289
+
290
+ // 测试 glob 模式匹配
291
+ try {
292
+ const result = await kernelClient.call('registry.lookup', {
293
+ field: 'tools.rpc.module.*'
294
+ });
295
+ assert(
296
+ result.results && result.results.length > 0,
297
+ 'registry.lookup: glob 模式匹配 (tools.rpc.module.*)'
298
+ );
299
+ } catch (err) {
300
+ assert(false, `registry.lookup: glob 匹配失败 - ${err.message}`);
301
+ }
302
+
303
+ logTest('', 'info');
304
+ }
305
+
306
+ // ============================================================
307
+ // 2. Launcher 模块测试
308
+ // ============================================================
309
+
310
+ async function testLauncherModule() {
311
+ logTest('【2】Launcher 模块测试', 'section');
312
+ logTest('', 'info');
313
+
314
+ logTest('RPC 方法注册:', 'subsection');
315
+ await testRpcMethod('launcher', 'tools.rpc.launcher.start_module', 'start_module');
316
+ await testRpcMethod('launcher', 'tools.rpc.launcher.stop_module', 'stop_module');
317
+ await testRpcMethod('launcher', 'tools.rpc.launcher.restart_module', 'restart_module');
318
+ await testRpcMethod('launcher', 'tools.rpc.launcher.list_modules', 'list_modules');
319
+ await testRpcMethod('launcher', 'tools.rpc.module.config.get', 'get_module_config');
320
+ await testRpcMethod('launcher', 'tools.rpc.module.config.update', 'update_module_config');
321
+ await testRpcMethod('launcher', 'tools.rpc.module.config.reset', 'reset_module_config');
322
+
323
+ logTest('', 'info');
324
+ logTest('事件发布注册:', 'subsection');
325
+ await testEvent('launcher', 'events_publish.system.ready', 'system.ready');
326
+ await testEvent('launcher', 'events_publish.module.starting', 'module.starting');
327
+ await testEvent('launcher', 'events_publish.module.started', 'module.started');
328
+ await testEvent('launcher', 'events_publish.module.ready', 'module.ready');
329
+ await testEvent('launcher', 'events_publish.module.stopped', 'module.stopped');
330
+ await testEvent('launcher', 'events_publish.module.exiting', 'module.exiting');
331
+ await testEvent('launcher', 'events_publish.module.shutdown', 'module.shutdown');
332
+
333
+ logTest('', 'info');
334
+ logTest('验证已删除的事件:', 'subsection');
335
+ try {
336
+ const result = await kernelClient.call('registry.lookup', {
337
+ field: 'events_publish.module.state_changed',
338
+ module: 'launcher'
339
+ });
340
+ assert(
341
+ !result.results || result.results.length === 0,
342
+ 'module.state_changed: 已正确删除'
343
+ );
344
+ } catch (err) {
345
+ assert(false, `验证删除失败 - ${err.message}`);
346
+ }
347
+
348
+ logTest('', 'info');
349
+ }
350
+
351
+ // ============================================================
352
+ // 3. Kernel 模块测试
353
+ // ============================================================
354
+
355
+ async function testKernelModule() {
356
+ logTest('【3】Kernel 模块测试', 'section');
357
+ logTest('', 'info');
358
+
359
+ logTest('Kernel 内置 RPC 方法测试:', 'subsection');
360
+ // Kernel 的方法是内置的,不在注册中心,直接调用测试
361
+ try {
362
+ await kernelClient.call('kernel.ping');
363
+ assert(true, 'kernel.ping: 调用成功');
364
+ } catch (err) {
365
+ assert(false, `kernel.ping: 调用失败 - ${err.message}`);
366
+ }
367
+
368
+ try {
369
+ const stats = await kernelClient.call('kernel.stats');
370
+ assert(
371
+ stats && typeof stats.registry === 'object',
372
+ 'kernel.stats: 返回正确的统计数据'
373
+ );
374
+ } catch (err) {
375
+ assert(false, `kernel.stats: 调用失败 - ${err.message}`);
376
+ }
377
+
378
+ try {
379
+ const health = await kernelClient.call('kernel.health');
380
+ assert(
381
+ health && typeof health.status === 'string',
382
+ 'kernel.health: 返回健康状态'
383
+ );
384
+ } catch (err) {
385
+ assert(false, `kernel.health: 调用失败 - ${err.message}`);
386
+ }
387
+
388
+ logTest('', 'info');
389
+ }
390
+
391
+ // ============================================================
392
+ // 4. Watchdog 模块测试
393
+ // ============================================================
394
+
395
+ async function testWatchdogModule() {
396
+ logTest('【4】Watchdog 模块测试', 'section');
397
+ logTest('', 'info');
398
+
399
+ logTest('RPC 方法注册:', 'subsection');
400
+ await testRpcMethod('watchdog', 'tools.rpc.module.health', 'health');
401
+ await testRpcMethod('watchdog', 'tools.rpc.module.status', 'status');
402
+
403
+ logTest('', 'info');
404
+ logTest('事件发布注册:', 'subsection');
405
+ await testEvent('watchdog', 'events_publish.watchdog.module.unhealthy', 'watchdog.module.unhealthy');
406
+ await testEvent('watchdog', 'events_publish.watchdog.module.recovered', 'watchdog.module.recovered');
407
+ await testEvent('watchdog', 'events_publish.watchdog.module.resource_critical', 'watchdog.module.resource_critical');
408
+ await testEvent('watchdog', 'events_publish.watchdog.module.resource_warning', 'watchdog.module.resource_warning');
409
+ await testEvent('watchdog', 'events_publish.watchdog.module.resource_recovered', 'watchdog.module.resource_recovered');
410
+ await testEvent('watchdog', 'events_publish.watchdog.alert', 'watchdog.alert');
411
+
412
+ logTest('', 'info');
413
+ }
414
+
415
+ // ============================================================
416
+ // 5. Backup 模块测试
417
+ // ============================================================
418
+
419
+ async function testBackupModule() {
420
+ logTest('【5】Backup 模块测试', 'section');
421
+ logTest('', 'info');
422
+
423
+ logTest('RPC 方法注册:', 'subsection');
424
+ await testRpcMethod('backup', 'tools.rpc.module.health', 'health');
425
+ await testRpcMethod('backup', 'tools.rpc.module.status', 'status');
426
+
427
+ logTest('', 'info');
428
+ logTest('事件发布注册:', 'subsection');
429
+ await testEvent('backup', 'events_publish.backup.test', 'backup.test');
430
+
431
+ logTest('', 'info');
432
+ }
433
+
434
+ // ============================================================
435
+ // 6. Web 模块测试
436
+ // ============================================================
437
+
438
+ async function testWebModule() {
439
+ logTest('【6】Web 模块测试', 'section');
440
+ logTest('', 'info');
441
+
442
+ logTest('RPC 方法注册:', 'subsection');
443
+ await testRpcMethod('web', 'tools.rpc.module.health', 'health');
444
+ await testRpcMethod('web', 'tools.rpc.module.status', 'status');
445
+ await testRpcMethod('web', 'tools.rpc.web.list_tokens', 'list_tokens');
446
+ await testRpcMethod('web', 'tools.rpc.web.revoke_token', 'revoke_token');
447
+
448
+ logTest('', 'info');
449
+ logTest('事件发布注册:', 'subsection');
450
+ await testEvent('web', 'events_publish.web.started', 'web.started');
451
+ await testEvent('web', 'events_publish.web.test', 'web.test');
452
+
453
+ logTest('', 'info');
454
+ }
455
+
456
+ // ============================================================
457
+ // 7. Assistant 模块测试
458
+ // ============================================================
459
+
460
+ async function testAssistantModule() {
461
+ logTest('【7】Assistant 模块测试', 'section');
462
+ logTest('', 'info');
463
+
464
+ // 检查模块是否存在
465
+ try {
466
+ const result = await kernelClient.call('registry.lookup', {
467
+ module: 'assistant'
468
+ });
469
+
470
+ if (!result.results || result.results.length === 0) {
471
+ skip('Assistant 模块未运行,跳过测试');
472
+ logTest('', 'info');
473
+ return;
474
+ }
475
+
476
+ logTest('事件发布注册:', 'subsection');
477
+ await testEvent('assistant', 'events_publish.assistant.test', 'assistant.test');
478
+
479
+ } catch (err) {
480
+ skip(`Assistant 模块测试失败: ${err.message}`);
481
+ }
482
+
483
+ logTest('', 'info');
484
+ }
485
+
486
+ // ============================================================
487
+ // 8. ACP Channel 模块测试
488
+ // ============================================================
489
+
490
+ async function testAcpChannelModule() {
491
+ logTest('【8】ACP Channel 模块测试', 'section');
492
+ logTest('', 'info');
493
+
494
+ // 检查模块是否存在
495
+ try {
496
+ const result = await kernelClient.call('registry.lookup', {
497
+ module: 'acp_channel'
498
+ });
499
+
500
+ if (!result.results || result.results.length === 0) {
501
+ skip('ACP Channel 模块未运行,跳过测试');
502
+ logTest('', 'info');
503
+ return;
504
+ }
505
+
506
+ logTest('事件发布注册:', 'subsection');
507
+ await testEvent('acp_channel', 'events_publish.acp_channel.test', 'acp_channel.test');
508
+
509
+ } catch (err) {
510
+ skip(`ACP Channel 模块测试失败: ${err.message}`);
511
+ }
512
+
513
+ logTest('', 'info');
514
+ }
515
+
516
+ // ============================================================
517
+ // 9. 缓存机制测试
518
+ // ============================================================
519
+
520
+ async function testCacheMechanism() {
521
+ logTest('【9】缓存机制测试', 'section');
522
+ logTest('', 'info');
523
+
524
+ try {
525
+ // 第一次查询
526
+ const result1 = await kernelClient.call('registry.lookup', {
527
+ field: 'tools.rpc.module.health'
528
+ });
529
+
530
+ const time1 = result1.last_update_time;
531
+ assert(typeof time1 === 'number', '缓存: last_update_time 存在');
532
+
533
+ // 第二次查询(应该使用缓存)
534
+ const result2 = await kernelClient.call('registry.lookup', {
535
+ field: 'tools.rpc.module.health'
536
+ });
537
+
538
+ const time2 = result2.last_update_time;
539
+ assert(time1 === time2, '缓存: last_update_time 一致(缓存生效)');
540
+
541
+ // 检查前端缓存
542
+ if (typeof _registryCache !== 'undefined') {
543
+ assert(
544
+ _registryCache.lastUpdateTime > 0,
545
+ '前端缓存: lastUpdateTime 已更新'
546
+ );
547
+ assert(
548
+ Object.keys(_registryCache.records).length > 0,
549
+ '前端缓存: 缓存记录存在'
550
+ );
551
+ } else {
552
+ skip('前端缓存对象未定义');
553
+ }
554
+
555
+ } catch (err) {
556
+ assert(false, `缓存机制测试失败 - ${err.message}`);
557
+ }
558
+
559
+ logTest('', 'info');
560
+ }
561
+
562
+ // ============================================================
563
+ // 10. 事件订阅测试
564
+ // ============================================================
565
+
566
+ async function testEventSubscription() {
567
+ logTest('【10】事件订阅测试', 'section');
568
+ logTest('', 'info');
569
+
570
+ try {
571
+ // 测试订阅功能
572
+ const testEvents = ['module.started', 'module.stopped'];
573
+ await kernelClient.call('event.subscribe', { events: testEvents });
574
+ assert(true, '事件订阅: event.subscribe 调用成功');
575
+
576
+ // 测试取消订阅
577
+ await kernelClient.call('event.unsubscribe', { events: ['module.started'] });
578
+ assert(true, '事件订阅: event.unsubscribe 调用成功');
579
+
580
+ } catch (err) {
581
+ assert(false, `事件订阅测试失败 - ${err.message}`);
582
+ }
583
+
584
+ logTest('', 'info');
585
+ }