@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,315 @@
1
+ #!/usr/bin/env python3
2
+ """Kite CLI 开发计划管理器
3
+
4
+ 用于管理开发计划的进度、状态和任务分配。
5
+ """
6
+ import json
7
+ import re
8
+ from datetime import datetime
9
+ from pathlib import Path
10
+ from typing import List, Dict, Optional
11
+
12
+
13
+ class PlanManager:
14
+ """开发计划管理器"""
15
+
16
+ def __init__(self, plan_file: str = None):
17
+ if plan_file is None:
18
+ plan_file = Path(__file__).parent.parent / "docs" / "CLI开发计划.md"
19
+ self.plan_file = Path(plan_file)
20
+ self.state_file = self.plan_file.parent / ".cli_plan_state.json"
21
+ self.state = self._load_state()
22
+
23
+ def _load_state(self) -> Dict:
24
+ """加载计划状态"""
25
+ if self.state_file.exists():
26
+ with open(self.state_file, "r", encoding="utf-8") as f:
27
+ return json.load(f)
28
+ return {
29
+ "tasks": {},
30
+ "history": []
31
+ }
32
+
33
+ def _save_state(self):
34
+ """保存计划状态"""
35
+ with open(self.state_file, "w", encoding="utf-8") as f:
36
+ json.dump(self.state, f, indent=2, ensure_ascii=False)
37
+
38
+ def list_tasks(self, phase: Optional[str] = None, status: Optional[str] = None):
39
+ """列出任务"""
40
+ content = self.plan_file.read_text(encoding="utf-8")
41
+
42
+ # 解析任务
43
+ tasks = []
44
+ current_phase = None
45
+ current_section = None
46
+
47
+ for line in content.split("\n"):
48
+ # 检测 Phase
49
+ phase_match = re.match(r"## (Phase \d+):", line)
50
+ if phase_match:
51
+ current_phase = phase_match.group(1)
52
+ continue
53
+
54
+ # 检测子任务
55
+ section_match = re.match(r"### ([\d.]+) (.+)", line)
56
+ if section_match:
57
+ task_id = section_match.group(1)
58
+ task_name = section_match.group(2)
59
+ current_section = f"{current_phase}.{task_id}"
60
+
61
+ # 获取状态
62
+ task_state = self.state["tasks"].get(current_section, {})
63
+ task_status = task_state.get("status", "待开始")
64
+
65
+ tasks.append({
66
+ "id": current_section,
67
+ "phase": current_phase,
68
+ "name": task_name,
69
+ "status": task_status,
70
+ "assignee": task_state.get("assignee"),
71
+ "started_at": task_state.get("started_at"),
72
+ "completed_at": task_state.get("completed_at")
73
+ })
74
+
75
+ # 过滤
76
+ if phase:
77
+ tasks = [t for t in tasks if t["phase"] == phase]
78
+ if status:
79
+ tasks = [t for t in tasks if t["status"] == status]
80
+
81
+ return tasks
82
+
83
+ def show_tasks(self, phase: Optional[str] = None, status: Optional[str] = None):
84
+ """显示任务列表"""
85
+ tasks = self.list_tasks(phase, status)
86
+
87
+ if not tasks:
88
+ print("没有找到任务")
89
+ return
90
+
91
+ print(f"\n{'ID':<20} {'任务名称':<30} {'状态':<10} {'负责人':<10}")
92
+ print("-" * 80)
93
+
94
+ for task in tasks:
95
+ task_id = task["id"]
96
+ name = task["name"][:28] + ".." if len(task["name"]) > 30 else task["name"]
97
+ status_str = task["status"]
98
+ assignee = task["assignee"] or "-"
99
+
100
+ print(f"{task_id:<20} {name:<30} {status_str:<10} {assignee:<10}")
101
+
102
+ print(f"\n共 {len(tasks)} 个任务")
103
+
104
+ def start_task(self, task_id: str, assignee: str = "开发者"):
105
+ """开始任务"""
106
+ if task_id not in self.state["tasks"]:
107
+ self.state["tasks"][task_id] = {}
108
+
109
+ self.state["tasks"][task_id].update({
110
+ "status": "进行中",
111
+ "assignee": assignee,
112
+ "started_at": datetime.now().isoformat()
113
+ })
114
+
115
+ self.state["history"].append({
116
+ "action": "start",
117
+ "task_id": task_id,
118
+ "assignee": assignee,
119
+ "timestamp": datetime.now().isoformat()
120
+ })
121
+
122
+ self._save_state()
123
+ print(f"[Done] 任务 {task_id} 已开始")
124
+
125
+ def complete_task(self, task_id: str, note: str = None):
126
+ """完成任务"""
127
+ if task_id not in self.state["tasks"]:
128
+ print(f"[Error] 任务 {task_id} 不存在")
129
+ return
130
+
131
+ self.state["tasks"][task_id].update({
132
+ "status": "已完成",
133
+ "completed_at": datetime.now().isoformat(),
134
+ "note": note
135
+ })
136
+
137
+ self.state["history"].append({
138
+ "action": "complete",
139
+ "task_id": task_id,
140
+ "note": note,
141
+ "timestamp": datetime.now().isoformat()
142
+ })
143
+
144
+ self._save_state()
145
+ print(f"[Done] 任务 {task_id} 已完成")
146
+
147
+ def block_task(self, task_id: str, reason: str):
148
+ """阻塞任务"""
149
+ if task_id not in self.state["tasks"]:
150
+ self.state["tasks"][task_id] = {}
151
+
152
+ self.state["tasks"][task_id].update({
153
+ "status": "阻塞",
154
+ "blocked_reason": reason,
155
+ "blocked_at": datetime.now().isoformat()
156
+ })
157
+
158
+ self.state["history"].append({
159
+ "action": "block",
160
+ "task_id": task_id,
161
+ "reason": reason,
162
+ "timestamp": datetime.now().isoformat()
163
+ })
164
+
165
+ self._save_state()
166
+ print(f"[Warning] 任务 {task_id} 已阻塞: {reason}")
167
+
168
+ def unblock_task(self, task_id: str):
169
+ """解除阻塞"""
170
+ if task_id not in self.state["tasks"]:
171
+ print(f"[Error] 任务 {task_id} 不存在")
172
+ return
173
+
174
+ self.state["tasks"][task_id].update({
175
+ "status": "进行中",
176
+ "blocked_reason": None,
177
+ "unblocked_at": datetime.now().isoformat()
178
+ })
179
+
180
+ self.state["history"].append({
181
+ "action": "unblock",
182
+ "task_id": task_id,
183
+ "timestamp": datetime.now().isoformat()
184
+ })
185
+
186
+ self._save_state()
187
+ print(f"[Done] 任务 {task_id} 已解除阻塞")
188
+
189
+ def show_progress(self):
190
+ """显示整体进度"""
191
+ tasks = self.list_tasks()
192
+
193
+ total = len(tasks)
194
+ completed = len([t for t in tasks if t["status"] == "已完成"])
195
+ in_progress = len([t for t in tasks if t["status"] == "进行中"])
196
+ blocked = len([t for t in tasks if t["status"] == "阻塞"])
197
+ pending = total - completed - in_progress - blocked
198
+
199
+ print("\n=== Kite CLI 开发进度 ===\n")
200
+ print(f"总任务数: {total}")
201
+ print(f"已完成: {completed} ({completed/total*100:.1f}%)")
202
+ print(f"进行中: {in_progress} ({in_progress/total*100:.1f}%)")
203
+ print(f"阻塞: {blocked} ({blocked/total*100:.1f}%)")
204
+ print(f"待开始: {pending} ({pending/total*100:.1f}%)")
205
+
206
+ # 按 Phase 统计
207
+ print("\n=== 各阶段进度 ===\n")
208
+ phases = {}
209
+ for task in tasks:
210
+ phase = task["phase"]
211
+ if phase not in phases:
212
+ phases[phase] = {"total": 0, "completed": 0}
213
+ phases[phase]["total"] += 1
214
+ if task["status"] == "已完成":
215
+ phases[phase]["completed"] += 1
216
+
217
+ for phase, stats in sorted(phases.items()):
218
+ total_p = stats["total"]
219
+ completed_p = stats["completed"]
220
+ percent = completed_p / total_p * 100 if total_p > 0 else 0
221
+ print(f"{phase}: {completed_p}/{total_p} ({percent:.1f}%)")
222
+
223
+ def show_history(self, limit: int = 10):
224
+ """显示操作历史"""
225
+ history = self.state["history"][-limit:]
226
+
227
+ if not history:
228
+ print("暂无操作历史")
229
+ return
230
+
231
+ print(f"\n最近 {len(history)} 条操作:\n")
232
+
233
+ for entry in history:
234
+ timestamp = entry["timestamp"][:19]
235
+ action = entry["action"]
236
+ task_id = entry["task_id"]
237
+
238
+ action_map = {
239
+ "start": "开始",
240
+ "complete": "完成",
241
+ "block": "阻塞",
242
+ "unblock": "解除阻塞"
243
+ }
244
+
245
+ action_str = action_map.get(action, action)
246
+ print(f"{timestamp} - {action_str} {task_id}")
247
+
248
+ if action == "complete" and entry.get("note"):
249
+ print(f" 备注: {entry['note']}")
250
+ elif action == "block" and entry.get("reason"):
251
+ print(f" 原因: {entry['reason']}")
252
+
253
+
254
+ def main():
255
+ """命令行入口"""
256
+ import argparse
257
+
258
+ parser = argparse.ArgumentParser(description="Kite CLI 开发计划管理器")
259
+ subparsers = parser.add_subparsers(dest="command", help="命令")
260
+
261
+ # list 命令
262
+ list_parser = subparsers.add_parser("list", help="列出任务")
263
+ list_parser.add_argument("--phase", help="过滤 Phase")
264
+ list_parser.add_argument("--status", help="过滤状态")
265
+
266
+ # start 命令
267
+ start_parser = subparsers.add_parser("start", help="开始任务")
268
+ start_parser.add_argument("task_id", help="任务 ID")
269
+ start_parser.add_argument("--assignee", default="开发者", help="负责人")
270
+
271
+ # complete 命令
272
+ complete_parser = subparsers.add_parser("complete", help="完成任务")
273
+ complete_parser.add_argument("task_id", help="任务 ID")
274
+ complete_parser.add_argument("--note", help="备注")
275
+
276
+ # block 命令
277
+ block_parser = subparsers.add_parser("block", help="阻塞任务")
278
+ block_parser.add_argument("task_id", help="任务 ID")
279
+ block_parser.add_argument("reason", help="阻塞原因")
280
+
281
+ # unblock 命令
282
+ unblock_parser = subparsers.add_parser("unblock", help="解除阻塞")
283
+ unblock_parser.add_argument("task_id", help="任务 ID")
284
+
285
+ # progress 命令
286
+ progress_parser = subparsers.add_parser("progress", help="显示进度")
287
+
288
+ # history 命令
289
+ history_parser = subparsers.add_parser("history", help="显示历史")
290
+ history_parser.add_argument("--limit", type=int, default=10, help="显示条数")
291
+
292
+ args = parser.parse_args()
293
+
294
+ manager = PlanManager()
295
+
296
+ if args.command == "list":
297
+ manager.show_tasks(phase=args.phase, status=args.status)
298
+ elif args.command == "start":
299
+ manager.start_task(args.task_id, args.assignee)
300
+ elif args.command == "complete":
301
+ manager.complete_task(args.task_id, args.note)
302
+ elif args.command == "block":
303
+ manager.block_task(args.task_id, args.reason)
304
+ elif args.command == "unblock":
305
+ manager.unblock_task(args.task_id)
306
+ elif args.command == "progress":
307
+ manager.show_progress()
308
+ elif args.command == "history":
309
+ manager.show_history(args.limit)
310
+ else:
311
+ parser.print_help()
312
+
313
+
314
+ if __name__ == "__main__":
315
+ main()
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Python 环境工具模块
3
+ *
4
+ * 提供获取虚拟环境 Python 路径的工具函数
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const os = require('os');
10
+
11
+ /**
12
+ * 获取 KITE_DATA 路径
13
+ */
14
+ function getKiteDataPath() {
15
+ return path.join(os.homedir(), '.kite');
16
+ }
17
+
18
+ /**
19
+ * 获取虚拟环境路径
20
+ */
21
+ function getVenvPath() {
22
+ return path.join(getKiteDataPath(), 'venv');
23
+ }
24
+
25
+ /**
26
+ * 获取虚拟环境的 Python 可执行文件路径
27
+ */
28
+ function getVenvPython() {
29
+ const venvPath = getVenvPath();
30
+
31
+ if (process.platform === 'win32') {
32
+ return path.join(venvPath, 'Scripts', 'python.exe');
33
+ } else {
34
+ return path.join(venvPath, 'bin', 'python');
35
+ }
36
+ }
37
+
38
+ /**
39
+ * 获取虚拟环境的 pip 可执行文件路径
40
+ */
41
+ function getVenvPip() {
42
+ const venvPath = getVenvPath();
43
+
44
+ if (process.platform === 'win32') {
45
+ return path.join(venvPath, 'Scripts', 'pip.exe');
46
+ } else {
47
+ return path.join(venvPath, 'bin', 'pip');
48
+ }
49
+ }
50
+
51
+ /**
52
+ * 检查虚拟环境是否存在
53
+ */
54
+ function venvExists() {
55
+ const pythonPath = getVenvPython();
56
+ return fs.existsSync(pythonPath);
57
+ }
58
+
59
+ /**
60
+ * 检查 Python 环境是否就绪
61
+ */
62
+ function isPythonReady() {
63
+ if (!venvExists()) {
64
+ return false;
65
+ }
66
+
67
+ // 检查 pip 是否存在
68
+ const pipPath = getVenvPip();
69
+ return fs.existsSync(pipPath);
70
+ }
71
+
72
+ module.exports = {
73
+ getKiteDataPath,
74
+ getVenvPath,
75
+ getVenvPython,
76
+ getVenvPip,
77
+ venvExists,
78
+ isPythonReady
79
+ };