@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.
- package/CHANGELOG.md +102 -0
- package/cli.js +44 -5
- package/core/dependency_checker.py +250 -0
- package/core/env_checker.py +490 -0
- package/dependencies_lock.json +128 -0
- package/extensions/agents/assistant/server.py +33 -17
- package/extensions/channels/acp_channel/server.py +33 -17
- package/extensions/services/backup/entry.py +23 -16
- 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 +23 -1
- 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 +42 -16
- package/extensions/services/watchdog/module.md +1 -0
- package/extensions/services/watchdog/monitor.py +34 -4
- package/extensions/services/web/module.md +1 -1
- package/extensions/services/web/server.py +30 -18
- package/extensions/services/web/static/js/token-manager.js +10 -10
- package/kernel/entry.py +1 -1
- package/kernel/module.md +25 -1
- package/kernel/registry_store.py +2 -26
- package/kernel/rpc_router.py +36 -10
- package/kernel/server.py +106 -17
- package/kite_cli/commands/deps_install.py +67 -0
- package/kite_cli/commands/env_check.py +45 -0
- package/kite_cli/commands/prepare.py +49 -0
- package/kite_cli/commands/venv_setup.py +56 -0
- package/kite_cli/main.py +29 -1
- package/launcher/entry.py +306 -21
- package/launcher/module.md +9 -0
- package/launcher/module_scanner.py +11 -1
- package/main.py +4 -1
- package/package.json +8 -1
- package/python_version.json +4 -0
- package/requirements.txt +38 -0
- package/scripts/env-manager.js +328 -0
- package/scripts/python-env.js +79 -0
- package/scripts/scan_dependencies.py +461 -0
- package/scripts/setup-python-env.js +191 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,105 @@
|
|
|
1
|
+
# v1.5.0
|
|
2
|
+
|
|
3
|
+
**发布日期**:2026-03-09
|
|
4
|
+
**上一版本**:v1.4.0
|
|
5
|
+
**版本级别**:minor
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 核心变更
|
|
10
|
+
|
|
11
|
+
本次发布新增 **Evol 账户管理模块**(`extensions/services/evol/`),提供完整的 Evol AI 平台账户管理、设备配对、中转服务和 Web UI。同时新增 **环境管理系统**(`core/env_checker.py`、`scripts/env-manager.js`),实现 Python 环境自动检测、依赖安装和版本锁定,确保跨平台一致性。Kite CLI 新增 `prepare` 命令,支持依赖扫描和锁定文件生成。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 变更统计
|
|
16
|
+
|
|
17
|
+
| 类型 | 数量 | 说明 |
|
|
18
|
+
|------|------|------|
|
|
19
|
+
| 新增 | 368 | evol 模块(36 个)+ 环境管理(6 个)+ kite_cli 命令(4 个)+ 其他 |
|
|
20
|
+
| 删除 | 2 | CHANGELOG.md、package.json(版本更新) |
|
|
21
|
+
| 修改 | 21 | 核心入口、模块定义、服务实现 |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 关键变更
|
|
26
|
+
|
|
27
|
+
### 新增模块
|
|
28
|
+
|
|
29
|
+
**`extensions/services/evol/`** (36 个文件)
|
|
30
|
+
- **账户管理**:`auth_manager.py` (登录认证), `evol_api.py` (API 封装), `config_loader.py` (配置加载)
|
|
31
|
+
- **设备配对**:`pairing.py` (配对码管理), `pairing_codes.jsonl` (持久化存储), `migrate_tokens.py` (Token 迁移)
|
|
32
|
+
- **中转服务**:`relay.py` (Kernel WebSocket 中转), `relay_config.json5` (中转配置)
|
|
33
|
+
- **路由系统**:`routes_management_ws.py` (WebSocket 管理), `routes_rpc.py` (RPC 转发), `routes_test.py` (测试接口)
|
|
34
|
+
- **Web UI**:完整的前端界面(HTML/CSS/JS),支持登录、配对、中转测试
|
|
35
|
+
- **配置文件**:`config.yaml`, `evol_config.json5` (多层配置系统)
|
|
36
|
+
|
|
37
|
+
**`core/` 环境管理** (2 个文件)
|
|
38
|
+
- `env_checker.py` — Python 环境检测、依赖安装、版本验证
|
|
39
|
+
- `dependency_checker.py` — 依赖扫描和锁定文件生成
|
|
40
|
+
|
|
41
|
+
**`scripts/` 环境脚本** (4 个文件)
|
|
42
|
+
- `env-manager.js` — Node.js 环境管理器(PYTHONPATH 修复)
|
|
43
|
+
- `python-env.js` — Python 环境检测和安装
|
|
44
|
+
- `setup-python-env.js` — npm postinstall 钩子
|
|
45
|
+
- `scan_dependencies.py` — 依赖扫描工具
|
|
46
|
+
|
|
47
|
+
**`kite_cli/commands/`** (4 个文件)
|
|
48
|
+
- `prepare.py` — 打包准备命令(依赖锁定 + Python 版本记录)
|
|
49
|
+
- 其他命令增强
|
|
50
|
+
|
|
51
|
+
### 删除内容
|
|
52
|
+
|
|
53
|
+
- **`CHANGELOG.md`** — 将被新版本覆盖
|
|
54
|
+
- **`package.json`** — 版本号更新为 1.5.0
|
|
55
|
+
|
|
56
|
+
### 入口变更
|
|
57
|
+
|
|
58
|
+
**`main.py`** — 行数变化:18 行 → 21 行
|
|
59
|
+
- 新增环境检查逻辑
|
|
60
|
+
- 优化启动流程
|
|
61
|
+
|
|
62
|
+
**`cli.js`** — 新增环境管理器调用
|
|
63
|
+
- 启动前检查 Python 环境
|
|
64
|
+
- 自动修复 PYTHONPATH
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 架构演进
|
|
69
|
+
|
|
70
|
+
| 版本 | 核心模块 | CLI 命令 | 服务模块 | 包文件数 |
|
|
71
|
+
|------|---------|---------|---------|---------|
|
|
72
|
+
| v1.3.2 | 2 (kernel, launcher) | 10 | 5 | 88 |
|
|
73
|
+
| v1.4.0 | 2 (kernel, launcher) | 11 | 5 | 134 |
|
|
74
|
+
| v1.5.0 | 2 (kernel, launcher) | 12 | 6 (新增 evol) | 499 |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 设计原则
|
|
79
|
+
|
|
80
|
+
- ✅ **零共享代码依赖** — evol 模块可独立拷贝使用
|
|
81
|
+
- ✅ **跨平台兼容** — 环境管理支持 Windows/Linux/macOS
|
|
82
|
+
- ✅ **版本锁定** — `dependencies_lock.json` + `python_version.json` 确保环境一致性
|
|
83
|
+
- ✅ **自动化安装** — npm postinstall 自动检测和安装 Python 依赖
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 包信息
|
|
88
|
+
|
|
89
|
+
- **文件数**:499(+365 vs v1.4.0)
|
|
90
|
+
- **打包大小**:待验证
|
|
91
|
+
- **解压大小**:待验证
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 兼容性说明
|
|
96
|
+
|
|
97
|
+
本次发布为 minor 版本,向后兼容。新增功能不影响现有模块运行。
|
|
98
|
+
|
|
99
|
+
- ✅ CLI 接口保持兼容(`kite` 命令)
|
|
100
|
+
- ✅ Kernel WebSocket 协议保持兼容
|
|
101
|
+
- ✅ 现有模块无需修改即可运行
|
|
102
|
+
- ✅ 新增 `kite prepare` 命令,不影响现有命令
|
|
1
103
|
# v1.4.0
|
|
2
104
|
|
|
3
105
|
**发布日期**:2026-03-07
|
package/cli.js
CHANGED
|
@@ -20,6 +20,7 @@ const { spawn, execSync } = require('child_process');
|
|
|
20
20
|
const crypto = require('crypto');
|
|
21
21
|
const fs = require('fs');
|
|
22
22
|
const path = require('path');
|
|
23
|
+
const { ensureEnvironment, markEnvFailed } = require('./scripts/env-manager');
|
|
23
24
|
|
|
24
25
|
// Timestamped console.log with delta + color
|
|
25
26
|
const _origLog = console.log.bind(console);
|
|
@@ -125,7 +126,7 @@ if (args[0] === 'start') {
|
|
|
125
126
|
|
|
126
127
|
// Only execute if we have a valid working directory
|
|
127
128
|
if (fs.existsSync(path.join(cliWorkDir, 'kite_cli', '__init__.py'))) {
|
|
128
|
-
//
|
|
129
|
+
// Use system Python (env_checker will handle venv)
|
|
129
130
|
const python = process.platform === 'win32' ? 'python' : 'python3';
|
|
130
131
|
const cliArgs = ['-m', 'kite_cli', ...args];
|
|
131
132
|
const result = spawn(python, cliArgs, {
|
|
@@ -209,6 +210,13 @@ if (!fs.existsSync(path.join(versionDir, 'main.py'))) {
|
|
|
209
210
|
install();
|
|
210
211
|
}
|
|
211
212
|
|
|
213
|
+
// 环境检查和准备(Node.js 层)
|
|
214
|
+
console.log('[kite] 检查环境...');
|
|
215
|
+
if (!ensureEnvironment(versionDir)) {
|
|
216
|
+
console.error('[kite] 环境准备失败,无法启动');
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
|
|
212
220
|
const kiteCwd = cwdOverride || process.cwd();
|
|
213
221
|
|
|
214
222
|
console.log(`[kite] 版本: ${useVersion}`);
|
|
@@ -228,20 +236,51 @@ const env = {
|
|
|
228
236
|
PYTHONUTF8: '1',
|
|
229
237
|
};
|
|
230
238
|
|
|
231
|
-
|
|
239
|
+
// Use venv Python (确保使用虚拟环境)
|
|
240
|
+
const venvPath = path.join(kiteHome, 'venv');
|
|
241
|
+
const python = process.platform === 'win32'
|
|
242
|
+
? path.join(venvPath, 'Scripts', 'python.exe')
|
|
243
|
+
: path.join(venvPath, 'bin', 'python');
|
|
244
|
+
|
|
245
|
+
// 检查虚拟环境 Python 是否存在
|
|
246
|
+
if (!fs.existsSync(python)) {
|
|
247
|
+
console.error(`[kite] 虚拟环境 Python 不存在: ${python}`);
|
|
248
|
+
console.error(`[kite] 环境准备可能失败,请重新运行 kite start`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log(`[kite] Python: ${python}`);
|
|
253
|
+
|
|
232
254
|
const child = spawn(
|
|
233
255
|
python,
|
|
234
|
-
[
|
|
256
|
+
[path.join(versionDir, 'main.py'), ...pythonArgs],
|
|
235
257
|
{ cwd: versionDir, env, stdio: 'inherit' }
|
|
236
258
|
);
|
|
237
259
|
|
|
238
260
|
child.on('error', err => {
|
|
239
261
|
console.error(`[kite] 启动 Python 失败: ${err.message}`);
|
|
240
|
-
console.error(`[kite] 请确认
|
|
262
|
+
console.error(`[kite] 请确认 Python 3.8+ 已安装`);
|
|
263
|
+
console.error(`[kite] 或运行: npm install 重新准备环境`);
|
|
264
|
+
|
|
265
|
+
// 标记环境失败
|
|
266
|
+
markEnvFailed('python_launch_failed');
|
|
241
267
|
process.exit(1);
|
|
242
268
|
});
|
|
243
269
|
|
|
244
|
-
child.on('exit', code =>
|
|
270
|
+
child.on('exit', (code, signal) => {
|
|
271
|
+
// 如果是异常退出,检查是否是环境问题
|
|
272
|
+
if (code !== 0 && code !== null) {
|
|
273
|
+
console.error(`[kite] Python 进程异常退出,退出码: ${code}`);
|
|
274
|
+
|
|
275
|
+
// 常见的环境相关错误码
|
|
276
|
+
if (code === 1 || code === 127) {
|
|
277
|
+
console.error(`[kite] 可能是环境问题,下次启动将重新检查环境`);
|
|
278
|
+
markEnvFailed('python_runtime_error');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
process.exit(code ?? 0);
|
|
283
|
+
});
|
|
245
284
|
|
|
246
285
|
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
247
286
|
process.on(sig, () => child.kill(sig));
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"""
|
|
2
|
+
依赖检查和自动安装模块
|
|
3
|
+
|
|
4
|
+
在 Kite 启动前检查 requirements.txt 中的依赖是否满足,
|
|
5
|
+
不满足则自动安装到用户级虚拟环境 ~/.kite/venv/
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
import subprocess
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import List, Tuple, Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_venv_path() -> Path:
|
|
16
|
+
"""获取 Kite 虚拟环境路径"""
|
|
17
|
+
return Path.home() / ".kite" / "venv"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_site_packages_path() -> Optional[Path]:
|
|
21
|
+
"""获取虚拟环境的 site-packages 路径"""
|
|
22
|
+
venv_path = get_venv_path()
|
|
23
|
+
|
|
24
|
+
if os.name == "nt": # Windows
|
|
25
|
+
site_packages = venv_path / "Lib" / "site-packages"
|
|
26
|
+
else: # Linux / macOS
|
|
27
|
+
python_version = f"python{sys.version_info.major}.{sys.version_info.minor}"
|
|
28
|
+
site_packages = venv_path / "lib" / python_version / "site-packages"
|
|
29
|
+
|
|
30
|
+
return site_packages if site_packages.exists() else None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def activate_venv():
|
|
34
|
+
"""将虚拟环境的 site-packages 添加到 sys.path"""
|
|
35
|
+
site_packages = get_site_packages_path()
|
|
36
|
+
|
|
37
|
+
if site_packages and site_packages not in sys.path:
|
|
38
|
+
sys.path.insert(0, str(site_packages))
|
|
39
|
+
print(f"[依赖] 已激活虚拟环境: {site_packages}")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def ensure_venv_exists() -> bool:
|
|
43
|
+
"""确保虚拟环境存在,不存在则创建"""
|
|
44
|
+
venv_path = get_venv_path()
|
|
45
|
+
|
|
46
|
+
if venv_path.exists():
|
|
47
|
+
return True
|
|
48
|
+
|
|
49
|
+
print(f"[依赖] 虚拟环境不存在,正在创建: {venv_path}")
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
venv_path.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
subprocess.run(
|
|
54
|
+
[sys.executable, "-m", "venv", str(venv_path)],
|
|
55
|
+
check=True,
|
|
56
|
+
capture_output=True,
|
|
57
|
+
text=True
|
|
58
|
+
)
|
|
59
|
+
print(f"[依赖] 虚拟环境创建成功")
|
|
60
|
+
return True
|
|
61
|
+
except subprocess.CalledProcessError as e:
|
|
62
|
+
print(f"[依赖] 虚拟环境创建失败: {e.stderr}")
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_venv_pip() -> Path:
|
|
67
|
+
"""获取虚拟环境的 pip 路径"""
|
|
68
|
+
venv_path = get_venv_path()
|
|
69
|
+
|
|
70
|
+
if os.name == "nt": # Windows
|
|
71
|
+
return venv_path / "Scripts" / "pip.exe"
|
|
72
|
+
else: # Linux / macOS
|
|
73
|
+
return venv_path / "bin" / "pip"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def parse_requirements(requirements_file: Path) -> List[Tuple[str, str]]:
|
|
77
|
+
"""
|
|
78
|
+
解析 requirements.txt
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List of (package_name, version_spec) tuples
|
|
82
|
+
例如: [("fastapi", ">=0.115.0"), ("uvicorn", ">=0.32.0")]
|
|
83
|
+
"""
|
|
84
|
+
requirements = []
|
|
85
|
+
|
|
86
|
+
with open(requirements_file, "r", encoding="utf-8") as f:
|
|
87
|
+
for line in f:
|
|
88
|
+
line = line.strip()
|
|
89
|
+
|
|
90
|
+
# 跳过注释和空行
|
|
91
|
+
if not line or line.startswith("#"):
|
|
92
|
+
continue
|
|
93
|
+
|
|
94
|
+
# 解析包名和版本
|
|
95
|
+
if ">=" in line:
|
|
96
|
+
package, version = line.split(">=", 1)
|
|
97
|
+
requirements.append((package.strip(), f">={version.strip()}"))
|
|
98
|
+
elif "==" in line:
|
|
99
|
+
package, version = line.split("==", 1)
|
|
100
|
+
requirements.append((package.strip(), f"=={version.strip()}"))
|
|
101
|
+
else:
|
|
102
|
+
requirements.append((line.strip(), ""))
|
|
103
|
+
|
|
104
|
+
return requirements
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def check_package_installed(package_name: str, version_spec: str) -> bool:
|
|
108
|
+
"""
|
|
109
|
+
检查包是否已安装且版本满足要求
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
package_name: 包名
|
|
113
|
+
version_spec: 版本要求,如 ">=0.115.0"
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
True if installed and version matches, False otherwise
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
import importlib.metadata
|
|
120
|
+
|
|
121
|
+
# 检查包是否存在
|
|
122
|
+
try:
|
|
123
|
+
installed_version = importlib.metadata.version(package_name)
|
|
124
|
+
except importlib.metadata.PackageNotFoundError:
|
|
125
|
+
return False
|
|
126
|
+
|
|
127
|
+
# 如果没有版本要求,只要安装了就行
|
|
128
|
+
if not version_spec:
|
|
129
|
+
return True
|
|
130
|
+
|
|
131
|
+
# 简单的版本比较(只支持 >= 和 ==)
|
|
132
|
+
if version_spec.startswith(">="):
|
|
133
|
+
required_version = version_spec[2:].strip()
|
|
134
|
+
return _version_gte(installed_version, required_version)
|
|
135
|
+
elif version_spec.startswith("=="):
|
|
136
|
+
required_version = version_spec[2:].strip()
|
|
137
|
+
return installed_version == required_version
|
|
138
|
+
|
|
139
|
+
return True
|
|
140
|
+
|
|
141
|
+
except Exception as e:
|
|
142
|
+
print(f"[依赖] 检查包 {package_name} 时出错: {e}")
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _version_gte(v1: str, v2: str) -> bool:
|
|
147
|
+
"""简单的版本比较:v1 >= v2"""
|
|
148
|
+
try:
|
|
149
|
+
parts1 = [int(x) for x in v1.split(".")[:3]]
|
|
150
|
+
parts2 = [int(x) for x in v2.split(".")[:3]]
|
|
151
|
+
|
|
152
|
+
# 补齐到 3 位
|
|
153
|
+
while len(parts1) < 3:
|
|
154
|
+
parts1.append(0)
|
|
155
|
+
while len(parts2) < 3:
|
|
156
|
+
parts2.append(0)
|
|
157
|
+
|
|
158
|
+
return parts1 >= parts2
|
|
159
|
+
except:
|
|
160
|
+
return True # 解析失败时假设满足
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def install_packages(packages: List[str]) -> bool:
|
|
164
|
+
"""
|
|
165
|
+
使用虚拟环境的 pip 安装包
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
packages: 包列表,如 ["fastapi>=0.115.0", "uvicorn>=0.32.0"]
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
True if success, False otherwise
|
|
172
|
+
"""
|
|
173
|
+
pip_path = get_venv_pip()
|
|
174
|
+
|
|
175
|
+
if not pip_path.exists():
|
|
176
|
+
print(f"[依赖] pip 不存在: {pip_path}")
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
print(f"[依赖] 正在安装 {len(packages)} 个包...")
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
# 使用 pip install 安装所有缺失的包
|
|
183
|
+
cmd = [str(pip_path), "install"] + packages
|
|
184
|
+
|
|
185
|
+
result = subprocess.run(
|
|
186
|
+
cmd,
|
|
187
|
+
check=True,
|
|
188
|
+
capture_output=True,
|
|
189
|
+
text=True
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
print(f"[依赖] 安装成功")
|
|
193
|
+
return True
|
|
194
|
+
|
|
195
|
+
except subprocess.CalledProcessError as e:
|
|
196
|
+
print(f"[依赖] 安装失败: {e.stderr}")
|
|
197
|
+
return False
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def check_and_install_dependencies(requirements_file: Path) -> bool:
|
|
201
|
+
"""
|
|
202
|
+
检查并安装依赖
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
requirements_file: requirements.txt 文件路径
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
True if all dependencies satisfied, False otherwise
|
|
209
|
+
"""
|
|
210
|
+
if not requirements_file.exists():
|
|
211
|
+
print(f"[依赖] requirements.txt 不存在: {requirements_file}")
|
|
212
|
+
return True # 没有依赖文件就跳过
|
|
213
|
+
|
|
214
|
+
# 1. 确保虚拟环境存在
|
|
215
|
+
if not ensure_venv_exists():
|
|
216
|
+
print("[依赖] 无法创建虚拟环境,跳过依赖检查")
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
# 2. 激活虚拟环境(添加到 sys.path)
|
|
220
|
+
activate_venv()
|
|
221
|
+
|
|
222
|
+
# 3. 解析 requirements.txt
|
|
223
|
+
requirements = parse_requirements(requirements_file)
|
|
224
|
+
|
|
225
|
+
if not requirements:
|
|
226
|
+
print("[依赖] requirements.txt 为空")
|
|
227
|
+
return True
|
|
228
|
+
|
|
229
|
+
# 4. 检查哪些包需要安装
|
|
230
|
+
missing_packages = []
|
|
231
|
+
|
|
232
|
+
for package_name, version_spec in requirements:
|
|
233
|
+
if not check_package_installed(package_name, version_spec):
|
|
234
|
+
spec = f"{package_name}{version_spec}" if version_spec else package_name
|
|
235
|
+
missing_packages.append(spec)
|
|
236
|
+
print(f"[依赖] 缺失: {spec}")
|
|
237
|
+
|
|
238
|
+
# 5. 如果有缺失的包,安装它们
|
|
239
|
+
if missing_packages:
|
|
240
|
+
print(f"[依赖] 发现 {len(missing_packages)} 个缺失的包,开始安装...")
|
|
241
|
+
|
|
242
|
+
if not install_packages(missing_packages):
|
|
243
|
+
print("[依赖] 安装失败,Kite 可能无法正常运行")
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
print("[依赖] 所有依赖已安装")
|
|
247
|
+
else:
|
|
248
|
+
print("[依赖] 所有依赖已满足")
|
|
249
|
+
|
|
250
|
+
return True
|