@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,44 @@
1
+ import agentcp
2
+ import Agently
3
+ import os
4
+ from dotenv import load_dotenv
5
+ load_dotenv()
6
+
7
+ if __name__ == "__main__":
8
+ agent_id = 'your_agent_id_from_profile'
9
+ acp = agentcp.AgentCP('.', seed_password='')
10
+ aid = acp.load_aid(agent_id)
11
+ openai_api_key = os.getenv("OPENAI_API_KEY")
12
+ model_url = os.getenv("BASE_URL")
13
+ model_name = os.getenv("MODEL")
14
+ agent = (
15
+ Agently.create_agent()
16
+ .set_settings("current_model", "OAIClient")
17
+ .set_settings("model.OAIClient.auth", {'api_key': openai_api_key})
18
+ .set_settings("model.OAIClient.url", model_url)
19
+ .set_settings("model.OAIClient.options", {'model': model_name})
20
+ )
21
+
22
+ @aid.message_handler() #消息处理函数
23
+ async def sync_message_handler(msg):
24
+ receiver = aid.get_receiver_from_message(msg) # 获取接收者
25
+ if aid.id not in receiver:
26
+ return
27
+ session_id = aid.get_session_id_from_message(msg)
28
+ sender = aid.get_sender_from_message(msg) # 获取发送者
29
+ sender_content = aid.get_content_from_message(msg)
30
+ result = (
31
+ agent
32
+ .general("输出规定", "必须使用中文进行输出")
33
+ .role({
34
+ "姓名": "ACP小助手",
35
+ "任务": "使用自己的知识为用户解答常见问题",
36
+ })
37
+ .input(sender_content)
38
+ .instruct(["你需要根据用户的问题提供相关的回答", "你可以适当的有点幽默"])
39
+ .start()
40
+ )
41
+ aid.send_message_content(to_aid_list=[sender], session_id=session_id, llm_content=result)
42
+ return True
43
+ aid.online()
44
+ acp.serve_forever()
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 AgentUnion Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ from . import file_util
@@ -0,0 +1,117 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ def get_file_info(file_path: str) -> dict:
4
+ """
5
+ 通过文件路径读取文件信息
6
+
7
+ Args:
8
+ file_path (str): 文件的完整路径
9
+
10
+ Returns:
11
+ dict: 包含文件信息的字典,格式为:
12
+ {
13
+ 'file_name': str, # 文件名
14
+ 'file_size': int, # 文件大小(字节)
15
+ 'file_type': str, # 文件类型/扩展名
16
+ 'exists': bool, # 文件是否存在
17
+ 'error': str # 错误信息(如果有)
18
+ }
19
+ """
20
+ try:
21
+ # 检查文件是否存在
22
+ if not os.path.exists(file_path):
23
+ return {
24
+ 'file_name': '',
25
+ 'file_size': 0,
26
+ 'file_type': '',
27
+ 'exists': False,
28
+ 'error': '文件不存在'
29
+ }
30
+
31
+ # 检查是否为文件(而不是目录)
32
+ if not os.path.isfile(file_path):
33
+ return {
34
+ 'file_name': '',
35
+ 'file_size': 0,
36
+ 'file_type': '',
37
+ 'exists': False,
38
+ 'error': '路径不是文件'
39
+ }
40
+
41
+ # 获取文件信息
42
+ file_stats = os.stat(file_path)
43
+ file_name = os.path.basename(file_path)
44
+ file_size = file_stats.st_size
45
+
46
+ # 获取文件扩展名作为文件类型
47
+ file_type = os.path.splitext(file_path)[1].lower()
48
+ if file_type.startswith('.'):
49
+ file_type = file_type[1:] # 移除开头的点
50
+
51
+ # 如果没有扩展名,尝试根据文件内容判断类型
52
+ if not file_type:
53
+ file_type = _detect_file_type(file_path)
54
+
55
+ return {
56
+ 'file_name': file_name,
57
+ 'file_size': file_size,
58
+ 'file_type': file_type,
59
+ 'exists': True,
60
+ 'error': ''
61
+ }
62
+
63
+ except PermissionError:
64
+ return {
65
+ 'file_name': '',
66
+ 'file_size': 0,
67
+ 'file_type': '',
68
+ 'exists': False,
69
+ 'error': '没有权限访问文件'
70
+ }
71
+ except Exception as e:
72
+ return {
73
+ 'file_name': '',
74
+ 'file_size': 0,
75
+ 'file_type': '',
76
+ 'exists': False,
77
+ 'error': f'读取文件信息时发生错误: {str(e)}'
78
+ }
79
+
80
+ def _detect_file_type(file_path: str) -> str:
81
+ """
82
+ 当文件没有扩展名时,尝试检测文件类型
83
+
84
+ Args:
85
+ file_path (str): 文件路径
86
+
87
+ Returns:
88
+ str: 检测到的文件类型
89
+ """
90
+ try:
91
+ with open(file_path, 'rb') as f:
92
+ # 读取文件头部字节来判断文件类型
93
+ header = f.read(16)
94
+
95
+ # 常见文件类型的魔数检测
96
+ if header.startswith(b'\x89PNG\r\n\x1a\n'):
97
+ return 'png'
98
+ elif header.startswith(b'\xff\xd8\xff'):
99
+ return 'jpg'
100
+ elif header.startswith(b'GIF8'):
101
+ return 'gif'
102
+ elif header.startswith(b'%PDF'):
103
+ return 'pdf'
104
+ elif header.startswith(b'PK\x03\x04'):
105
+ return 'zip'
106
+ elif header.startswith(b'\x50\x4b\x03\x04'):
107
+ return 'zip'
108
+ else:
109
+ # 尝试作为文本文件读取
110
+ try:
111
+ f.seek(0)
112
+ f.read().decode('utf-8')
113
+ return 'txt'
114
+ except UnicodeDecodeError:
115
+ return 'binary'
116
+ except Exception:
117
+ return 'unknown'
@@ -0,0 +1,99 @@
1
+ # -*- coding: utf-8 -*-
2
+ import os
3
+ from contextlib import contextmanager
4
+ from urllib.parse import urlparse
5
+
6
+
7
+ _LOCAL_HOSTS = ("localhost", "127.0.0.1", "::1", "0.0.0.0")
8
+ _LOCAL_NO_PROXY = "localhost,127.0.0.1,::1"
9
+ LOCAL_NO_PROXY_LIST = ["localhost", "127.0.0.1", "::1"]
10
+
11
+
12
+ def ensure_no_proxy_for_local_env() -> None:
13
+ """Ensure NO_PROXY/no_proxy includes localhost, as a safety net against global proxies."""
14
+ for key in ("NO_PROXY", "no_proxy"):
15
+ existing = (os.environ.get(key) or "").strip()
16
+ if not existing:
17
+ os.environ[key] = _LOCAL_NO_PROXY
18
+ continue
19
+
20
+ existing_parts = [p.strip() for p in existing.replace(";", ",").split(",") if p.strip()]
21
+ existing_lower = {p.lower() for p in existing_parts}
22
+ for host in _LOCAL_NO_PROXY.split(","):
23
+ if host.lower() not in existing_lower:
24
+ existing_parts.append(host)
25
+ os.environ[key] = ",".join(existing_parts)
26
+
27
+
28
+ def is_local_url(url: str) -> bool:
29
+ """Return True when URL hostname is localhost/loopback."""
30
+ try:
31
+ parsed = urlparse(url)
32
+ host = parsed.hostname
33
+ if not host:
34
+ return False
35
+ host = host.strip("[]").lower()
36
+ return host in _LOCAL_HOSTS
37
+ except Exception:
38
+ return False
39
+
40
+
41
+ def get_requests_proxies(use_system_proxy: bool, url: str):
42
+ """
43
+ For requests:
44
+ - {} disables proxy
45
+ - None uses env/system proxy
46
+ """
47
+ return {}
48
+
49
+
50
+ def get_trust_env(use_system_proxy: bool, url: str) -> bool:
51
+ """For httpx/aiohttp trust_env: never trust env proxy for any URL."""
52
+ return False
53
+
54
+
55
+ def pop_proxy_env():
56
+ """Remove proxy env vars and return the saved mapping for restoration."""
57
+ keys = (
58
+ "HTTP_PROXY",
59
+ "HTTPS_PROXY",
60
+ "ALL_PROXY",
61
+ "FTP_PROXY",
62
+ "SOCKS_PROXY",
63
+ "http_proxy",
64
+ "https_proxy",
65
+ "all_proxy",
66
+ "ftp_proxy",
67
+ "socks_proxy",
68
+ )
69
+ saved = {k: os.environ.get(k) for k in keys}
70
+ for k in keys:
71
+ os.environ.pop(k, None)
72
+ return saved
73
+
74
+
75
+ def restore_proxy_env(saved) -> None:
76
+ if not saved:
77
+ return
78
+ for k, v in saved.items():
79
+ if v is None:
80
+ os.environ.pop(k, None)
81
+ else:
82
+ os.environ[k] = v
83
+
84
+
85
+ @contextmanager
86
+ def without_proxy_env(enabled: bool = True):
87
+ """
88
+ Temporarily remove proxy env vars (HTTP(S)_PROXY/ALL_PROXY and lowercase variants).
89
+ Useful for websocket libraries that consult env proxies.
90
+ """
91
+ if not enabled:
92
+ yield
93
+ return
94
+
95
+ saved = pop_proxy_env()
96
+ try:
97
+ yield
98
+ finally:
99
+ restore_proxy_env(saved)
@@ -0,0 +1,203 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright 2025 AgentUnion Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ """
17
+ 我们来详细实现Workflow:
18
+ 1.Mermaid类是mermaid语法的解析器,类构造实例的时候传入mermaid语法的文本,得到流程图的节点和边.目前只支持graph
19
+ 2.Workflow类是用来处理任意工作流,在构造实例的时候传入一个Mermaid的实例作为整个工作流参考的基础
20
+ 3.各节点类通过装饰器output_port和input_port来定义节点的输入输出端口
21
+ 4.节点通过Workflow的addnode方法加入工作流,工作流在调用start方法的时候,根据mermaid的节点和边的关系建立各节点实例输入输出端口之间的绑定关系
22
+ 5.在定义Agent的时候, 不同的Agent需要有不同Agent的类
23
+ 6.每个Agent类, 他有具体的输入输出端口, 这些输入输出端口是通过装饰器来定义
24
+ 7.装饰器做两件事:
25
+ 1.完成参数的传递
26
+ 2.完成端口函数名字和端口注解的绑定(可以在函数定义里面的注释部分来描述这个端口是做什么用的,
27
+ 他应该与mermaid里面的流程里面的描述词一样)
28
+ 8.通过workflow.start的时候, 首先将已经通过addmode加入的节点之间, 让输入输出端口之间根据描述词建立绑定关系.
29
+ 这样, 当一个输出端口执行完毕后, 将自动开始调用其指向的下一个Agent的输入端口函数
30
+ """
31
+
32
+ # 引入acp的库
33
+ # import time
34
+ import threading
35
+
36
+ from inspect import iscoroutinefunction
37
+ import asyncio
38
+
39
+ from .mermaid import Mermaid
40
+ from functools import wraps
41
+ from collections import defaultdict
42
+
43
+ from agentcp.base.log import log_error, log_info, log_warning
44
+
45
+
46
+ class Workflow:
47
+ _workflow_lock = threading.Lock()
48
+ _workflow_storage = dict()
49
+
50
+ def output_port(description: str):
51
+ """
52
+ 输出端口的函数参数定义无限制,只要他的调用者(通常就是当前节点自己的输入端口函数中)正确的传递参数即可
53
+ 输入端口的函数参数定义,是一个字符串,其实原则上也是没有限制的,只要调用者参数传递争取即可
54
+
55
+ :return:
56
+ """
57
+
58
+ # 输出端口的函数定义是随便的,只要他的调用者正确的传递参数即可
59
+ #
60
+ def decorator(func):
61
+ func.is_output_port = True
62
+ func.output_port_desc = description
63
+
64
+ @wraps(func)
65
+ def wrapper(self, *args, **kwargs):
66
+ try:
67
+ result = func(self, *args, **kwargs)
68
+
69
+ workflow = self._workflow
70
+
71
+ output_port_name = f"{self.__class__.__name__}:{func.__name__}"
72
+ target_port, target_port_name = workflow.port_mapping.get(output_port_name, (None, None))
73
+ if target_port:
74
+ # 判断是否为异步方法并处理
75
+ if iscoroutinefunction(target_port):
76
+ # 获取或创建事件循环
77
+ try:
78
+ loop = asyncio.get_running_loop()
79
+ except RuntimeError:
80
+ loop = asyncio.new_event_loop()
81
+ asyncio.set_event_loop(loop)
82
+ # 异步调用(支持同步/异步上下文)
83
+ loop.run_until_complete(target_port(result))
84
+ else:
85
+ # 同步调用
86
+ target_port(result)
87
+ else:
88
+ log_error(f"{output_port_name}没有找到绑定的输入端口")
89
+
90
+ return result
91
+ except Exception as e:
92
+ log_error(f"Error in output port {func.__name__}: {e}")
93
+ raise
94
+
95
+ return wrapper
96
+
97
+ return decorator
98
+
99
+ def input_port(param: str):
100
+ def decorator(func):
101
+ func.is_input_port = True
102
+ func.input_port_desc = param
103
+
104
+ @wraps(func)
105
+ def wrapper(self, *args, **kwargs):
106
+ try:
107
+ return func(self, *args, **kwargs)
108
+ except Exception as e:
109
+ log_error(f"输入端口异常 {func.__name__}: {e}")
110
+ raise
111
+
112
+ return wrapper
113
+
114
+ return decorator
115
+
116
+ def __init__(self, mermaid: Mermaid):
117
+ self.nodes = {}
118
+ self.port_mapping = defaultdict()
119
+ self.mermaid = mermaid # 保存 Mermaid 实例
120
+
121
+ def addnode(self, agent, node_name):
122
+ agent._workflow = self
123
+ self.nodes[node_name] = agent
124
+ return self # 返回 self 以支持链式调用
125
+
126
+ @classmethod
127
+ def getstorage(cls, key=None, default=None, caller: str = "") -> dict:
128
+ # 不同的工作流调用者得到不同的存储对象,默认是一个线程一个对象
129
+ if not caller or len(caller) == 0:
130
+ threadid = threading.get_ident()
131
+ caller = f"workflow_caller_{threadid}"
132
+ with cls._workflow_lock:
133
+ if caller not in cls._workflow_storage:
134
+ cls._workflow_storage[caller] = dict()
135
+
136
+ storage = cls._workflow_storage[caller]
137
+ if key:
138
+ return storage.setdefault(key, default)
139
+ return storage
140
+
141
+ @classmethod
142
+ def clearstorage(cls, caller: str = "") -> None:
143
+ """
144
+ 清除指定调用者的存储数据
145
+
146
+ :param caller: 调用者标识,默认为当前线程生成的标识
147
+ """
148
+ if not caller or len(caller) == 0:
149
+ threadid = threading.get_ident()
150
+ caller = f"workflow_caller_{threadid}"
151
+ with cls._workflow_lock:
152
+ if caller in cls._workflow_storage:
153
+ del cls._workflow_storage[caller]
154
+
155
+ def start(self):
156
+ self._build_port_mapping()
157
+
158
+ def _build_port_mapping(self):
159
+ mermaid_edges = self.mermaid.edges # 从 Mermaid 实例获取边数据
160
+ for edge in mermaid_edges:
161
+ source_node, description, target_node = edge
162
+ source_node_desc = self.mermaid.node_dict.get(source_node, "")
163
+ target_node_desc = self.mermaid.node_dict.get(target_node, "")
164
+ source_agent = self.nodes.get(source_node_desc, None)
165
+ target_agent = self.nodes.get(target_node_desc, None)
166
+ if not source_agent:
167
+ log_warning(
168
+ f'"{source_node} -->|{description}|{target_node}"\t{source_node}[{source_node_desc}]没有找到'
169
+ )
170
+ if not target_agent:
171
+ log_warning(
172
+ f'"{source_node} -->|{description}|{target_node}"\t{target_node}[{target_node_desc}]没有找到'
173
+ )
174
+ if source_agent and target_agent:
175
+ output_port = self._find_output_port(source_agent, description)
176
+ input_port = self._find_input_port(target_agent, description)
177
+ if not output_port:
178
+ log_warning(f'"{source_node_desc}"没有发现输出端口:{description}')
179
+ if not input_port:
180
+ log_warning(f'"{target_node_desc}"没有发现输入端口:{description}')
181
+ if input_port and output_port:
182
+ self.port_mapping[f"{source_agent.__class__.__name__}:{output_port.__name__}"] = (
183
+ input_port,
184
+ f"{target_agent.__class__.__name__}:{input_port.__name__}",
185
+ )
186
+ log_info(
187
+ f"[{source_node_desc} -> |{description}| {target_node_desc}]"
188
+ f"\n\t调用链: {source_agent.__class__.__name__}:{output_port.__name__} >> {target_agent.__class__.__name__}:{input_port.__name__}"
189
+ )
190
+
191
+ def _find_output_port(self, agent, desc):
192
+ for method_name in dir(agent):
193
+ method = getattr(agent, method_name)
194
+ if hasattr(method, "is_output_port") and method.output_port_desc == desc:
195
+ return method
196
+ return None
197
+
198
+ def _find_input_port(self, agent, desc):
199
+ for method_name in dir(agent):
200
+ method = getattr(agent, method_name)
201
+ if hasattr(method, "is_input_port") and method.input_port_desc == desc:
202
+ return method
203
+ return None
@@ -0,0 +1,109 @@
1
+ """
2
+ console_auth.py - 控制台认证交互模块
3
+
4
+ 提供控制台交互式登录功能:
5
+ 1. 检查本地 token 是否有效(fsss2 文件修改时间 < 7天)
6
+ 2. 控制台输入手机号 + 验证码完成登录
7
+ """
8
+
9
+ import asyncio
10
+ import os
11
+ import time
12
+
13
+
14
+ def check_token_valid() -> bool:
15
+ """
16
+ 检查本地 token 是否有效
17
+
18
+ 判断逻辑:
19
+ 1. 读取 ~/.evol/default/fsss2 文件
20
+ 2. 如果文件存在且内容非空
21
+ 3. 检查文件修改时间距今是否 < 7天
22
+
23
+ Returns:
24
+ bool: True 表示 token 有效,False 表示需要重新登录
25
+ """
26
+ from evol.presenter.configPresenter import configPresenter
27
+
28
+ token = configPresenter.get_token()
29
+ if not token:
30
+ return False
31
+
32
+ # 检查 fsss2 文件的修改时间
33
+ fsss2_path = configPresenter.get_fsss2_file_path()
34
+
35
+ if not os.path.exists(fsss2_path):
36
+ return False
37
+
38
+ try:
39
+ mtime = os.path.getmtime(fsss2_path)
40
+ days_since_modified = (time.time() - mtime) / (60 * 60 * 24)
41
+
42
+ if days_since_modified >= 7:
43
+ print(f"Token 已过期({days_since_modified:.1f} 天前更新),需要重新登录")
44
+ return False
45
+
46
+ print(f"Token 有效({days_since_modified:.1f} 天前更新)")
47
+ return True
48
+
49
+ except OSError:
50
+ return False
51
+
52
+
53
+ async def console_login():
54
+ """
55
+ 控制台交互式登录
56
+
57
+ 流程:
58
+ 1. 提示输入手机号
59
+ 2. 调用 send_sms_code 发送验证码
60
+ 3. 提示输入验证码
61
+ 4. 调用 sms_login 完成登录
62
+ """
63
+ from evol.presenter.userPresenter import userPresenter
64
+
65
+ print("\n" + "=" * 50)
66
+ print(" Evol Sample Backend - 用户登录")
67
+ print("=" * 50)
68
+
69
+ while True:
70
+ phone = input("\n请输入手机号: ").strip()
71
+ if not phone:
72
+ print("手机号不能为空,请重新输入")
73
+ continue
74
+ if len(phone) != 11 or not phone.isdigit():
75
+ print("请输入有效的11位手机号")
76
+ continue
77
+ break
78
+
79
+ # 发送验证码
80
+ print(f"\n正在向 {phone[:3]}****{phone[7:]} 发送验证码...")
81
+ sms_result = await userPresenter.send_sms_code(phone)
82
+
83
+ if sms_result.get("status") != "success":
84
+ print(f"发送验证码失败: {sms_result.get('error', '未知错误')}")
85
+ raise SystemExit(1)
86
+
87
+ print("验证码已发送,请查收短信")
88
+
89
+ # 输入验证码
90
+ while True:
91
+ code = input("请输入验证码: ").strip()
92
+ if not code:
93
+ print("验证码不能为空,请重新输入")
94
+ continue
95
+ if len(code) != 6 or not code.isdigit():
96
+ print("请输入6位数字验证码")
97
+ continue
98
+ break
99
+
100
+ # 登录
101
+ print("\n正在登录...")
102
+ login_result = await userPresenter.sms_login(phone, code)
103
+
104
+ if login_result.get("status") != "success":
105
+ print(f"登录失败: {login_result.get('error', '未知错误')}")
106
+ raise SystemExit(1)
107
+
108
+ print("登录成功!")
109
+ return True
@@ -0,0 +1 @@
1
+ # -*- coding: utf-8 -*-
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 全局配置文件
4
+ """
5
+
6
+ APP_ENV = "dev"
7
+
8
+ # ============ API 配置 ============
9
+ # SSL证书配置:
10
+ # - 当前已禁用SSL验证(AsyncHttpClient.VERIFY_SSL = False)
11
+ # - 如需启用验证,修改 evol/http/async_http.py 中的 VERIFY_SSL = True
12
+
13
+ API_BASE_URL = "https://api.evolai.cn:8550"
14
+ # API_BASE_URL = "http://localhost:8550"
15
+ PRICE_AID = "evol_price_1.aid.pub"
16
+ # 备用API地址:
17
+ # API_BASE_URL = "http://api.agentcp.cn:8550" # HTTP方式
18
+ # API_BASE_URL = "http://localhost:8080" # 本地开发
19
+ # API_BASE_URL = "https://www.agentcp.cn" # 标准443端口
20
+
21
+ # ============ 其他配置 ============
22
+
23
+ REPORT_AID = "llmstat.acp.internal" if APP_ENV == "test" else "llmstat.aid.pub"
24
+ COLLECTOR_URL = (
25
+ "http://trace.acp.internal/api/v1/monitor/add" if APP_ENV == "test" else "https://trace.aid.pub/api/v1/monitor/add"
26
+ )
27
+
28
+ # ============ 日志配置 ============
29
+ # 日志文件开关配置
30
+ # 设置为 True 启用日志文件记录,False 禁用
31
+ ENABLE_MCP_SERVER_LOG = False # MCP服务器启动日志
32
+ ENABLE_CLAUDE_PROXY_LOG = False # Claude代理请求日志
33
+
34
+
35
+ class Config:
36
+ def __init__(self) -> None:
37
+ pass
@@ -0,0 +1 @@
1
+ # -*- coding: utf-8 -*-