@agentunion/kite 1.3.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/cli.js +119 -4
  3. package/core/dependency_checker.py +250 -0
  4. package/core/env_checker.py +490 -0
  5. package/dependencies_lock.json +128 -0
  6. package/extensions/agents/assistant/entry.py +111 -1
  7. package/extensions/agents/assistant/server.py +279 -215
  8. package/extensions/channels/acp_channel/entry.py +111 -1
  9. package/extensions/channels/acp_channel/module.md +23 -22
  10. package/extensions/channels/acp_channel/server.py +279 -215
  11. package/extensions/event_hub_bench/entry.py +107 -1
  12. package/extensions/services/backup/entry.py +306 -21
  13. package/extensions/services/backup/module.md +24 -22
  14. package/extensions/services/evol/auth_manager.py +443 -0
  15. package/extensions/services/evol/config.yaml +149 -0
  16. package/extensions/services/evol/config_loader.py +117 -0
  17. package/extensions/services/evol/entry.py +406 -0
  18. package/extensions/services/evol/evol_api.py +173 -0
  19. package/extensions/services/evol/evol_config.json5 +29 -0
  20. package/extensions/services/evol/migrate_tokens.py +122 -0
  21. package/extensions/services/evol/module.md +32 -0
  22. package/extensions/services/evol/pairing.py +250 -0
  23. package/extensions/services/evol/pairing_codes.jsonl +1 -0
  24. package/extensions/services/evol/relay.py +682 -0
  25. package/extensions/services/evol/relay_config.json5 +67 -0
  26. package/extensions/services/evol/routes/__init__.py +1 -0
  27. package/extensions/services/evol/routes/routes_management_ws.py +127 -0
  28. package/extensions/services/evol/routes/routes_rpc.py +89 -0
  29. package/extensions/services/evol/routes/routes_test.py +61 -0
  30. package/extensions/services/evol/server.py +875 -0
  31. package/extensions/services/evol/static/css/style.css +1200 -0
  32. package/extensions/services/evol/static/index.html +781 -0
  33. package/extensions/services/evol/static/index_evol.html +14 -0
  34. package/extensions/services/evol/static/js/app.js +6304 -0
  35. package/extensions/services/evol/static/js/auth.js +326 -0
  36. package/extensions/services/evol/static/js/dialog.js +285 -0
  37. package/extensions/services/evol/static/js/evol-app-fixed.js +50 -0
  38. package/extensions/services/evol/static/js/evol-app.js +1949 -0
  39. package/extensions/services/evol/static/js/evol-app.js.bak +1800 -0
  40. package/extensions/services/evol/static/js/kernel-client-example.js +228 -0
  41. package/extensions/services/evol/static/js/kernel-client.js +396 -0
  42. package/extensions/services/evol/static/js/main.js +141 -0
  43. package/extensions/services/evol/static/js/registry-tests.js +585 -0
  44. package/extensions/services/evol/static/js/stats.js +217 -0
  45. package/extensions/services/evol/static/js/token-manager.js +175 -0
  46. package/extensions/services/evol/static/pairing.html +248 -0
  47. package/extensions/services/evol/static/test_registry.html +262 -0
  48. package/extensions/services/evol/static/test_relay.html +462 -0
  49. package/extensions/services/evol/stats_manager.py +240 -0
  50. package/extensions/services/model_service/entry.py +167 -19
  51. package/extensions/services/model_service/module.md +21 -22
  52. package/extensions/services/proxy/.claude/settings.local.json +13 -0
  53. package/extensions/services/proxy/CHANGELOG_20260308.md +258 -0
  54. package/extensions/services/proxy/_fix_prints.py +133 -0
  55. package/extensions/services/proxy/_fix_prints2.py +87 -0
  56. package/extensions/services/proxy/agentcp/LICENCE +178 -0
  57. package/extensions/services/proxy/agentcp/README copy.md +85 -0
  58. package/extensions/services/proxy/agentcp/README.md +260 -0
  59. package/extensions/services/proxy/agentcp/__init__.py +16 -0
  60. package/extensions/services/proxy/agentcp/agent.py +4 -0
  61. package/extensions/services/proxy/agentcp/agentcp.py +2494 -0
  62. package/extensions/services/proxy/agentcp/agentprofile.json +89 -0
  63. package/extensions/services/proxy/agentcp/ap/__init__.py +16 -0
  64. package/extensions/services/proxy/agentcp/ap/ap_client.py +316 -0
  65. package/extensions/services/proxy/agentcp/assets/images/wechat_qr.png +0 -0
  66. package/extensions/services/proxy/agentcp/backup/metrics.json +31 -0
  67. package/extensions/services/proxy/agentcp/base/__init__.py +20 -0
  68. package/extensions/services/proxy/agentcp/base/auth_client.py +257 -0
  69. package/extensions/services/proxy/agentcp/base/client.py +112 -0
  70. package/extensions/services/proxy/agentcp/base/env.py +34 -0
  71. package/extensions/services/proxy/agentcp/base/html_util.py +336 -0
  72. package/extensions/services/proxy/agentcp/base/log.py +98 -0
  73. package/extensions/services/proxy/agentcp/ca/__init__.py +17 -0
  74. package/extensions/services/proxy/agentcp/ca/ca_client.py +414 -0
  75. package/extensions/services/proxy/agentcp/ca/ca_root.py +74 -0
  76. package/extensions/services/proxy/agentcp/context/__init__.py +20 -0
  77. package/extensions/services/proxy/agentcp/context/context.py +73 -0
  78. package/extensions/services/proxy/agentcp/context/exceptions.py +114 -0
  79. package/extensions/services/proxy/agentcp/create_profile.py +125 -0
  80. package/extensions/services/proxy/agentcp/create_profile_weather.py +125 -0
  81. package/extensions/services/proxy/agentcp/db/__init__.py +15 -0
  82. package/extensions/services/proxy/agentcp/db/db_mananger.py +550 -0
  83. package/extensions/services/proxy/agentcp/docs/UDP_HEARTBEAT_FIX_REPORT.md +265 -0
  84. package/extensions/services/proxy/agentcp/docs/heartbeat_issue_analysis.md +291 -0
  85. package/extensions/services/proxy/agentcp/file/__init__.py +16 -0
  86. package/extensions/services/proxy/agentcp/file/file_client.py +141 -0
  87. package/extensions/services/proxy/agentcp/file/wss_binary_message.py +137 -0
  88. package/extensions/services/proxy/agentcp/hcp.py +299 -0
  89. package/extensions/services/proxy/agentcp/heartbeat/__init__.py +16 -0
  90. package/extensions/services/proxy/agentcp/heartbeat/heartbeat_client.py +360 -0
  91. package/extensions/services/proxy/agentcp/improved_scheduler.py +498 -0
  92. package/extensions/services/proxy/agentcp/llm_agent_utils.py +249 -0
  93. package/extensions/services/proxy/agentcp/llm_server.py +172 -0
  94. package/extensions/services/proxy/agentcp/mermaid.py +210 -0
  95. package/extensions/services/proxy/agentcp/message.py +149 -0
  96. package/extensions/services/proxy/agentcp/metrics.py +256 -0
  97. package/extensions/services/proxy/agentcp/monitoring/__init__.py +20 -0
  98. package/extensions/services/proxy/agentcp/monitoring/global_monitor.py +27 -0
  99. package/extensions/services/proxy/agentcp/monitoring/metrics_store.py +325 -0
  100. package/extensions/services/proxy/agentcp/monitoring/monitoring_service.py +269 -0
  101. package/extensions/services/proxy/agentcp/monitoring/sliding_window.py +222 -0
  102. package/extensions/services/proxy/agentcp/monitoring/standalone_reader.py +224 -0
  103. package/extensions/services/proxy/agentcp/msg/__init__.py +21 -0
  104. package/extensions/services/proxy/agentcp/msg/connection_manager.py +456 -0
  105. package/extensions/services/proxy/agentcp/msg/message_client.py +2058 -0
  106. package/extensions/services/proxy/agentcp/msg/message_serialize.py +263 -0
  107. package/extensions/services/proxy/agentcp/msg/open_ai_message.py +88 -0
  108. package/extensions/services/proxy/agentcp/msg/session_manager.py +1062 -0
  109. package/extensions/services/proxy/agentcp/msg/stream_client.py +267 -0
  110. package/extensions/services/proxy/agentcp/msg/websocket_file_receiver.py +89 -0
  111. package/extensions/services/proxy/agentcp/msg/ws_logger.py +685 -0
  112. package/extensions/services/proxy/agentcp/msg/wss_binary_message.py +137 -0
  113. package/extensions/services/proxy/agentcp/requirements.txt +7 -0
  114. package/extensions/services/proxy/agentcp/samples/agent_graph/README.md +37 -0
  115. package/extensions/services/proxy/agentcp/samples/agent_graph/agentprofile.json +89 -0
  116. package/extensions/services/proxy/agentcp/samples/agent_graph/create_profile.py +138 -0
  117. package/extensions/services/proxy/agentcp/samples/agent_graph/main.py +164 -0
  118. package/extensions/services/proxy/agentcp/samples/agent_use/create_profile.py +123 -0
  119. package/extensions/services/proxy/agentcp/samples/agent_use/llm/create_profile.py +129 -0
  120. package/extensions/services/proxy/agentcp/samples/agent_use/llm/env.json +5 -0
  121. package/extensions/services/proxy/agentcp/samples/agent_use/llm/main.py +146 -0
  122. package/extensions/services/proxy/agentcp/samples/agent_use/main.py +123 -0
  123. package/extensions/services/proxy/agentcp/samples/agent_use/readme.md +379 -0
  124. package/extensions/services/proxy/agentcp/samples/agent_use/search/create_profile.py +129 -0
  125. package/extensions/services/proxy/agentcp/samples/agent_use/search/main.py +28 -0
  126. package/extensions/services/proxy/agentcp/samples/agent_use/tool/create_profile.py +129 -0
  127. package/extensions/services/proxy/agentcp/samples/agent_use/tool/main.py +20 -0
  128. package/extensions/services/proxy/agentcp/samples/ali_amap/README.md +97 -0
  129. package/extensions/services/proxy/agentcp/samples/ali_amap/amap_agent.py +88 -0
  130. package/extensions/services/proxy/agentcp/samples/ali_amap/create_profile.py +125 -0
  131. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/powershell.py +228 -0
  132. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/software.py +63 -0
  133. package/extensions/services/proxy/agentcp/samples/compute_agent/agent/tools.py +36 -0
  134. package/extensions/services/proxy/agentcp/samples/compute_agent/browser_user.py +41 -0
  135. package/extensions/services/proxy/agentcp/samples/deepseek/README.md +79 -0
  136. package/extensions/services/proxy/agentcp/samples/deepseek/create_profile.py +126 -0
  137. package/extensions/services/proxy/agentcp/samples/deepseek/deepseek.py +42 -0
  138. package/extensions/services/proxy/agentcp/samples/dify_chat/README.md +78 -0
  139. package/extensions/services/proxy/agentcp/samples/dify_chat/create_profile.py +126 -0
  140. package/extensions/services/proxy/agentcp/samples/dify_chat/dify_chat.py +47 -0
  141. package/extensions/services/proxy/agentcp/samples/dify_workflow/README.md +78 -0
  142. package/extensions/services/proxy/agentcp/samples/dify_workflow/create_profile.py +126 -0
  143. package/extensions/services/proxy/agentcp/samples/dify_workflow/dify_workflow.py +46 -0
  144. package/extensions/services/proxy/agentcp/samples/executor/README.md +44 -0
  145. package/extensions/services/proxy/agentcp/samples/executor/agentprofile.json +89 -0
  146. package/extensions/services/proxy/agentcp/samples/executor/create_profile.py +139 -0
  147. package/extensions/services/proxy/agentcp/samples/executor/main.py +160 -0
  148. package/extensions/services/proxy/agentcp/samples/filereader/README.md +45 -0
  149. package/extensions/services/proxy/agentcp/samples/filereader/agentprofile.json +90 -0
  150. package/extensions/services/proxy/agentcp/samples/filereader/create_profile.py +137 -0
  151. package/extensions/services/proxy/agentcp/samples/filereader/main.py +253 -0
  152. package/extensions/services/proxy/agentcp/samples/filewriter/README.md +38 -0
  153. package/extensions/services/proxy/agentcp/samples/filewriter/agentprofile.json +91 -0
  154. package/extensions/services/proxy/agentcp/samples/filewriter/create_profile.py +138 -0
  155. package/extensions/services/proxy/agentcp/samples/filewriter/main.py +289 -0
  156. package/extensions/services/proxy/agentcp/samples/hcp/README.md +85 -0
  157. package/extensions/services/proxy/agentcp/samples/hcp/acp_weather_agent.zip +0 -0
  158. package/extensions/services/proxy/agentcp/samples/hcp/create_profile.py +125 -0
  159. package/extensions/services/proxy/agentcp/samples/hcp/hcp.py +237 -0
  160. package/extensions/services/proxy/agentcp/samples/helloworld/README.md +68 -0
  161. package/extensions/services/proxy/agentcp/samples/helloworld/hello_world.py +40 -0
  162. package/extensions/services/proxy/agentcp/samples/llm_agent/MEADME.md +117 -0
  163. package/extensions/services/proxy/agentcp/samples/llm_agent/create_profile.py +125 -0
  164. package/extensions/services/proxy/agentcp/samples/llm_agent/qwen_agent.py +136 -0
  165. package/extensions/services/proxy/agentcp/samples/local_llm_agent/README.md +90 -0
  166. package/extensions/services/proxy/agentcp/samples/local_llm_agent/create_profile.py +125 -0
  167. package/extensions/services/proxy/agentcp/samples/local_llm_agent/main.py +49 -0
  168. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/README.md +55 -0
  169. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/create_profile.py +125 -0
  170. package/extensions/services/proxy/agentcp/samples/query_llm_from_agent/main.py +23 -0
  171. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/README.md +103 -0
  172. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/create_profile.py +125 -0
  173. package/extensions/services/proxy/agentcp/samples/query_weather_api_agent/main.py +69 -0
  174. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/README.md +58 -0
  175. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/create_profile.py +125 -0
  176. package/extensions/services/proxy/agentcp/samples/query_weather_from_agent/main.py +25 -0
  177. package/extensions/services/proxy/agentcp/samples/qwen3/README.md +71 -0
  178. package/extensions/services/proxy/agentcp/samples/qwen3/create_profile.py +126 -0
  179. package/extensions/services/proxy/agentcp/samples/qwen3/qwen3.py +37 -0
  180. package/extensions/services/proxy/agentcp/samples/qwen3_tools/README.md +133 -0
  181. package/extensions/services/proxy/agentcp/samples/qwen3_tools/create_profile.py +126 -0
  182. package/extensions/services/proxy/agentcp/samples/qwen3_tools/qwen3_tools.py +98 -0
  183. package/extensions/services/proxy/agentcp/samples/search/create_profile_qwen.py +125 -0
  184. package/extensions/services/proxy/agentcp/samples/search/create_profile_search.py +125 -0
  185. package/extensions/services/proxy/agentcp/samples/search/qwen_agent.py +136 -0
  186. package/extensions/services/proxy/agentcp/samples/search/search_agent.py +170 -0
  187. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/README.md +89 -0
  188. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/create_profile.py +125 -0
  189. package/extensions/services/proxy/agentcp/samples/wrapper_agently_to_agent/main.py +44 -0
  190. package/extensions/services/proxy/agentcp/utils/__init__.py +15 -0
  191. package/extensions/services/proxy/agentcp/utils/file_util.py +117 -0
  192. package/extensions/services/proxy/agentcp/utils/proxy_bypass.py +99 -0
  193. package/extensions/services/proxy/agentcp/workflow.py +203 -0
  194. package/extensions/services/proxy/console_auth.py +109 -0
  195. package/extensions/services/proxy/evol/__init__.py +1 -0
  196. package/extensions/services/proxy/evol/config.py +37 -0
  197. package/extensions/services/proxy/evol/http/__init__.py +1 -0
  198. package/extensions/services/proxy/evol/http/async_http.py +551 -0
  199. package/extensions/services/proxy/evol/log.py +28 -0
  200. package/extensions/services/proxy/evol/presenter/__init__.py +2 -0
  201. package/extensions/services/proxy/evol/presenter/agentIdPresenter.py +1031 -0
  202. package/extensions/services/proxy/evol/presenter/apikeyPresenter.py +106 -0
  203. package/extensions/services/proxy/evol/presenter/configPresenter.py +1281 -0
  204. package/extensions/services/proxy/evol/presenter/userPresenter.py +477 -0
  205. package/extensions/services/proxy/evol/server/__init__.py +1 -0
  206. package/extensions/services/proxy/evol/server/claude_proxy_async.py +3430 -0
  207. package/extensions/services/proxy/evol/server/openclaw_proxy.py +1861 -0
  208. package/extensions/services/proxy/evol/server/proxy_config.py +15 -0
  209. package/extensions/services/proxy/evol/server/proxy_engine.py +501 -0
  210. package/extensions/services/proxy/evol/version.py +24 -0
  211. package/extensions/services/proxy/logs/websocket.log +260 -0
  212. package/extensions/services/proxy/main.py +240 -0
  213. package/extensions/services/proxy/requirements.txt +13 -0
  214. package/extensions/services/proxy/server.py +271 -0
  215. package/extensions/services/watchdog/entry.py +215 -26
  216. package/extensions/services/watchdog/module.md +1 -0
  217. package/extensions/services/watchdog/monitor.py +178 -38
  218. package/extensions/services/web/WEBSOCKET_STATUS.md +143 -0
  219. package/extensions/services/web/config_example.py +35 -0
  220. package/extensions/services/web/config_loader.py +110 -0
  221. package/extensions/services/web/entry.py +114 -26
  222. package/extensions/services/web/module.md +35 -24
  223. package/extensions/services/web/pairing.py +250 -0
  224. package/extensions/services/web/pairing_codes.jsonl +16 -0
  225. package/extensions/services/web/relay.py +643 -0
  226. package/extensions/services/web/relay_config.json5 +67 -0
  227. package/extensions/services/web/routes/routes_management_ws.py +127 -0
  228. package/extensions/services/web/routes/routes_rpc.py +89 -0
  229. package/extensions/services/web/routes/routes_test.py +61 -0
  230. package/extensions/services/web/routes/schemas.py +0 -22
  231. package/extensions/services/web/server.py +434 -99
  232. package/extensions/services/web/static/css/style.css +67 -28
  233. package/extensions/services/web/static/index.html +234 -44
  234. package/extensions/services/web/static/js/app.js +1335 -48
  235. package/extensions/services/web/static/js/kernel-client-example.js +161 -0
  236. package/extensions/services/web/static/js/kernel-client.js +383 -0
  237. package/extensions/services/web/static/js/registry-tests.js +558 -0
  238. package/extensions/services/web/static/js/token-manager.js +175 -0
  239. package/extensions/services/web/static/pairing.html +248 -0
  240. package/extensions/services/web/static/test_registry.html +262 -0
  241. package/extensions/services/web/web_config.json5 +29 -0
  242. package/kernel/entry.py +120 -32
  243. package/kernel/event_hub.py +141 -16
  244. package/kernel/module.md +60 -33
  245. package/kernel/registry_store.py +45 -36
  246. package/kernel/rpc_router.py +152 -59
  247. package/kernel/server.py +322 -26
  248. package/kite_cli/__init__.py +3 -0
  249. package/kite_cli/__main__.py +5 -0
  250. package/kite_cli/commands/__init__.py +1 -0
  251. package/kite_cli/commands/clean.py +101 -0
  252. package/kite_cli/commands/deps_install.py +67 -0
  253. package/kite_cli/commands/doctor.py +35 -0
  254. package/kite_cli/commands/env_check.py +45 -0
  255. package/kite_cli/commands/history.py +111 -0
  256. package/kite_cli/commands/info.py +96 -0
  257. package/kite_cli/commands/install.py +313 -0
  258. package/kite_cli/commands/list.py +143 -0
  259. package/kite_cli/commands/log.py +81 -0
  260. package/kite_cli/commands/prepare.py +49 -0
  261. package/kite_cli/commands/rollback.py +88 -0
  262. package/kite_cli/commands/search.py +73 -0
  263. package/kite_cli/commands/uninstall.py +85 -0
  264. package/kite_cli/commands/update.py +118 -0
  265. package/kite_cli/commands/venv_setup.py +56 -0
  266. package/kite_cli/core/__init__.py +1 -0
  267. package/kite_cli/core/checker.py +142 -0
  268. package/kite_cli/core/dependency.py +229 -0
  269. package/kite_cli/core/downloader.py +209 -0
  270. package/kite_cli/core/install_info.py +40 -0
  271. package/kite_cli/core/tool_installer.py +397 -0
  272. package/kite_cli/core/validator.py +78 -0
  273. package/kite_cli/main.py +317 -0
  274. package/kite_cli/utils/__init__.py +1 -0
  275. package/kite_cli/utils/i18n.py +252 -0
  276. package/kite_cli/utils/interactive.py +63 -0
  277. package/kite_cli/utils/operation_log.py +77 -0
  278. package/kite_cli/utils/paths.py +34 -0
  279. package/kite_cli/utils/version.py +308 -0
  280. package/launcher/entry.py +1124 -178
  281. package/launcher/logging_setup.py +104 -0
  282. package/launcher/module.md +46 -37
  283. package/launcher/module_scanner.py +11 -1
  284. package/main.py +4 -1
  285. package/package.json +9 -1
  286. package/python_version.json +4 -0
  287. package/requirements.txt +38 -0
  288. package/scripts/env-manager.js +328 -0
  289. package/scripts/plan_manager.py +315 -0
  290. package/scripts/python-env.js +79 -0
  291. package/scripts/scan_dependencies.py +461 -0
  292. package/scripts/setup-python-env.js +191 -0
  293. package/extensions/services/web/routes/routes_modules.py +0 -249
