@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.
- package/CHANGELOG.md +302 -0
- package/cli.js +119 -4
- package/core/dependency_checker.py +250 -0
- package/core/env_checker.py +490 -0
- package/dependencies_lock.json +128 -0
- package/extensions/agents/assistant/entry.py +111 -1
- package/extensions/agents/assistant/server.py +279 -215
- package/extensions/channels/acp_channel/entry.py +111 -1
- package/extensions/channels/acp_channel/module.md +23 -22
- package/extensions/channels/acp_channel/server.py +279 -215
- package/extensions/event_hub_bench/entry.py +107 -1
- package/extensions/services/backup/entry.py +306 -21
- package/extensions/services/backup/module.md +24 -22
- package/extensions/services/evol/auth_manager.py +443 -0
- package/extensions/services/evol/config.yaml +149 -0
- package/extensions/services/evol/config_loader.py +117 -0
- package/extensions/services/evol/entry.py +406 -0
- package/extensions/services/evol/evol_api.py +173 -0
- package/extensions/services/evol/evol_config.json5 +29 -0
- package/extensions/services/evol/migrate_tokens.py +122 -0
- package/extensions/services/evol/module.md +32 -0
- package/extensions/services/evol/pairing.py +250 -0
- package/extensions/services/evol/pairing_codes.jsonl +1 -0
- package/extensions/services/evol/relay.py +682 -0
- package/extensions/services/evol/relay_config.json5 +67 -0
- package/extensions/services/evol/routes/__init__.py +1 -0
- package/extensions/services/evol/routes/routes_management_ws.py +127 -0
- package/extensions/services/evol/routes/routes_rpc.py +89 -0
- package/extensions/services/evol/routes/routes_test.py +61 -0
- package/extensions/services/evol/server.py +875 -0
- package/extensions/services/evol/static/css/style.css +1200 -0
- package/extensions/services/evol/static/index.html +781 -0
- package/extensions/services/evol/static/index_evol.html +14 -0
- package/extensions/services/evol/static/js/app.js +6304 -0
- package/extensions/services/evol/static/js/auth.js +326 -0
- package/extensions/services/evol/static/js/dialog.js +285 -0
- package/extensions/services/evol/static/js/evol-app-fixed.js +50 -0
- package/extensions/services/evol/static/js/evol-app.js +1949 -0
- package/extensions/services/evol/static/js/evol-app.js.bak +1800 -0
- package/extensions/services/evol/static/js/kernel-client-example.js +228 -0
- package/extensions/services/evol/static/js/kernel-client.js +396 -0
- package/extensions/services/evol/static/js/main.js +141 -0
- package/extensions/services/evol/static/js/registry-tests.js +585 -0
- package/extensions/services/evol/static/js/stats.js +217 -0
- package/extensions/services/evol/static/js/token-manager.js +175 -0
- package/extensions/services/evol/static/pairing.html +248 -0
- package/extensions/services/evol/static/test_registry.html +262 -0
- package/extensions/services/evol/static/test_relay.html +462 -0
- package/extensions/services/evol/stats_manager.py +240 -0
- package/extensions/services/model_service/entry.py +167 -19
- package/extensions/services/model_service/module.md +21 -22
- package/extensions/services/proxy/.claude/settings.local.json +13 -0
- package/extensions/services/proxy/CHANGELOG_20260308.md +258 -0
- package/extensions/services/proxy/_fix_prints.py +133 -0
- package/extensions/services/proxy/_fix_prints2.py +87 -0
- package/extensions/services/proxy/agentcp/LICENCE +178 -0
- package/extensions/services/proxy/agentcp/README copy.md +85 -0
- package/extensions/services/proxy/agentcp/README.md +260 -0
- package/extensions/services/proxy/agentcp/__init__.py +16 -0
- package/extensions/services/proxy/agentcp/agent.py +4 -0
- package/extensions/services/proxy/agentcp/agentcp.py +2494 -0
- package/extensions/services/proxy/agentcp/agentprofile.json +89 -0
- package/extensions/services/proxy/agentcp/ap/__init__.py +16 -0
- package/extensions/services/proxy/agentcp/ap/ap_client.py +316 -0
- package/extensions/services/proxy/agentcp/assets/images/wechat_qr.png +0 -0
- package/extensions/services/proxy/agentcp/backup/metrics.json +31 -0
- package/extensions/services/proxy/agentcp/base/__init__.py +20 -0
- package/extensions/services/proxy/agentcp/base/auth_client.py +257 -0
- package/extensions/services/proxy/agentcp/base/client.py +112 -0
- package/extensions/services/proxy/agentcp/base/env.py +34 -0
- package/extensions/services/proxy/agentcp/base/html_util.py +336 -0
- package/extensions/services/proxy/agentcp/base/log.py +98 -0
- package/extensions/services/proxy/agentcp/ca/__init__.py +17 -0
- package/extensions/services/proxy/agentcp/ca/ca_client.py +414 -0
- package/extensions/services/proxy/agentcp/ca/ca_root.py +74 -0
- package/extensions/services/proxy/agentcp/context/__init__.py +20 -0
- package/extensions/services/proxy/agentcp/context/context.py +73 -0
- package/extensions/services/proxy/agentcp/context/exceptions.py +114 -0
- package/extensions/services/proxy/agentcp/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/create_profile_weather.py +125 -0
- package/extensions/services/proxy/agentcp/db/__init__.py +15 -0
- package/extensions/services/proxy/agentcp/db/db_mananger.py +550 -0
- package/extensions/services/proxy/agentcp/docs/UDP_HEARTBEAT_FIX_REPORT.md +265 -0
- package/extensions/services/proxy/agentcp/docs/heartbeat_issue_analysis.md +291 -0
- package/extensions/services/proxy/agentcp/file/__init__.py +16 -0
- package/extensions/services/proxy/agentcp/file/file_client.py +141 -0
- package/extensions/services/proxy/agentcp/file/wss_binary_message.py +137 -0
- package/extensions/services/proxy/agentcp/hcp.py +299 -0
- package/extensions/services/proxy/agentcp/heartbeat/__init__.py +16 -0
- package/extensions/services/proxy/agentcp/heartbeat/heartbeat_client.py +360 -0
- package/extensions/services/proxy/agentcp/improved_scheduler.py +498 -0
- package/extensions/services/proxy/agentcp/llm_agent_utils.py +249 -0
- package/extensions/services/proxy/agentcp/llm_server.py +172 -0
- package/extensions/services/proxy/agentcp/mermaid.py +210 -0
- package/extensions/services/proxy/agentcp/message.py +149 -0
- package/extensions/services/proxy/agentcp/metrics.py +256 -0
- package/extensions/services/proxy/agentcp/monitoring/__init__.py +20 -0
- package/extensions/services/proxy/agentcp/monitoring/global_monitor.py +27 -0
- package/extensions/services/proxy/agentcp/monitoring/metrics_store.py +325 -0
- package/extensions/services/proxy/agentcp/monitoring/monitoring_service.py +269 -0
- package/extensions/services/proxy/agentcp/monitoring/sliding_window.py +222 -0
- package/extensions/services/proxy/agentcp/monitoring/standalone_reader.py +224 -0
- package/extensions/services/proxy/agentcp/msg/__init__.py +21 -0
- package/extensions/services/proxy/agentcp/msg/connection_manager.py +456 -0
- package/extensions/services/proxy/agentcp/msg/message_client.py +2058 -0
- package/extensions/services/proxy/agentcp/msg/message_serialize.py +263 -0
- package/extensions/services/proxy/agentcp/msg/open_ai_message.py +88 -0
- package/extensions/services/proxy/agentcp/msg/session_manager.py +1062 -0
- package/extensions/services/proxy/agentcp/msg/stream_client.py +267 -0
- package/extensions/services/proxy/agentcp/msg/websocket_file_receiver.py +89 -0
- package/extensions/services/proxy/agentcp/msg/ws_logger.py +685 -0
- package/extensions/services/proxy/agentcp/msg/wss_binary_message.py +137 -0
- package/extensions/services/proxy/agentcp/requirements.txt +7 -0
- package/extensions/services/proxy/agentcp/samples/agent_graph/README.md +37 -0
- package/extensions/services/proxy/agentcp/samples/agent_graph/agentprofile.json +89 -0
- package/extensions/services/proxy/agentcp/samples/agent_graph/create_profile.py +138 -0
- package/extensions/services/proxy/agentcp/samples/agent_graph/main.py +164 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/create_profile.py +123 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/llm/create_profile.py +129 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/llm/env.json +5 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/llm/main.py +146 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/main.py +123 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/readme.md +379 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/search/create_profile.py +129 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/search/main.py +28 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/tool/create_profile.py +129 -0
- package/extensions/services/proxy/agentcp/samples/agent_use/tool/main.py +20 -0
- package/extensions/services/proxy/agentcp/samples/ali_amap/README.md +97 -0
- package/extensions/services/proxy/agentcp/samples/ali_amap/amap_agent.py +88 -0
- package/extensions/services/proxy/agentcp/samples/ali_amap/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/compute_agent/agent/powershell.py +228 -0
- package/extensions/services/proxy/agentcp/samples/compute_agent/agent/software.py +63 -0
- package/extensions/services/proxy/agentcp/samples/compute_agent/agent/tools.py +36 -0
- package/extensions/services/proxy/agentcp/samples/compute_agent/browser_user.py +41 -0
- package/extensions/services/proxy/agentcp/samples/deepseek/README.md +79 -0
- package/extensions/services/proxy/agentcp/samples/deepseek/create_profile.py +126 -0
- package/extensions/services/proxy/agentcp/samples/deepseek/deepseek.py +42 -0
- package/extensions/services/proxy/agentcp/samples/dify_chat/README.md +78 -0
- package/extensions/services/proxy/agentcp/samples/dify_chat/create_profile.py +126 -0
- package/extensions/services/proxy/agentcp/samples/dify_chat/dify_chat.py +47 -0
- package/extensions/services/proxy/agentcp/samples/dify_workflow/README.md +78 -0
- package/extensions/services/proxy/agentcp/samples/dify_workflow/create_profile.py +126 -0
- package/extensions/services/proxy/agentcp/samples/dify_workflow/dify_workflow.py +46 -0
- package/extensions/services/proxy/agentcp/samples/executor/README.md +44 -0
- package/extensions/services/proxy/agentcp/samples/executor/agentprofile.json +89 -0
- package/extensions/services/proxy/agentcp/samples/executor/create_profile.py +139 -0
- package/extensions/services/proxy/agentcp/samples/executor/main.py +160 -0
- package/extensions/services/proxy/agentcp/samples/filereader/README.md +45 -0
- package/extensions/services/proxy/agentcp/samples/filereader/agentprofile.json +90 -0
- package/extensions/services/proxy/agentcp/samples/filereader/create_profile.py +137 -0
- package/extensions/services/proxy/agentcp/samples/filereader/main.py +253 -0
- package/extensions/services/proxy/agentcp/samples/filewriter/README.md +38 -0
- package/extensions/services/proxy/agentcp/samples/filewriter/agentprofile.json +91 -0
- package/extensions/services/proxy/agentcp/samples/filewriter/create_profile.py +138 -0
- package/extensions/services/proxy/agentcp/samples/filewriter/main.py +289 -0
- package/extensions/services/proxy/agentcp/samples/hcp/README.md +85 -0
- package/extensions/services/proxy/agentcp/samples/hcp/acp_weather_agent.zip +0 -0
- package/extensions/services/proxy/agentcp/samples/hcp/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/hcp/hcp.py +237 -0
- package/extensions/services/proxy/agentcp/samples/helloworld/README.md +68 -0
- package/extensions/services/proxy/agentcp/samples/helloworld/hello_world.py +40 -0
- package/extensions/services/proxy/agentcp/samples/llm_agent/MEADME.md +117 -0
- package/extensions/services/proxy/agentcp/samples/llm_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/llm_agent/qwen_agent.py +136 -0
- package/extensions/services/proxy/agentcp/samples/local_llm_agent/README.md +90 -0
- package/extensions/services/proxy/agentcp/samples/local_llm_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/local_llm_agent/main.py +49 -0
- package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/README.md +55 -0
- package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/main.py +23 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/README.md +103 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/main.py +69 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/README.md +58 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/main.py +25 -0
- package/extensions/services/proxy/agentcp/samples/qwen3/README.md +71 -0
- package/extensions/services/proxy/agentcp/samples/qwen3/create_profile.py +126 -0
- package/extensions/services/proxy/agentcp/samples/qwen3/qwen3.py +37 -0
- package/extensions/services/proxy/agentcp/samples/qwen3_tools/README.md +133 -0
- package/extensions/services/proxy/agentcp/samples/qwen3_tools/create_profile.py +126 -0
- package/extensions/services/proxy/agentcp/samples/qwen3_tools/qwen3_tools.py +98 -0
- package/extensions/services/proxy/agentcp/samples/search/create_profile_qwen.py +125 -0
- package/extensions/services/proxy/agentcp/samples/search/create_profile_search.py +125 -0
- package/extensions/services/proxy/agentcp/samples/search/qwen_agent.py +136 -0
- package/extensions/services/proxy/agentcp/samples/search/search_agent.py +170 -0
- package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/README.md +89 -0
- package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/create_profile.py +125 -0
- package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/main.py +44 -0
- package/extensions/services/proxy/agentcp/utils/__init__.py +15 -0
- package/extensions/services/proxy/agentcp/utils/file_util.py +117 -0
- package/extensions/services/proxy/agentcp/utils/proxy_bypass.py +99 -0
- package/extensions/services/proxy/agentcp/workflow.py +203 -0
- package/extensions/services/proxy/console_auth.py +109 -0
- package/extensions/services/proxy/evol/__init__.py +1 -0
- package/extensions/services/proxy/evol/config.py +37 -0
- package/extensions/services/proxy/evol/http/__init__.py +1 -0
- package/extensions/services/proxy/evol/http/async_http.py +551 -0
- package/extensions/services/proxy/evol/log.py +28 -0
- package/extensions/services/proxy/evol/presenter/__init__.py +2 -0
- package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +1031 -0
- package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +106 -0
- package/extensions/services/proxy/evol/presenter/configPresenter.py +1281 -0
- package/extensions/services/proxy/evol/presenter/userPresenter.py +477 -0
- package/extensions/services/proxy/evol/server/__init__.py +1 -0
- package/extensions/services/proxy/evol/server/claude_proxy_async.py +3430 -0
- package/extensions/services/proxy/evol/server/openclaw_proxy.py +1861 -0
- package/extensions/services/proxy/evol/server/proxy_config.py +15 -0
- package/extensions/services/proxy/evol/server/proxy_engine.py +501 -0
- package/extensions/services/proxy/evol/version.py +24 -0
- package/extensions/services/proxy/logs/websocket.log +260 -0
- package/extensions/services/proxy/main.py +240 -0
- package/extensions/services/proxy/requirements.txt +13 -0
- package/extensions/services/proxy/server.py +271 -0
- package/extensions/services/watchdog/entry.py +215 -26
- package/extensions/services/watchdog/module.md +1 -0
- package/extensions/services/watchdog/monitor.py +178 -38
- package/extensions/services/web/WEBSOCKET_STATUS.md +143 -0
- package/extensions/services/web/config_example.py +35 -0
- package/extensions/services/web/config_loader.py +110 -0
- package/extensions/services/web/entry.py +114 -26
- package/extensions/services/web/module.md +35 -24
- package/extensions/services/web/pairing.py +250 -0
- package/extensions/services/web/pairing_codes.jsonl +16 -0
- package/extensions/services/web/relay.py +643 -0
- package/extensions/services/web/relay_config.json5 +67 -0
- package/extensions/services/web/routes/routes_management_ws.py +127 -0
- package/extensions/services/web/routes/routes_rpc.py +89 -0
- package/extensions/services/web/routes/routes_test.py +61 -0
- package/extensions/services/web/routes/schemas.py +0 -22
- package/extensions/services/web/server.py +434 -99
- package/extensions/services/web/static/css/style.css +67 -28
- package/extensions/services/web/static/index.html +234 -44
- package/extensions/services/web/static/js/app.js +1335 -48
- package/extensions/services/web/static/js/kernel-client-example.js +161 -0
- package/extensions/services/web/static/js/kernel-client.js +383 -0
- package/extensions/services/web/static/js/registry-tests.js +558 -0
- package/extensions/services/web/static/js/token-manager.js +175 -0
- package/extensions/services/web/static/pairing.html +248 -0
- package/extensions/services/web/static/test_registry.html +262 -0
- package/extensions/services/web/web_config.json5 +29 -0
- package/kernel/entry.py +120 -32
- package/kernel/event_hub.py +141 -16
- package/kernel/module.md +60 -33
- package/kernel/registry_store.py +45 -36
- package/kernel/rpc_router.py +152 -59
- package/kernel/server.py +322 -26
- package/kite_cli/__init__.py +3 -0
- package/kite_cli/__main__.py +5 -0
- package/kite_cli/commands/__init__.py +1 -0
- package/kite_cli/commands/clean.py +101 -0
- package/kite_cli/commands/deps_install.py +67 -0
- package/kite_cli/commands/doctor.py +35 -0
- package/kite_cli/commands/env_check.py +45 -0
- package/kite_cli/commands/history.py +111 -0
- package/kite_cli/commands/info.py +96 -0
- package/kite_cli/commands/install.py +313 -0
- package/kite_cli/commands/list.py +143 -0
- package/kite_cli/commands/log.py +81 -0
- package/kite_cli/commands/prepare.py +49 -0
- package/kite_cli/commands/rollback.py +88 -0
- package/kite_cli/commands/search.py +73 -0
- package/kite_cli/commands/uninstall.py +85 -0
- package/kite_cli/commands/update.py +118 -0
- package/kite_cli/commands/venv_setup.py +56 -0
- package/kite_cli/core/__init__.py +1 -0
- package/kite_cli/core/checker.py +142 -0
- package/kite_cli/core/dependency.py +229 -0
- package/kite_cli/core/downloader.py +209 -0
- package/kite_cli/core/install_info.py +40 -0
- package/kite_cli/core/tool_installer.py +397 -0
- package/kite_cli/core/validator.py +78 -0
- package/kite_cli/main.py +317 -0
- package/kite_cli/utils/__init__.py +1 -0
- package/kite_cli/utils/i18n.py +252 -0
- package/kite_cli/utils/interactive.py +63 -0
- package/kite_cli/utils/operation_log.py +77 -0
- package/kite_cli/utils/paths.py +34 -0
- package/kite_cli/utils/version.py +308 -0
- package/launcher/entry.py +1124 -178
- package/launcher/logging_setup.py +104 -0
- package/launcher/module.md +46 -37
- package/launcher/module_scanner.py +11 -1
- package/main.py +4 -1
- package/package.json +9 -1
- package/python_version.json +4 -0
- package/requirements.txt +38 -0
- package/scripts/env-manager.js +328 -0
- package/scripts/plan_manager.py +315 -0
- package/scripts/python-env.js +79 -0
- package/scripts/scan_dependencies.py +461 -0
- package/scripts/setup-python-env.js +191 -0
- package/extensions/services/web/routes/routes_modules.py +0 -249
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
// 中转服务配置
|
|
3
|
+
relay: {
|
|
4
|
+
// 基础模块 ID(实际 module_id 会加上 session 后缀)
|
|
5
|
+
base_module_id: "evol-client",
|
|
6
|
+
|
|
7
|
+
// 重连超时时间(秒)
|
|
8
|
+
// 前端刷新页面或短暂断网时,中转服务保持 Kernel 连接的时长
|
|
9
|
+
reconnect_timeout: 6,
|
|
10
|
+
|
|
11
|
+
// WebSocket 端点路径
|
|
12
|
+
endpoint: "/ws/relay"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// 认证配置
|
|
16
|
+
auth: {
|
|
17
|
+
// frontend_token 有效期(秒,30天)
|
|
18
|
+
token_expiry: 2592000,
|
|
19
|
+
|
|
20
|
+
// token 续期阈值(秒,7天)
|
|
21
|
+
// 当 token 剩余有效期小于此值时,自动续期
|
|
22
|
+
token_renew_threshold: 604800,
|
|
23
|
+
|
|
24
|
+
// 配对码长度
|
|
25
|
+
pairing_code_length: 6,
|
|
26
|
+
|
|
27
|
+
// 配对码文件路径(相对于模块数据目录)
|
|
28
|
+
pairing_code_file: "pairing_codes.jsonl"
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// 权限配置(基于角色的 RPC 白名单)
|
|
32
|
+
permissions: {
|
|
33
|
+
// 管理员角色 - 完全权限
|
|
34
|
+
admin: [
|
|
35
|
+
"event.*", // 事件订阅(必需)
|
|
36
|
+
"registry.*", // 注册表查询(必需)
|
|
37
|
+
"launcher.*", // 所有 launcher RPC
|
|
38
|
+
"kernel.health", // Kernel 健康检查
|
|
39
|
+
"kernel.stats", // Kernel 统计信息
|
|
40
|
+
"*.health", // 所有模块的健康检查
|
|
41
|
+
"*.status", // 所有模块的状态查询
|
|
42
|
+
"watchdog.*", // Watchdog 相关
|
|
43
|
+
"backup.*", // Backup 相关
|
|
44
|
+
"model_service.*", // Model Service 相关
|
|
45
|
+
"web.*" // Web 管理相关(token 管理等)
|
|
46
|
+
],
|
|
47
|
+
|
|
48
|
+
// 操作员角色 - 模块管理权限
|
|
49
|
+
operator: [
|
|
50
|
+
"event.*", // 事件订阅(必需)
|
|
51
|
+
"launcher.list_modules",
|
|
52
|
+
"launcher.start_module",
|
|
53
|
+
"launcher.stop_module",
|
|
54
|
+
"launcher.restart_module",
|
|
55
|
+
"*.health",
|
|
56
|
+
"*.status"
|
|
57
|
+
],
|
|
58
|
+
|
|
59
|
+
// 查看者角色 - 只读权限
|
|
60
|
+
viewer: [
|
|
61
|
+
"event.*", // 事件订阅(必需)
|
|
62
|
+
"launcher.list_modules",
|
|
63
|
+
"*.health",
|
|
64
|
+
"*.status"
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Management WebSocket — 实时推送模块状态变更到前端管理页面"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
from datetime import datetime, timezone
|
|
9
|
+
|
|
10
|
+
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
router = APIRouter()
|
|
15
|
+
|
|
16
|
+
# 全局连接池 — 所有连接的管理客户端
|
|
17
|
+
_management_clients: set[WebSocket] = set()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@router.websocket("/ws/management")
|
|
21
|
+
async def management_websocket(ws: WebSocket):
|
|
22
|
+
"""
|
|
23
|
+
管理后台实时状态推送 WebSocket.
|
|
24
|
+
|
|
25
|
+
前端连接后会收到:
|
|
26
|
+
- 初始 connected 消息
|
|
27
|
+
- 模块状态变更事件(module.started, module.stopped, module.crashed 等)
|
|
28
|
+
- 健康检查结果(module.health)
|
|
29
|
+
- Kernel 连接状态(module.connected, module.registered)
|
|
30
|
+
"""
|
|
31
|
+
await ws.accept()
|
|
32
|
+
_management_clients.add(ws)
|
|
33
|
+
client_id = id(ws)
|
|
34
|
+
logger.info(f"Management WS: client connected (id={client_id}, total={len(_management_clients)})")
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
# 发送初始连接确认
|
|
38
|
+
await ws.send_json({
|
|
39
|
+
"type": "connected",
|
|
40
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
# 保持连接,接收心跳和客户端消息
|
|
44
|
+
while True:
|
|
45
|
+
try:
|
|
46
|
+
raw = await asyncio.wait_for(ws.receive_text(), timeout=60.0)
|
|
47
|
+
msg = json.loads(raw)
|
|
48
|
+
|
|
49
|
+
# 心跳响应
|
|
50
|
+
if msg.get("type") == "ping":
|
|
51
|
+
await ws.send_json({
|
|
52
|
+
"type": "pong",
|
|
53
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
except asyncio.TimeoutError:
|
|
57
|
+
# 60 秒无消息,发送 ping 检测连接
|
|
58
|
+
try:
|
|
59
|
+
await ws.send_json({"type": "ping"})
|
|
60
|
+
except Exception:
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
except WebSocketDisconnect:
|
|
64
|
+
logger.info(f"Management WS: client disconnected (id={client_id})")
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.warning(f"Management WS: client error (id={client_id}): {e}")
|
|
67
|
+
finally:
|
|
68
|
+
_management_clients.discard(ws)
|
|
69
|
+
logger.info(f"Management WS: client removed (id={client_id}, remaining={len(_management_clients)})")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
async def broadcast_event(event_type: str, data: dict):
|
|
73
|
+
"""
|
|
74
|
+
广播事件到所有连接的管理客户端.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
event_type: 事件类型(如 module.started, module.stopped)
|
|
78
|
+
data: 事件数据(通常包含 module_id 等字段)
|
|
79
|
+
"""
|
|
80
|
+
if not _management_clients:
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
message = {
|
|
84
|
+
"type": event_type,
|
|
85
|
+
"data": data,
|
|
86
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
message_str = json.dumps(message)
|
|
90
|
+
dead_clients = []
|
|
91
|
+
|
|
92
|
+
# 并发发送到所有客户端
|
|
93
|
+
for ws in list(_management_clients):
|
|
94
|
+
try:
|
|
95
|
+
await ws.send_text(message_str)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
logger.debug(f"Management WS: failed to send to client {id(ws)}: {e}")
|
|
98
|
+
dead_clients.append(ws)
|
|
99
|
+
|
|
100
|
+
# 清理失败的连接
|
|
101
|
+
for ws in dead_clients:
|
|
102
|
+
_management_clients.discard(ws)
|
|
103
|
+
|
|
104
|
+
if dead_clients:
|
|
105
|
+
logger.info(f"Management WS: removed {len(dead_clients)} dead clients, remaining={len(_management_clients)}")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_client_count() -> int:
|
|
109
|
+
"""返回当前连接的管理客户端数量"""
|
|
110
|
+
return len(_management_clients)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
async def close_all_clients():
|
|
114
|
+
"""优雅关闭所有管理客户端(用于 shutdown)"""
|
|
115
|
+
if not _management_clients:
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
logger.info(f"Management WS: closing {len(_management_clients)} clients...")
|
|
119
|
+
|
|
120
|
+
for ws in list(_management_clients):
|
|
121
|
+
try:
|
|
122
|
+
await ws.close(code=1001, reason="Server shutting down")
|
|
123
|
+
except Exception as e:
|
|
124
|
+
logger.debug(f"Management WS: error closing client {id(ws)}: {e}")
|
|
125
|
+
|
|
126
|
+
_management_clients.clear()
|
|
127
|
+
logger.info("Management WS: all clients closed")
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""RPC forwarding routes — forward HTTP requests to Kernel RPC."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
import logging
|
|
8
|
+
import uuid
|
|
9
|
+
|
|
10
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
router = APIRouter(tags=["rpc"])
|
|
15
|
+
|
|
16
|
+
# Global reference to EvolServer instance (set by server.py)
|
|
17
|
+
_evol_server = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def set_evol_server(server):
|
|
21
|
+
"""Set the EvolServer instance for RPC forwarding."""
|
|
22
|
+
global _evol_server
|
|
23
|
+
_evol_server = server
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@router.post("/rpc/{method:path}")
|
|
27
|
+
async def forward_rpc(method: str, request: Request):
|
|
28
|
+
"""
|
|
29
|
+
Forward RPC call to Kernel via WebSocket.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
POST /api/rpc/launcher.start_module
|
|
33
|
+
Body: {"name": "watchdog"}
|
|
34
|
+
"""
|
|
35
|
+
if not _evol_server:
|
|
36
|
+
raise HTTPException(503, "Evol 模块未初始化")
|
|
37
|
+
|
|
38
|
+
if not _evol_server._ws:
|
|
39
|
+
raise HTTPException(503, "Evol 模块未连接到 Kernel,请检查 Kernel 是否正常运行")
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
body = await request.json()
|
|
43
|
+
except Exception:
|
|
44
|
+
body = {}
|
|
45
|
+
|
|
46
|
+
# Generate unique request ID
|
|
47
|
+
rpc_id = str(uuid.uuid4())
|
|
48
|
+
|
|
49
|
+
# Create RPC request
|
|
50
|
+
rpc_request = {
|
|
51
|
+
"jsonrpc": "2.0",
|
|
52
|
+
"id": rpc_id,
|
|
53
|
+
"method": method,
|
|
54
|
+
"params": body,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Create a future to wait for response
|
|
58
|
+
response_future = asyncio.Future()
|
|
59
|
+
|
|
60
|
+
# Store the future in a dict (keyed by rpc_id)
|
|
61
|
+
if not hasattr(_evol_server, '_rpc_futures'):
|
|
62
|
+
_evol_server._rpc_futures = {}
|
|
63
|
+
_evol_server._rpc_futures[rpc_id] = response_future
|
|
64
|
+
|
|
65
|
+
# Send RPC request
|
|
66
|
+
try:
|
|
67
|
+
await _evol_server._ws.send(json.dumps(rpc_request))
|
|
68
|
+
except Exception as e:
|
|
69
|
+
_evol_server._rpc_futures.pop(rpc_id, None)
|
|
70
|
+
raise HTTPException(503, f"发送 RPC 请求失败: {str(e)}")
|
|
71
|
+
|
|
72
|
+
# Wait for response (with timeout)
|
|
73
|
+
try:
|
|
74
|
+
response = await asyncio.wait_for(response_future, timeout=30.0)
|
|
75
|
+
except asyncio.TimeoutError:
|
|
76
|
+
_evol_server._rpc_futures.pop(rpc_id, None)
|
|
77
|
+
raise HTTPException(504, f"RPC 请求超时(30秒),目标服务可能未响应")
|
|
78
|
+
finally:
|
|
79
|
+
_evol_server._rpc_futures.pop(rpc_id, None)
|
|
80
|
+
|
|
81
|
+
# Check for RPC error
|
|
82
|
+
if "error" in response:
|
|
83
|
+
error = response["error"]
|
|
84
|
+
error_msg = error.get('message', '未知错误')
|
|
85
|
+
error_code = error.get('code', -1)
|
|
86
|
+
raise HTTPException(500, f"RPC 调用失败: {error_msg} (code: {error_code})")
|
|
87
|
+
|
|
88
|
+
# Return result
|
|
89
|
+
return response.get("result", {})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
测试日志 API 路由
|
|
3
|
+
"""
|
|
4
|
+
import os
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from fastapi import APIRouter, HTTPException
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
router = APIRouter()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestLogRequest(BaseModel):
|
|
14
|
+
"""测试日志请求"""
|
|
15
|
+
content: str
|
|
16
|
+
test_name: str = "registry_test"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@router.post("/save_test_log")
|
|
20
|
+
async def save_test_log(req: TestLogRequest):
|
|
21
|
+
"""
|
|
22
|
+
保存测试日志到服务器
|
|
23
|
+
|
|
24
|
+
日志保存路径: {KITE_MODULE_DATA}/log/registry_test.log (每次覆盖)
|
|
25
|
+
"""
|
|
26
|
+
try:
|
|
27
|
+
# 获取模块数据目录
|
|
28
|
+
module_data = os.environ.get("KITE_MODULE_DATA")
|
|
29
|
+
if not module_data:
|
|
30
|
+
raise HTTPException(status_code=500, detail="KITE_MODULE_DATA not set")
|
|
31
|
+
|
|
32
|
+
# 日志保存到 log 目录(与 latest.log 同级)
|
|
33
|
+
log_dir = Path(module_data) / "log"
|
|
34
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
35
|
+
|
|
36
|
+
# 固定文件名,每次覆盖
|
|
37
|
+
log_file = log_dir / "registry_test.log"
|
|
38
|
+
|
|
39
|
+
# 写入日志(覆盖模式)
|
|
40
|
+
now = datetime.now()
|
|
41
|
+
with open(log_file, "w", encoding="utf-8") as f:
|
|
42
|
+
f.write(f"# Kite 注册中心测试日志\n")
|
|
43
|
+
f.write(f"# 测试时间: {now.isoformat()}\n")
|
|
44
|
+
f.write(f"# {'=' * 70}\n\n")
|
|
45
|
+
f.write(req.content)
|
|
46
|
+
|
|
47
|
+
# 输出到控制台(会被 Launcher 捕获)
|
|
48
|
+
print(f"\n{'=' * 70}")
|
|
49
|
+
print(f"[evol] 测试日志已保存")
|
|
50
|
+
print(f"[evol] 路径: {log_file}")
|
|
51
|
+
print(f"[evol] 时间: {now.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
52
|
+
print(f"{'=' * 70}\n")
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"success": True,
|
|
56
|
+
"log_path": str(log_file),
|
|
57
|
+
"timestamp": now.isoformat()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
raise HTTPException(status_code=500, detail=f"Failed to save log: {str(e)}")
|