@@ -0,0 +1,45 @@
1
+ """
2
+ kite env-check 命令
3
+
4
+ 环境检查和准备:
5
+ 1. 检查虚拟环境是否存在
6
+ 2. 检查依赖库是否安装且版本一致
7
+ 3. 创建虚拟环境(如果需要)
8
+ 4. 安装依赖库(如果需要)
9
+ """
10
+
11
+ import sys
12
+ from pathlib import Path
13
+
14
+
15
+ def run_env_check(args):
16
+ """执行环境检查"""
17
+ # 导入环境检查器
18
+ project_root = Path(__file__).parent.parent.parent
19
+
20
+ # 添加到 sys.path
21
+ sys.path.insert(0, str(project_root))
22
+
23
+ # 导入并执行环境检查
24
+ from core.env_checker import check_environment
25
+
26
+ print("=" * 60)
27
+ print(" Kite 环境检查")
28
+ print("=" * 60)
29
+ print()
30
+
31
+ try:
32
+ success = check_environment()
33
+
34
+ if success:
35
+ print("\n✓ 环境检查通过")
36
+ return 0
37
+ else:
38
+ print("\n✗ 环境检查失败")
39
+ return 1
40
+
41
+ except Exception as e:
42
+ print(f"\n✗ 环境检查异常: {e}")
43
+ import traceback
44
+ traceback.print_exc()
45
+ return 1
@@ -0,0 +1,111 @@
1
+ """history 命令实现 - 显示最近安装的模块"""
2
+ from kite_cli.utils.operation_log import read_operations
3
+ from kite_cli.utils.i18n import t
4
+
5
+
6
+ def run_history(args):
7
+ """执行历史查看命令"""
8
+ limit = args.limit if hasattr(args, 'limit') else 6
9
+ show_all = args.all if hasattr(args, 'all') else False
10
+
11
+ # 读取操作日志
12
+ operations = read_operations(limit=100) # 读取更多记录用于过滤
13
+
14
+ if not operations:
15
+ print("[Info] 暂无安装记录")
16
+ return 0
17
+
18
+ # 只保留成功的 install 操作
19
+ install_ops = []
20
+ seen_modules = set() # 用于去重
21
+
22
+ for op in reversed(operations): # 从最新到最旧
23
+ if op.get("operation") == "install" and op.get("success"):
24
+ details = op.get("details", {})
25
+ module_name = details.get("module")
26
+
27
+ if not module_name:
28
+ continue
29
+
30
+ # 检查是否已被卸载(在此操作之后)
31
+ is_uninstalled = False
32
+ for later_op in operations:
33
+ if later_op.get("timestamp") > op.get("timestamp"):
34
+ if later_op.get("operation") == "uninstall" and later_op.get("success"):
35
+ uninstall_details = later_op.get("details", {})
36
+ if uninstall_details.get("module") == module_name:
37
+ is_uninstalled = True
38
+ break
39
+
40
+ # 如果 show_all=False,只显示未卸载的;如果 show_all=True,显示所有
41
+ if show_all or not is_uninstalled:
42
+ # 去重:同一个模块只显示最近一次安装
43
+ if module_name not in seen_modules:
44
+ seen_modules.add(module_name)
45
+ install_ops.append({
46
+ "timestamp": op.get("timestamp"),
47
+ "module": module_name,
48
+ "version": details.get("version", "unknown"),
49
+ "location": details.get("location", "unknown"),
50
+ "source_type": details.get("source", {}).get("type", "unknown"),
51
+ "path": details.get("path", ""),
52
+ "is_uninstalled": is_uninstalled
53
+ })
54
+
55
+ if len(install_ops) >= limit:
56
+ break
57
+
58
+ if not install_ops:
59
+ print("[Info] 暂无安装记录")
60
+ return 0
61
+
62
+ print(f"\n[History] 最近安装的 {len(install_ops)} 个模块:\n")
63
+
64
+ for i, op in enumerate(install_ops, 1):
65
+ timestamp = op["timestamp"][:19].replace("T", " ")
66
+ module = op["module"]
67
+ version = op["version"]
68
+ location = op["location"]
69
+ source_type = op["source_type"]
70
+ is_uninstalled = op["is_uninstalled"]
71
+
72
+ # 状态标记
73
+ status = "[已卸载]" if is_uninstalled else "[已安装]"
74
+
75
+ # 位置标记
76
+ location_map = {
77
+ "dev": "开发",
78
+ "local": "本地",
79
+ "global": "全局"
80
+ }
81
+ location_str = location_map.get(location, location)
82
+
83
+ print(f"{i}. {module} v{version}")
84
+ print(f" 时间: {timestamp}")
85
+ print(f" 位置: {location_str} ({location})")
86
+ print(f" 来源: {source_type}")
87
+ print(f" 状态: {status}")
88
+
89
+ # 如果未卸载,显示卸载命令
90
+ if not is_uninstalled:
91
+ print(f" 卸载: kite uninstall {module}")
92
+ if location != "global":
93
+ print(f" kite uninstall {module} -l {location}")
94
+
95
+ print()
96
+
97
+ # 显示快速卸载提示
98
+ if not show_all:
99
+ active_modules = [op["module"] for op in install_ops if not op["is_uninstalled"]]
100
+ if active_modules:
101
+ print("[Tip] 快速卸载最近安装的模块:")
102
+ for module in active_modules[:3]: # 只显示前3个
103
+ print(f" kite uninstall {module}")
104
+ print()
105
+
106
+ # 显示查看所有历史的提示
107
+ if not show_all and len(operations) > limit:
108
+ print("[Tip] 查看所有历史记录(包括已卸载): kite history --all")
109
+ print("[Tip] 查看更多记录: kite history -n 20")
110
+
111
+ return 0
@@ -0,0 +1,96 @@
1
+ """info 命令实现"""
2
+ from pathlib import Path
3
+ from kite_cli.utils.paths import get_install_path
4
+ from kite_cli.core.validator import Validator
5
+ from kite_cli.core.install_info import read_install_info
6
+ from kite_cli.utils.i18n import t
7
+
8
+
9
+ def run_info(args):
10
+ """执行 info 命令"""
11
+ module_name = args.name
12
+ location = args.location if hasattr(args, 'location') else None
13
+
14
+ print(t('module_info', name=module_name) + "\n")
15
+
16
+ # 查找模块
17
+ if location:
18
+ locations = [location]
19
+ else:
20
+ locations = find_module_locations(module_name)
21
+ if not locations:
22
+ print(t('module_not_found', name=module_name))
23
+ return 1
24
+
25
+ # 显示所有找到的位置
26
+ for loc in locations:
27
+ module_path = get_install_path(loc, module_name)
28
+ show_module_info(module_path, loc)
29
+ print()
30
+
31
+ return 0
32
+
33
+
34
+ def show_module_info(module_path: Path, location: str):
35
+ """显示模块详细信息"""
36
+ location_key = f"info_location_{location}"
37
+ location_name = t(location_key)
38
+
39
+ print(f"【{location_name}】")
40
+ print(f"{t('info_path')}: {module_path}")
41
+
42
+ # 读取 module.md
43
+ module_md = Validator.find_module_md(module_path)
44
+ if not module_md:
45
+ print(t('info_no_module_md'))
46
+ return
47
+
48
+ module_data = Validator.parse_module_md(module_md)
49
+ if not module_data:
50
+ print(t('info_parse_failed'))
51
+ return
52
+
53
+ # 基本信息
54
+ print(f"{t('info_name')}: {module_data.get('name', 'unknown')}")
55
+ print(f"{t('info_display_name')}: {module_data.get('display_name', module_data.get('name', 'unknown'))}")
56
+ print(f"{t('info_version')}: {module_data.get('version', 'unknown')}")
57
+ print(f"{t('info_type')}: {module_data.get('type', 'unknown')}")
58
+ print(f"{t('info_runtime')}: {module_data.get('runtime', 'unknown')}")
59
+ print(f"{t('info_entry')}: {module_data.get('entry', 'unknown')}")
60
+ print(f"{t('info_state')}: {module_data.get('state', 'unknown')}")
61
+
62
+ # 依赖信息
63
+ dependencies = module_data.get("dependencies", {})
64
+ if dependencies:
65
+ print(f"\n{t('info_dependencies')}:")
66
+ if dependencies.get("python"):
67
+ print(f" Python: {', '.join(dependencies['python'])}")
68
+ if dependencies.get("npm"):
69
+ print(f" npm: {', '.join(dependencies['npm'])}")
70
+ if dependencies.get("kite"):
71
+ print(f" Kite: {', '.join(dependencies['kite'])}")
72
+
73
+ # 安装信息
74
+ install_info = read_install_info(module_path)
75
+ if install_info:
76
+ print(f"\n{t('info_install_info')}:")
77
+ source = install_info.get("source", {})
78
+ print(f" {t('info_source')}: {source.get('type', 'unknown')}")
79
+ if source.get("package"):
80
+ print(f" {t('info_package')}: {source['package']}")
81
+ if source.get("url"):
82
+ print(f" {t('info_url')}: {source['url']}")
83
+ print(f" {t('info_installed_at')}: {install_info.get('installed_at', 'unknown')}")
84
+
85
+
86
+ def find_module_locations(module_name: str):
87
+ """查找模块在哪些位置存在"""
88
+ locations = []
89
+ for loc in ["dev", "local", "global"]:
90
+ try:
91
+ module_path = get_install_path(loc, module_name)
92
+ if module_path.exists():
93
+ locations.append(loc)
94
+ except Exception:
95
+ pass
96
+ return locations
@@ -0,0 +1,313 @@
1
+ """install 命令实现"""
2
+ import os
3
+ import tempfile
4
+ import shutil
5
+ from pathlib import Path
6
+ from kite_cli.core.checker import PlatformChecker
7
+ from kite_cli.core.downloader import Downloader
8
+ from kite_cli.core.validator import Validator
9
+ from kite_cli.core.dependency import DependencyInstaller
10
+ from kite_cli.core.install_info import record_install_info
11
+ from kite_cli.utils.interactive import select_source, select_location, confirm_action
12
+ from kite_cli.utils.paths import get_install_path
13
+ from kite_cli.utils.i18n import t
14
+ from kite_cli.utils.operation_log import log_operation
15
+ from kite_cli.utils.version import parse_version_spec, filter_versions, get_latest_version
16
+
17
+
18
+ def run_install(args):
19
+ """执行安装命令"""
20
+ source = args.source
21
+ location = args.location
22
+ from_platform = args.from_platform
23
+ skip_confirm = args.yes
24
+ no_deps = args.no_deps
25
+
26
+ # 如果没有指定 source,检查当前目录
27
+ if not source:
28
+ cwd = Path.cwd()
29
+ module_md = cwd / "module.md"
30
+
31
+ if module_md.exists():
32
+ print(f"[Info] 检测到当前目录包含 module.md")
33
+ source = str(cwd)
34
+ from_platform = "local"
35
+ print(f"[Info] 将安装当前目录: {source}")
36
+ else:
37
+ print("[Error] 缺少参数 <source>")
38
+ print("[Info] 请指定模块名,或在包含 module.md 的目录下执行")
39
+ print("[Info] 示例:")
40
+ print(" kite install requests # 安装 PyPI/npm 包")
41
+ print(" kite install ./my-module # 安装本地模块")
42
+ print(" kite install # 在模块目录下安装当前目录")
43
+ return 1
44
+
45
+ # 解析版本号 (如 pkg@1.2.0)
46
+ package_name, version_spec = parse_version_spec(source)
47
+
48
+ # 保留名称检查 - 防止安装 Kite 框架本身或核心组件
49
+ RESERVED_NAMES = ['kite', 'launcher', 'kernel', 'core']
50
+
51
+ # 提取模块名(去除路径、URL等)
52
+ module_name = package_name.lower().strip()
53
+ if '/' in module_name:
54
+ module_name = module_name.split('/')[-1]
55
+ if module_name.endswith('.git'):
56
+ module_name = module_name[:-4]
57
+
58
+ # 只检查完全匹配的保留名称
59
+ if module_name in RESERVED_NAMES:
60
+ print(t('reserved_name_error', name=source))
61
+ print(t('reserved_name_hint', name=module_name))
62
+ print(t('update_framework_hint'))
63
+ return 1
64
+
65
+ if version_spec:
66
+ print(t('searching_module', name=f"{package_name}@{version_spec}"))
67
+ else:
68
+ print(t('searching_module', name=package_name))
69
+
70
+ # 步骤 1: 检查各平台
71
+ if from_platform:
72
+ # 指定了平台,只检查该平台
73
+ candidates = check_single_platform(package_name, from_platform, version_spec)
74
+ else:
75
+ # 未指定平台,检查所有平台
76
+ candidates = check_all_platforms(package_name, version_spec)
77
+
78
+ if not candidates:
79
+ print(t('module_not_found', name=source))
80
+ return 1
81
+
82
+ # 步骤 2: 用户选择来源(如果有多个)
83
+ if len(candidates) > 1:
84
+ selected = select_source(candidates)
85
+ if not selected:
86
+ print("[Cancelled] 已取消")
87
+ return 1
88
+ else:
89
+ selected = candidates[0]
90
+
91
+ print(t('select_source', platform=selected['platform'], name=selected.get('name', source)))
92
+
93
+ # 步骤 3: 下载到临时目录
94
+ temp_dir = Path(tempfile.mkdtemp(prefix="kite-install-"))
95
+ try:
96
+ print(t('downloading'))
97
+ downloaded_dir, error = download_module(selected, temp_dir)
98
+ if not downloaded_dir:
99
+ print(t('download_failed'))
100
+ if error:
101
+ print(f" {error}")
102
+ return 1
103
+
104
+ print(t('download_complete', path=downloaded_dir))
105
+
106
+ # 步骤 4: 验证 module.md
107
+ print(t('validating'))
108
+
109
+ # 对于本地安装,不验证模块名,直接读取 module.md
110
+ if selected["platform"] == "local":
111
+ module_md = Validator.find_module_md(downloaded_dir)
112
+ if not module_md:
113
+ print(t('validation_failed', error="未找到 module.md"))
114
+ return 1
115
+ module_data = Validator.parse_module_md(module_md)
116
+ if not module_data or not module_data.get("name"):
117
+ print(t('validation_failed', error="无法解析 module.md 或缺少 name 字段"))
118
+ return 1
119
+ else:
120
+ # 其他平台需要验证模块名匹配
121
+ valid, error, module_data = Validator.validate_module(downloaded_dir, source)
122
+ if not valid:
123
+ print(t('validation_failed', error=error))
124
+ return 1
125
+
126
+ print(t('validation_passed', name=module_data.get('name'), version=module_data.get('version', 'unknown')))
127
+
128
+ # 步骤 5: 选择安装位置
129
+ if not location:
130
+ location = select_location()
131
+ if not location:
132
+ print("[Cancelled] 已取消")
133
+ return 1
134
+
135
+ # 步骤 6: 检查冲突
136
+ install_path = get_install_path(location, module_data['name'])
137
+ if install_path.exists():
138
+ if not skip_confirm:
139
+ if not confirm_action(f"模块 {module_data['name']} 已存在,是否覆盖?"):
140
+ print("[Cancelled] 已取消")
141
+ return 1
142
+ print("[Warning] 删除旧版本...")
143
+ shutil.rmtree(install_path)
144
+
145
+ # 步骤 7: 安装依赖
146
+ if not no_deps:
147
+ print(t('installing_deps'))
148
+ if not DependencyInstaller.install_all_deps(downloaded_dir, module_data, location, no_deps):
149
+ print(t('deps_failed'))
150
+ if not skip_confirm:
151
+ if not confirm_action("是否继续安装模块(不含依赖)?"):
152
+ return 1
153
+ else:
154
+ return 1
155
+
156
+ # 步骤 8: 复制到目标位置
157
+ print(t('installing_to', path=install_path))
158
+ install_path.parent.mkdir(parents=True, exist_ok=True)
159
+ shutil.copytree(downloaded_dir, install_path)
160
+
161
+ # 步骤 9: 记录安装信息
162
+ source_info = {
163
+ "type": selected["platform"],
164
+ "name": selected.get("name", source),
165
+ }
166
+ if selected["platform"] == "pypi":
167
+ source_info["package"] = selected["name"]
168
+ source_info["version"] = selected.get("latest")
169
+ elif selected["platform"] == "npm":
170
+ source_info["package"] = selected["name"]
171
+ source_info["version"] = selected.get("latest")
172
+ elif selected["platform"] == "git":
173
+ source_info["url"] = selected["url"]
174
+ source_info["full_name"] = selected.get("full_name")
175
+ elif selected["platform"] == "local":
176
+ source_info["path"] = selected["path"]
177
+
178
+ record_install_info(install_path, source_info, module_data, location)
179
+
180
+ # 记录操作日志
181
+ log_operation("install", {
182
+ "module": module_data['name'],
183
+ "version": module_data.get('version', 'unknown'),
184
+ "source": source_info,
185
+ "location": location,
186
+ "path": str(install_path)
187
+ }, success=True)
188
+
189
+ print(t('install_complete'))
190
+ print(t('restart_hint'))
191
+
192
+ return 0
193
+
194
+ except Exception as e:
195
+ # 记录失败日志
196
+ log_operation("install", {
197
+ "source": source,
198
+ "location": location
199
+ }, success=False, error=str(e))
200
+ raise
201
+
202
+ finally:
203
+ # 清理临时目录
204
+ shutil.rmtree(temp_dir, ignore_errors=True)
205
+
206
+
207
+ def check_single_platform(source: str, platform: str, version_spec: str = None):
208
+ """检查单个平台"""
209
+ candidates = []
210
+
211
+ if platform == "pypi":
212
+ result = PlatformChecker.check_pypi(source)
213
+ if result:
214
+ # 根据版本规范过滤
215
+ if version_spec:
216
+ matched_versions = filter_versions(result.get("versions", []), version_spec)
217
+ if matched_versions:
218
+ result["matched_version"] = matched_versions[0] # 选择最新的匹配版本
219
+ result["version_spec"] = version_spec
220
+ candidates.append(result)
221
+ else:
222
+ candidates.append(result)
223
+
224
+ elif platform == "npm":
225
+ result = PlatformChecker.check_npm(source)
226
+ if result:
227
+ # 根据版本规范过滤
228
+ if version_spec:
229
+ matched_versions = filter_versions(result.get("versions", []), version_spec)
230
+ if matched_versions:
231
+ result["matched_version"] = matched_versions[0]
232
+ result["version_spec"] = version_spec
233
+ candidates.append(result)
234
+ else:
235
+ candidates.append(result)
236
+
237
+ elif platform == "git":
238
+ results = PlatformChecker.check_git(source)
239
+ if results:
240
+ candidates.extend(results)
241
+
242
+ elif platform == "local":
243
+ # 本地路径直接返回
244
+ if Path(source).exists():
245
+ candidates.append({
246
+ "platform": "local",
247
+ "path": source
248
+ })
249
+
250
+ return candidates
251
+
252
+
253
+ def check_all_platforms(source: str, version_spec: str = None):
254
+ """检查所有平台"""
255
+ candidates = []
256
+
257
+ # 先检查是否是本地路径
258
+ if Path(source).exists():
259
+ candidates.append({
260
+ "platform": "local",
261
+ "path": source,
262
+ "name": Path(source).name
263
+ })
264
+ return candidates
265
+
266
+ # 并行检查 PyPI/npm/Git
267
+ results = PlatformChecker.check_all(source)
268
+
269
+ if results["pypi"]:
270
+ result = results["pypi"]
271
+ # 根据版本规范过滤
272
+ if version_spec:
273
+ matched_versions = filter_versions(result.get("versions", []), version_spec)
274
+ if matched_versions:
275
+ result["matched_version"] = matched_versions[0]
276
+ result["version_spec"] = version_spec
277
+ candidates.append(result)
278
+ else:
279
+ candidates.append(result)
280
+
281
+ if results["npm"]:
282
+ result = results["npm"]
283
+ # 根据版本规范过滤
284
+ if version_spec:
285
+ matched_versions = filter_versions(result.get("versions", []), version_spec)
286
+ if matched_versions:
287
+ result["matched_version"] = matched_versions[0]
288
+ result["version_spec"] = version_spec
289
+ candidates.append(result)
290
+ else:
291
+ candidates.append(result)
292
+
293
+ if results["git"]:
294
+ candidates.extend(results["git"])
295
+
296
+ return candidates
297
+
298
+
299
+ def download_module(selected: dict, temp_dir: Path):
300
+ """根据选择的来源下载模块"""
301
+ platform = selected["platform"]
302
+ version = selected.get("matched_version") or selected.get("latest")
303
+
304
+ if platform == "pypi":
305
+ return Downloader.download_pypi(selected["name"], temp_dir, version)
306
+ elif platform == "npm":
307
+ return Downloader.download_npm(selected["name"], temp_dir, version)
308
+ elif platform == "git":
309
+ return Downloader.download_git(selected["url"], temp_dir)
310
+ elif platform == "local":
311
+ return Downloader.download_local(selected["path"], temp_dir)
312
+
313
+ return None, "未知的平台类型"