agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.1__py3-none-any.whl

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 (450) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/METADATA +52 -20
  2. agentengine_sdk_python-0.8.1.dist-info/RECORD +644 -0
  3. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +180 -11
  5. ksadk/a2a/bootstrap.py +332 -0
  6. ksadk/a2a/card.py +15 -0
  7. ksadk/a2a/context_store.py +203 -0
  8. ksadk/a2a/control_plane.py +1056 -0
  9. ksadk/a2a/credential.py +99 -0
  10. ksadk/a2a/event_adapter.py +149 -0
  11. ksadk/a2a/executor.py +361 -137
  12. ksadk/a2a/external_transport.py +516 -0
  13. ksadk/a2a/identity.py +304 -0
  14. ksadk/a2a/ids.py +22 -0
  15. ksadk/a2a/langgraph.py +285 -0
  16. ksadk/a2a/resume_store.py +201 -0
  17. ksadk/a2a/routes.py +112 -0
  18. ksadk/a2a/server.py +102 -62
  19. ksadk/a2a/service_env.py +33 -0
  20. ksadk/a2a/space_client.py +1122 -0
  21. ksadk/a2a/task_adapter.py +423 -0
  22. ksadk/a2a/task_event_dispatcher.py +167 -0
  23. ksadk/a2a/task_event_outbox.py +326 -0
  24. ksadk/a2a/task_store.py +206 -0
  25. ksadk/a2a_card.py +101 -0
  26. ksadk/a2ui/__init__.py +27 -0
  27. ksadk/a2ui/core.py +186 -0
  28. ksadk/a2ui/models.py +166 -0
  29. ksadk/a2ui/renderer.py +198 -0
  30. ksadk/agui/__init__.py +9 -0
  31. ksadk/agui/a2ui_projection.py +92 -0
  32. ksadk/agui/agent.py +872 -0
  33. ksadk/agui/config.py +92 -0
  34. ksadk/agui/routes.py +47 -0
  35. ksadk/api/client.py +238 -204
  36. ksadk/api/environment.py +27 -0
  37. ksadk/builders/__init__.py +2 -0
  38. ksadk/builders/base.py +16 -14
  39. ksadk/builders/code_builder.py +375 -270
  40. ksadk/builders/container_builder.py +240 -200
  41. ksadk/builders/framework_requirements.py +31 -12
  42. ksadk/builders/ks3_uploader.py +60 -29
  43. ksadk/builders/managed_runtime_builder.py +173 -0
  44. ksadk/builders/mcp_builder.py +91 -92
  45. ksadk/builders/requirements_utils.py +1 -5
  46. ksadk/cli/__init__.py +97 -171
  47. ksadk/cli/cmd_a2a.py +255 -84
  48. ksadk/cli/cmd_agent.py +19 -5
  49. ksadk/cli/cmd_build.py +158 -29
  50. ksadk/cli/cmd_completion.py +47 -35
  51. ksadk/cli/cmd_config.py +267 -198
  52. ksadk/cli/cmd_create.py +507 -740
  53. ksadk/cli/cmd_dashboard.py +120 -45
  54. ksadk/cli/cmd_deploy.py +135 -59
  55. ksadk/cli/cmd_destroy.py +44 -14
  56. ksadk/cli/cmd_eval.py +386 -0
  57. ksadk/cli/cmd_files.py +63 -24
  58. ksadk/cli/cmd_hermes.py +313 -135
  59. ksadk/cli/cmd_invoke.py +184 -122
  60. ksadk/cli/cmd_launch.py +76 -28
  61. ksadk/cli/cmd_mcp.py +98 -64
  62. ksadk/cli/cmd_model.py +14 -5
  63. ksadk/cli/cmd_openclaw.py +564 -268
  64. ksadk/cli/cmd_replay.py +71 -0
  65. ksadk/cli/cmd_run.py +58 -73
  66. ksadk/cli/cmd_status.py +80 -31
  67. ksadk/cli/cmd_studio.py +110 -0
  68. ksadk/cli/cmd_version.py +20 -13
  69. ksadk/cli/cmd_web.py +95 -18
  70. ksadk/cli/deploy_utils.py +20 -20
  71. ksadk/cli/dry_run.py +7 -4
  72. ksadk/cli/env_options.py +83 -0
  73. ksadk/cli/error_utils.py +37 -12
  74. ksadk/cli/global_options.py +4 -3
  75. ksadk/cli/local_runtime.py +1 -2
  76. ksadk/cli/model_catalog.py +6 -2
  77. ksadk/cli/network_options.py +41 -19
  78. ksadk/cli/resource_common.py +6 -2
  79. ksadk/cli/runtime_bootstrap.py +51 -0
  80. ksadk/cli/storage.py +0 -1
  81. ksadk/cli/ui.py +11 -3
  82. ksadk/cli/workflow_common.py +52 -18
  83. ksadk/codex/__init__.py +12 -0
  84. ksadk/codex/client.py +1042 -0
  85. ksadk/codex/phase.py +143 -0
  86. ksadk/codex/runtime.py +940 -0
  87. ksadk/common/aicp_env.py +0 -1
  88. ksadk/common/auth.py +2 -2
  89. ksadk/common/constants.py +1 -3
  90. ksadk/common/kop_client.py +232 -0
  91. ksadk/common/llm_utils.py +17 -13
  92. ksadk/compat/__init__.py +5 -0
  93. ksadk/compat/adk_compat.py +200 -0
  94. ksadk/compat/copilotkit_a2ui.py +330 -0
  95. ksadk/configs/__init__.py +12 -14
  96. ksadk/configs/env_registry.py +661 -116
  97. ksadk/configs/global_config.py +3 -2
  98. ksadk/configs/settings.py +133 -209
  99. ksadk/conversations/__init__.py +85 -92
  100. ksadk/conversations/attachment_storage.py +16 -11
  101. ksadk/conversations/attachments.py +44 -36
  102. ksadk/conversations/compaction_pipeline.py +12 -12
  103. ksadk/conversations/compaction_prompt.py +9 -5
  104. ksadk/conversations/context.py +221 -6
  105. ksadk/conversations/message_projection.py +438 -51
  106. ksadk/conversations/model_context.py +12 -6
  107. ksadk/conversations/model_options.py +0 -1
  108. ksadk/conversations/normalize.py +20 -16
  109. ksadk/conversations/reasoning_markup.py +1 -1
  110. ksadk/conversations/runtime.py +339 -5255
  111. ksadk/conversations/runtime_compaction.py +333 -0
  112. ksadk/conversations/runtime_constants.py +27 -0
  113. ksadk/conversations/runtime_governance.py +185 -0
  114. ksadk/conversations/runtime_input.py +660 -0
  115. ksadk/conversations/runtime_invocation.py +395 -0
  116. ksadk/conversations/runtime_metadata.py +475 -0
  117. ksadk/conversations/runtime_observability.py +367 -0
  118. ksadk/conversations/runtime_payloads.py +272 -0
  119. ksadk/conversations/runtime_persistence.py +440 -0
  120. ksadk/conversations/runtime_preparation.py +426 -0
  121. ksadk/conversations/runtime_resume.py +836 -0
  122. ksadk/conversations/runtime_stream_events.py +902 -0
  123. ksadk/conversations/runtime_streaming.py +700 -0
  124. ksadk/conversations/semantic_summary.py +17 -5
  125. ksadk/conversations/session_title.py +6 -3
  126. ksadk/deployment/__init__.py +15 -16
  127. ksadk/deployment/agent_access.py +12 -23
  128. ksadk/deployment/base.py +51 -38
  129. ksadk/deployment/managed_runtime.py +33 -0
  130. ksadk/deployment/manager.py +85 -71
  131. ksadk/deployment/providers/serverless.py +379 -210
  132. ksadk/deployment/registry.py +38 -32
  133. ksadk/deployment/state.py +11 -11
  134. ksadk/deployment/ui_config.py +1 -1
  135. ksadk/detection/__init__.py +1 -1
  136. ksadk/detection/detector.py +146 -83
  137. ksadk/detection/mcp_detector.py +9 -6
  138. ksadk/evaluation/__init__.py +84 -0
  139. ksadk/evaluation/a2a_adapter.py +444 -0
  140. ksadk/evaluation/adapters.py +54 -0
  141. ksadk/evaluation/contracts.py +409 -0
  142. ksadk/evaluation/evalset.py +351 -0
  143. ksadk/evaluation/evaluators.py +461 -0
  144. ksadk/evaluation/executor.py +118 -0
  145. ksadk/evaluation/storage.py +68 -0
  146. ksadk/evaluation/target.py +73 -0
  147. ksadk/events/__init__.py +25 -0
  148. ksadk/events/parser.py +191 -0
  149. ksadk/events/replay.py +37 -0
  150. ksadk/events/runtime_event.py +273 -0
  151. ksadk/events/store.py +317 -0
  152. ksadk/harness/__init__.py +35 -0
  153. ksadk/harness/app.py +269 -0
  154. ksadk/harness/config.py +181 -0
  155. ksadk/harness/reasoner.py +105 -0
  156. ksadk/harness/runtime.py +364 -0
  157. ksadk/harness/sandbox.py +141 -0
  158. ksadk/harness/tools.py +222 -0
  159. ksadk/hermes_terminal.py +28 -12
  160. ksadk/identity/resolver.py +15 -9
  161. ksadk/ids.py +32 -0
  162. ksadk/knowledge_base/adk_tool.py +1 -1
  163. ksadk/knowledge_base/client.py +38 -33
  164. ksadk/managed_a2a_card.py +160 -0
  165. ksadk/managed_runtime.py +195 -0
  166. ksadk/markdown.py +5 -2
  167. ksadk/mcp_runtime/__init__.py +9 -6
  168. ksadk/memory/__init__.py +1 -1
  169. ksadk/memory/adk/__init__.py +2 -0
  170. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  171. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  172. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  173. ksadk/memory/adk/backends/sdk_ltm_backend.py +36 -36
  174. ksadk/memory/adk/long_term_memory.py +34 -37
  175. ksadk/memory/adk/resilient_session_service.py +4 -5
  176. ksadk/memory/adk/short_term_memory.py +12 -21
  177. ksadk/memory/adk_tool.py +3 -2
  178. ksadk/memory/backends/base.py +19 -19
  179. ksadk/memory/backends/memory.py +24 -25
  180. ksadk/memory/backends/redis.py +31 -30
  181. ksadk/memory/langchain_tool.py +2 -1
  182. ksadk/memory/manager.py +52 -47
  183. ksadk/memory/service.py +16 -6
  184. ksadk/memory/tool.py +4 -0
  185. ksadk/model_policy.py +15 -7
  186. ksadk/model_proxy/__init__.py +51 -0
  187. ksadk/model_proxy/bootstrap.py +80 -0
  188. ksadk/model_proxy/cache.py +165 -0
  189. ksadk/model_proxy/config.py +66 -0
  190. ksadk/model_proxy/demo_webui.py +115 -0
  191. ksadk/model_proxy/detect.py +145 -0
  192. ksadk/model_proxy/gate.py +68 -0
  193. ksadk/model_proxy/namespace.py +201 -0
  194. ksadk/model_proxy/protocol_proxy.py +22 -0
  195. ksadk/model_proxy/server.py +443 -0
  196. ksadk/model_proxy/transform.py +735 -0
  197. ksadk/openclaw_gateway.py +29 -14
  198. ksadk/runners/adk_runner.py +354 -146
  199. ksadk/runners/base_runner.py +71 -29
  200. ksadk/runners/deepagents_runner.py +0 -1
  201. ksadk/runners/factory.py +18 -5
  202. ksadk/runners/langchain_runner.py +29 -742
  203. ksadk/runners/langgraph_runner.py +417 -97
  204. ksadk/runners/patch_langchain.py +16 -16
  205. ksadk/runners/remote_runner.py +134 -33
  206. ksadk/runners/usage_accumulator.py +1 -0
  207. ksadk/runners/utils/__init__.py +0 -10
  208. ksadk/runners/utils/loader.py +23 -7
  209. ksadk/runtime/__init__.py +67 -0
  210. ksadk/runtime/adapter.py +412 -0
  211. ksadk/runtime/conversation_execution.py +553 -0
  212. ksadk/runtime/executor.py +251 -0
  213. ksadk/runtime/factory.py +156 -0
  214. ksadk/runtime/framework_adapters.py +118 -0
  215. ksadk/runtime/launch.py +48 -0
  216. ksadk/runtime/preprocessing.py +131 -0
  217. ksadk/runtime/runner_adapter.py +1032 -0
  218. ksadk/runtime/runner_loading.py +36 -0
  219. ksadk/runtime_context.py +18 -3
  220. ksadk/runtime_state.py +0 -1
  221. ksadk/sandbox/__init__.py +4 -1
  222. ksadk/sandbox/backends/__init__.py +4 -1
  223. ksadk/sandbox/backends/e2b.py +13 -5
  224. ksadk/sandbox/backends/local_process.py +11 -3
  225. ksadk/sandbox/base.py +10 -15
  226. ksadk/sandbox/factory.py +14 -4
  227. ksadk/sandbox/registry.py +57 -6
  228. ksadk/server/__init__.py +39 -4
  229. ksadk/server/api_models.py +15 -5
  230. ksadk/server/app.py +24 -3928
  231. ksadk/server/composition.py +47 -0
  232. ksadk/server/factory.py +622 -0
  233. ksadk/server/routes/__init__.py +1 -0
  234. ksadk/server/routes/checkpoint_resolution.py +116 -0
  235. ksadk/server/routes/common.py +682 -0
  236. ksadk/server/routes/control.py +331 -0
  237. ksadk/server/routes/dependencies.py +98 -0
  238. ksadk/server/routes/misc.py +425 -0
  239. ksadk/server/routes/models.py +451 -0
  240. ksadk/server/routes/openai_compat.py +229 -0
  241. ksadk/server/routes/projection.py +848 -0
  242. ksadk/server/routes/routers.py +52 -0
  243. ksadk/server/routes/run.py +519 -0
  244. ksadk/server/routes/sessions.py +644 -0
  245. ksadk/server/routes/streaming.py +265 -0
  246. ksadk/server/routes/workspace.py +414 -0
  247. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-CakCqxEN.js} +1 -1
  248. ksadk/server/static/assets/CodeBlock-CynLknyO.js +9 -0
  249. ksadk/server/static/assets/MathMessageMarkdown-3sQdOysS.js +8 -0
  250. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +303 -0
  251. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +1 -0
  252. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-DrgjcKhl.js} +1 -1
  253. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +1 -0
  254. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-BXoVRbQ6.js} +1 -1
  255. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-BnaB3Ywv.js} +1 -1
  256. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-Dw4weZcp.js} +1 -1
  257. ksadk/server/static/assets/channel-Dt3rQTFI.js +1 -0
  258. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-ChjpLK7j.js} +1 -1
  259. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-B9drTgOW.js} +1 -1
  260. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-CK4ROATy.js} +1 -1
  261. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B9KtTTgw.js} +1 -1
  262. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-1O1mki3m.js} +1 -1
  263. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-B_fH2YuH.js} +1 -1
  264. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D6rFLaVV.js} +1 -1
  265. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +1 -0
  266. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +1 -0
  267. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +1 -0
  268. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-ChNs_Mdk.js} +1 -1
  269. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-D0QXg_MQ.js} +1 -1
  270. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-DBDDKwBQ.js} +1 -1
  271. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-BkwDOxmO.js} +1 -1
  272. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Bv8waYvY.js} +1 -1
  273. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-e1VECDdu.js} +1 -1
  274. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-Ds9adfRl.js} +1 -1
  275. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-4N2NMVYg.js} +1 -1
  276. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-B-jNR6Vn.js} +1 -1
  277. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-B5J2uhNk.js} +1 -1
  278. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-B5oS1zcj.js} +1 -1
  279. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BB3-OwTQ.js} +1 -1
  280. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-BIlKoW0k.js} +1 -1
  281. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-BjOdlDjj.js} +1 -1
  282. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-C1sz5Eo3.js} +1 -1
  283. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-CWV4lDr1.js} +1 -1
  284. ksadk/server/static/assets/{dist-D-xOD048.js → dist-CmZHzlwZ.js} +1 -1
  285. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-D6MpCZtz.js} +1 -1
  286. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-DJN_6Y39.js} +1 -1
  287. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-DQU9EWw-.js} +1 -1
  288. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-DWKByxWV.js} +1 -1
  289. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-Dli7qW-B.js} +1 -1
  290. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-DsHPdk3W.js} +1 -1
  291. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-X4TnqwOK.js} +1 -1
  292. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-_pHPTyZ-.js} +1 -1
  293. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-fhOuWds5.js} +1 -1
  294. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-gLnrGsoU.js} +1 -1
  295. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-j6Dxmf_j.js} +1 -1
  296. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-o2OVmKvt.js} +1 -1
  297. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-BPItFKH6.js} +1 -1
  298. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +1 -0
  299. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-BbYB9w5Y.js} +1 -1
  300. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-TQXa0KXv.js} +1 -1
  301. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +1 -0
  302. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-bKblCnpa.js} +1 -1
  303. ksadk/server/static/assets/index-R52pJJvg.js +177 -0
  304. ksadk/server/static/assets/index-jJr3_955.css +2 -0
  305. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +1 -0
  306. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-BGVT7J_i.js} +1 -1
  307. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-K0OOfVna.js} +1 -1
  308. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-8LeOJaZp.js} +1 -1
  309. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-C6uCgZrW.js} +1 -1
  310. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-CYWseY5E.js} +1 -1
  311. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-hdBcYzM8.js} +1 -1
  312. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-BWrDjSZM.js} +2 -2
  313. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-Bjy_2v4_.js} +1 -1
  314. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +1 -0
  315. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +1 -0
  316. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-GmmqNiVH.js} +1 -1
  317. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-BmkRbwCg.js} +1 -1
  318. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +1 -0
  319. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DSWFqL7c.js} +1 -1
  320. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-l6iXmU65.js} +1 -1
  321. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-Cq6UBeQB.js} +1 -1
  322. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-qzTQpg3Y.js} +1 -1
  323. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +1 -0
  324. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-DEz24vV0.js} +1 -1
  325. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +1 -0
  326. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +1 -0
  327. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-CMCixki2.js} +1 -1
  328. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +1 -0
  329. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-CVzB8F9K.js} +1 -1
  330. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-BFBqBLc1.js} +1 -1
  331. ksadk/server/static/index.html +2 -2
  332. ksadk/server/terminal_sessions.py +111 -58
  333. ksadk/sessions/__init__.py +69 -19
  334. ksadk/sessions/base.py +31 -11
  335. ksadk/sessions/continuity.py +2 -3
  336. ksadk/sessions/in_memory.py +46 -2
  337. ksadk/sessions/local_service.py +148 -17
  338. ksadk/sessions/postgres_service.py +143 -25
  339. ksadk/sessions/resilient.py +36 -8
  340. ksadk/skills/models.py +17 -5
  341. ksadk/skills/package_store.py +5 -2
  342. ksadk/skills/runtime/agent.py +20 -5
  343. ksadk/skills/runtime/artifacts.py +1 -5
  344. ksadk/skills/runtime/backends/e2b.py +10 -4
  345. ksadk/skills/runtime/backends/local.py +15 -3
  346. ksadk/skills/runtime/base.py +1 -2
  347. ksadk/skills/runtime/executor.py +10 -3
  348. ksadk/skills/runtime/factory.py +4 -2
  349. ksadk/skills/runtime/loader.py +1 -2
  350. ksadk/skills/runtime/registry.py +15 -10
  351. ksadk/skills/runtime/request.py +3 -1
  352. ksadk/skills/service_client.py +47 -16
  353. ksadk/skills/tool_defs.py +15 -10
  354. ksadk/studio/__init__.py +5 -0
  355. ksadk/studio/agent_avatar_assets.py +120 -0
  356. ksadk/studio/agent_lifecycle.py +51 -0
  357. ksadk/studio/api.py +1046 -0
  358. ksadk/studio/api_catalog_routes.py +324 -0
  359. ksadk/studio/api_contracts.py +177 -0
  360. ksadk/studio/api_helpers.py +132 -0
  361. ksadk/studio/authoring.py +524 -0
  362. ksadk/studio/authoring_coordinator.py +285 -0
  363. ksadk/studio/builder.py +320 -0
  364. ksadk/studio/capabilities.py +351 -0
  365. ksadk/studio/cloud.py +278 -0
  366. ksadk/studio/codex_agent_service.py +583 -0
  367. ksadk/studio/codex_builder.py +324 -0
  368. ksadk/studio/codex_manifest.py +278 -0
  369. ksadk/studio/codex_run.py +352 -0
  370. ksadk/studio/compiler.py +189 -0
  371. ksadk/studio/contracts.py +644 -0
  372. ksadk/studio/errors.py +47 -0
  373. ksadk/studio/evaluation.py +192 -0
  374. ksadk/studio/event_store.py +284 -0
  375. ksadk/studio/framework_run.py +114 -0
  376. ksadk/studio/identifiers.py +33 -0
  377. ksadk/studio/mcp_runtime.py +229 -0
  378. ksadk/studio/model_client.py +543 -0
  379. ksadk/studio/model_profile_service.py +214 -0
  380. ksadk/studio/operations.py +243 -0
  381. ksadk/studio/otel_trace.py +754 -0
  382. ksadk/studio/pagination.py +182 -0
  383. ksadk/studio/python_tool_inspection.py +183 -0
  384. ksadk/studio/repository.py +306 -0
  385. ksadk/studio/resource_catalog.py +1217 -0
  386. ksadk/studio/run_service.py +707 -0
  387. ksadk/studio/runtime_catalog.py +74 -0
  388. ksadk/studio/runtime_source.py +339 -0
  389. ksadk/studio/service.py +1141 -0
  390. ksadk/studio/shared_web.py +994 -0
  391. ksadk/studio/skill_discovery.py +628 -0
  392. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  393. ksadk/studio/static/assets/index-CaEN0eTR.css +1 -0
  394. ksadk/studio/static/assets/index-DI2eY_NH.js +252 -0
  395. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  396. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  397. ksadk/studio/static/index.html +15 -0
  398. ksadk/studio/templates.py +630 -0
  399. ksadk/studio/validator.py +246 -0
  400. ksadk/studio/workspace.py +137 -0
  401. ksadk/terminal_exec_policy.py +3 -4
  402. ksadk/tools/gateway.py +101 -15
  403. ksadk/tools/result_budget.py +12 -4
  404. ksadk/toolsets/__init__.py +161 -37
  405. ksadk/toolsets/a2a.py +426 -0
  406. ksadk/toolsets/platform.py +21 -5
  407. ksadk/toolsets/sandbox.py +82 -16
  408. ksadk/toolsets/skills.py +200 -39
  409. ksadk/toolsets/web.py +123 -26
  410. ksadk/toolsets/workspace.py +212 -101
  411. ksadk/tracing/__init__.py +19 -21
  412. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  413. ksadk/tracing/setup.py +135 -506
  414. ksadk/tracing/span_utils.py +0 -41
  415. ksadk/tui/loop.py +78 -30
  416. ksadk/tui/stream_render.py +1 -0
  417. ksadk/ui_config.py +5 -3
  418. ksadk/version.py +1 -1
  419. ksadk_runtime_common/memory_backend/registry.py +56 -56
  420. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  421. ksadk_runtime_common/workspace_files/router.py +8 -2
  422. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  423. ksadk/a2a/card_builder.py +0 -64
  424. ksadk/a2a/client.py +0 -309
  425. ksadk/runners/utils/langfuse.py +0 -230
  426. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  427. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  428. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  429. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  430. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  431. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  432. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  433. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  434. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  435. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  436. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  437. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  438. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  439. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  440. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  441. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  442. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  443. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  444. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  445. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  446. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  447. ksadk/tracing/exporters/langfuse_exporter.py +0 -445
  448. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/entry_points.txt +0 -0
  449. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/licenses/LICENSE +0 -0
  450. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/top_level.txt +0 -0
@@ -4,115 +4,121 @@
4
4
  使用装饰器模式自动注册 Provider,支持动态扩展。
5
5
  """
6
6
 
7
- from typing import Dict, Type, List, Optional
7
+ from typing import Dict, List, Optional, Type
8
+
8
9
  from ksadk.deployment.base import BaseDeployProvider
9
10
 
10
11
 
11
12
  class DeployProviderRegistry:
12
13
  """Provider 注册表
13
-
14
+
14
15
  使用方式:
15
16
  @DeployProviderRegistry.register("my-provider")
16
17
  class MyProvider(BaseDeployProvider):
17
18
  ...
18
19
  """
19
-
20
+
20
21
  _providers: Dict[str, Type[BaseDeployProvider]] = {}
21
22
  _instances: Dict[str, BaseDeployProvider] = {}
22
-
23
+
23
24
  @classmethod
24
25
  def register(cls, name: str):
25
26
  """装饰器: 注册 Provider
26
-
27
+
27
28
  Args:
28
29
  name: Provider 名称 (如 "serverless", "k8s", "docker")
29
30
  """
31
+
30
32
  def decorator(provider_class: Type[BaseDeployProvider]):
31
33
  if not issubclass(provider_class, BaseDeployProvider):
32
34
  raise TypeError(f"{provider_class} must inherit from BaseDeployProvider")
33
-
35
+
34
36
  provider_class.name = name
35
37
  cls._providers[name] = provider_class
36
38
  return provider_class
37
-
39
+
38
40
  return decorator
39
-
41
+
40
42
  @classmethod
41
- def get(cls, name: str, config: Dict = None) -> BaseDeployProvider:
43
+ def get(cls, name: str, config: Optional[Dict] = None) -> BaseDeployProvider:
42
44
  """获取 Provider 实例
43
-
45
+
44
46
  Args:
45
47
  name: Provider 名称
46
48
  config: Provider 配置
47
-
49
+
48
50
  Returns:
49
51
  Provider 实例
50
52
  """
51
53
  if name not in cls._providers:
52
54
  available = ", ".join(cls._providers.keys())
53
55
  raise ValueError(f"Unknown provider: {name}. Available: {available}")
54
-
56
+
55
57
  # 缓存实例 (相同 name 返回相同实例)
56
58
  cache_key = f"{name}:{hash(str(config))}"
57
59
  if cache_key not in cls._instances:
58
60
  cls._instances[cache_key] = cls._providers[name](config)
59
-
61
+
60
62
  return cls._instances[cache_key]
61
-
63
+
62
64
  @classmethod
63
65
  def get_class(cls, name: str) -> Type[BaseDeployProvider]:
64
66
  """获取 Provider 类 (不实例化)
65
-
67
+
66
68
  Args:
67
69
  name: Provider 名称
68
-
70
+
69
71
  Returns:
70
72
  Provider 类
71
73
  """
72
74
  if name not in cls._providers:
73
75
  raise ValueError(f"Unknown provider: {name}")
74
76
  return cls._providers[name]
75
-
77
+
76
78
  @classmethod
77
79
  def list_providers(cls) -> List[str]:
78
80
  """列出所有已注册的 Provider 名称
79
-
81
+
80
82
  Returns:
81
83
  Provider 名称列表
82
84
  """
83
85
  return list(cls._providers.keys())
84
-
86
+
85
87
  @classmethod
86
88
  def get_provider_info(cls) -> List[Dict]:
87
89
  """获取所有 Provider 的详细信息
88
-
90
+
89
91
  Returns:
90
92
  Provider 信息列表
91
93
  """
92
94
  result = []
93
95
  for name, provider_class in cls._providers.items():
94
- result.append({
95
- "name": name,
96
- "display_name": getattr(provider_class, "display_name", name),
97
- "description": getattr(provider_class, "description", ""),
98
- "supports_streaming": getattr(provider_class, "supports_streaming", False),
99
- "supports_scaling": getattr(provider_class, "supports_scaling", False),
100
- "requires_image_registry": getattr(provider_class, "requires_image_registry", False),
101
- })
96
+ result.append(
97
+ {
98
+ "name": name,
99
+ "display_name": getattr(provider_class, "display_name", name),
100
+ "description": getattr(provider_class, "description", ""),
101
+ "supports_streaming": getattr(provider_class, "supports_streaming", False),
102
+ "supports_scaling": getattr(provider_class, "supports_scaling", False),
103
+ "requires_image_registry": getattr(
104
+ provider_class, "requires_image_registry", False
105
+ ),
106
+ }
107
+ )
102
108
  return result
103
-
109
+
104
110
  @classmethod
105
111
  def has_provider(cls, name: str) -> bool:
106
112
  """检查 Provider 是否存在
107
-
113
+
108
114
  Args:
109
115
  name: Provider 名称
110
-
116
+
111
117
  Returns:
112
118
  是否存在
113
119
  """
114
120
  return name in cls._providers
115
-
121
+
116
122
  @classmethod
117
123
  def clear(cls):
118
124
  """清空注册表 (主要用于测试)"""
ksadk/deployment/state.py CHANGED
@@ -4,11 +4,11 @@
4
4
  用于管理本地 .agentengine.state 文件,记录已部署的 Agent/MCP 信息。
5
5
  """
6
6
 
7
- import yaml
8
- from pathlib import Path
9
- from typing import Optional, Dict, Any
10
7
  from datetime import datetime
8
+ from pathlib import Path
9
+ from typing import Any, Dict, Optional
11
10
 
11
+ import yaml
12
12
 
13
13
  STATE_FILE_NAME = ".agentengine.state"
14
14
 
@@ -23,9 +23,9 @@ def load_state(project_dir: Path) -> Dict[str, Any]:
23
23
  state_file = get_state_file_path(project_dir)
24
24
  if not state_file.exists():
25
25
  return {}
26
-
26
+
27
27
  try:
28
- with open(state_file, 'r', encoding='utf-8') as f:
28
+ with open(state_file, "r", encoding="utf-8") as f:
29
29
  return yaml.safe_load(f) or {}
30
30
  except Exception:
31
31
  return {}
@@ -34,12 +34,12 @@ def load_state(project_dir: Path) -> Dict[str, Any]:
34
34
  def save_state(project_dir: Path, data: Dict[str, Any]) -> None:
35
35
  """保存状态文件"""
36
36
  state_file = get_state_file_path(project_dir)
37
-
37
+
38
38
  # 自动添加 updated_at
39
39
  if "updated_at" not in data:
40
40
  data["updated_at"] = datetime.now().isoformat()
41
-
42
- with open(state_file, 'w', encoding='utf-8') as f:
41
+
42
+ with open(state_file, "w", encoding="utf-8") as f:
43
43
  yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
44
44
 
45
45
 
@@ -51,9 +51,9 @@ def update_state(project_dir: Path, updates: Dict[str, Any]) -> Dict[str, Any]:
51
51
  return current_state
52
52
 
53
53
 
54
- def clear_state(project_dir: Path, key: str = None) -> bool:
54
+ def clear_state(project_dir: Path, key: Optional[str] = None) -> bool:
55
55
  """清理状态文件
56
-
56
+
57
57
  Args:
58
58
  project_dir: 项目目录
59
59
  key: 如果指定,仅当状态中的 ID 与 key 匹配时才删除
@@ -64,7 +64,7 @@ def clear_state(project_dir: Path, key: str = None) -> bool:
64
64
  state_file = get_state_file_path(project_dir)
65
65
  if not state_file.exists():
66
66
  return False
67
-
67
+
68
68
  if key:
69
69
  # 检查是否匹配
70
70
  state = load_state(project_dir)
@@ -2,13 +2,13 @@
2
2
 
3
3
  from ksadk.ui_config import ( # noqa: F401
4
4
  SUPPORTED_UI_PROFILES,
5
- UIConfig,
6
5
  UI_PROFILE_ADK,
7
6
  UI_PROFILE_AUTO,
8
7
  UI_PROFILE_CUSTOM,
9
8
  UI_PROFILE_HERMES,
10
9
  UI_PROFILE_LANGCHAIN,
11
10
  UI_PROFILE_OPENCLAW,
11
+ UIConfig,
12
12
  default_ui_path,
13
13
  extract_ui_state,
14
14
  infer_ui_profile_from_framework,
@@ -2,6 +2,6 @@
2
2
  KsADK Detection - 框架自动检测模块
3
3
  """
4
4
 
5
- from ksadk.detection.detector import FrameworkDetector, DetectionResult, FrameworkType
5
+ from ksadk.detection.detector import DetectionResult, FrameworkDetector, FrameworkType
6
6
 
7
7
  __all__ = ["FrameworkDetector", "DetectionResult", "FrameworkType"]
@@ -4,7 +4,7 @@
4
4
 
5
5
  import ast
6
6
  import json
7
- from dataclasses import dataclass
7
+ from dataclasses import dataclass, field
8
8
  from enum import Enum
9
9
  from pathlib import Path
10
10
  from typing import Optional
@@ -20,6 +20,8 @@ class FrameworkType(Enum):
20
20
  LANGGRAPH = "langgraph"
21
21
  DEEPAGENTS = "deepagents"
22
22
  HERMES = "hermes"
23
+ FASTMCP = "fastmcp"
24
+ CODEX = "codex"
23
25
  UNKNOWN = "unknown"
24
26
 
25
27
 
@@ -34,6 +36,9 @@ class DetectionResult:
34
36
  agent_variable: str = "root_agent"
35
37
  runner_class: str = ""
36
38
  confidence: float = 0.0
39
+ # 配置文件的原始内容(ksadk.yaml/agentengine.yaml),供 runner 读 model/prompt 等
40
+ # 真实生效字段(codex 无 root_agent,配置全靠它)。默认空 dict,不影响既有构造。
41
+ raw_config: dict = field(default_factory=dict)
37
42
 
38
43
  @property
39
44
  def is_valid(self) -> bool:
@@ -44,6 +49,14 @@ class FrameworkDetector:
44
49
  """框架检测器"""
45
50
 
46
51
  _ENTRY_FILES = ("agent.py", "main.py", "app.py")
52
+ _LANGCHAIN_MODULES = frozenset(
53
+ {
54
+ "langchain",
55
+ "langchain_openai",
56
+ "langchain_core",
57
+ "langchain_community",
58
+ }
59
+ )
47
60
 
48
61
  def __init__(self, project_dir: str):
49
62
  self.project_dir = Path(project_dir).resolve()
@@ -56,6 +69,11 @@ class FrameworkDetector:
56
69
  if config_result:
57
70
  return config_result
58
71
 
72
+ # 1.5 codex.yaml 标志文件(fallback 自动探测,优先级低于 ksadk.yaml framework)
73
+ codex_result = self._check_codex_yaml()
74
+ if codex_result:
75
+ return codex_result
76
+
59
77
  graph_config_result = self._check_langgraph_json()
60
78
  if graph_config_result:
61
79
  return graph_config_result
@@ -104,12 +122,15 @@ class FrameworkDetector:
104
122
  "langgraph": FrameworkType.LANGGRAPH,
105
123
  "deepagents": FrameworkType.DEEPAGENTS,
106
124
  "hermes": FrameworkType.HERMES,
125
+ "codex": FrameworkType.CODEX,
107
126
  }.get(framework, FrameworkType.UNKNOWN)
108
127
 
109
128
  artifact_type = str(config.get("artifact_type") or "").strip().lower()
110
129
  is_hermes_container = (
111
130
  framework_type == FrameworkType.HERMES and artifact_type == "container"
112
131
  )
132
+ # codex 无 root_agent 变量(agent 逻辑在 prompt),跳过 entry_exposes_variable 校验
133
+ is_codex = framework_type == FrameworkType.CODEX
113
134
  default_entry_point = (
114
135
  "runtime/app.py"
115
136
  if is_hermes_container and (self.project_dir / "runtime" / "app.py").is_file()
@@ -119,10 +140,13 @@ class FrameworkDetector:
119
140
  agent_variable = config.get("agent_variable", "root_agent")
120
141
  runner_class = str(config.get("runner_class") or "").strip()
121
142
  entry_path = self.project_dir / str(entry_point).replace("\\", "/")
122
- if not entry_path.exists() or not entry_path.is_file():
143
+ # codex 无 agent.py(逻辑在 prompt),容忍 entry_point 不存在
144
+ if not is_codex and (not entry_path.exists() or not entry_path.is_file()):
123
145
  return None
124
- if not is_hermes_container and not self._entry_exposes_variable(
125
- entry_path, agent_variable
146
+ if (
147
+ not is_codex
148
+ and not is_hermes_container
149
+ and not self._entry_exposes_variable(entry_path, agent_variable)
126
150
  ):
127
151
  return None
128
152
  package = str(config.get("package") or "").strip()
@@ -141,10 +165,30 @@ class FrameworkDetector:
141
165
  agent_variable=agent_variable,
142
166
  runner_class=runner_class,
143
167
  confidence=1.0,
168
+ raw_config=config,
144
169
  )
145
170
  except Exception:
146
171
  return None
147
172
 
173
+ def _check_codex_yaml(self) -> Optional[DetectionResult]:
174
+ """fallback:项目根有 codex.yaml 即判 CODEX(最小标志文件,可含 model/sandbox)。
175
+
176
+ 保守规则,不做源码 import 扫描(避免误判普通 Python 项目)。优先级低于
177
+ ksadk.yaml framework: codex 显式声明。
178
+ """
179
+ codex_path = self.project_dir / "codex.yaml"
180
+ if not codex_path.exists():
181
+ return None
182
+ return DetectionResult(
183
+ type=FrameworkType.CODEX,
184
+ name=self.project_dir.name,
185
+ entry_point="",
186
+ package_path=str(self.project_dir),
187
+ agent_variable="",
188
+ runner_class="",
189
+ confidence=0.9,
190
+ )
191
+
148
192
  def _find_package_dir(self) -> Optional[Path]:
149
193
  """查找 Python 包目录"""
150
194
  # 优先查找与项目同名的包 (下划线版本)
@@ -270,19 +314,16 @@ class FrameworkDetector:
270
314
  ) -> FrameworkType:
271
315
  try:
272
316
  content = entry_path.read_text(encoding="utf-8-sig")
317
+ except Exception:
318
+ return fallback
319
+ try:
273
320
  tree = ast.parse(content, filename=str(entry_path))
274
321
  imports = self._extract_imports(tree)
322
+ calls = self._extract_call_names(tree)
323
+ framework = self._classify(imports, calls, content)
275
324
  except Exception:
276
- return fallback
277
- if self._is_deepagents(imports, content):
278
- return FrameworkType.DEEPAGENTS
279
- if self._is_langgraph(imports, content):
280
- return FrameworkType.LANGGRAPH
281
- if self._is_adk(imports, content):
282
- return FrameworkType.ADK
283
- if self._is_langchain(imports, content):
284
- return FrameworkType.LANGCHAIN
285
- return fallback
325
+ framework = self._classify_from_strings(content)
326
+ return framework if framework != FrameworkType.UNKNOWN else fallback
286
327
 
287
328
  def _check_langgraph_json(self) -> Optional[DetectionResult]:
288
329
  config_path = self.project_dir / "langgraph.json"
@@ -318,71 +359,79 @@ class FrameworkDetector:
318
359
 
319
360
  def _analyze_code(self, agent_file: Path, package_path: Path) -> DetectionResult:
320
361
  """分析代码确定框架类型"""
362
+ entry_point = str(agent_file.relative_to(self.project_dir))
321
363
  try:
322
364
  # 使用 utf-8-sig 自动处理 BOM,兼容 Windows/编辑器带 BOM 的脚本
323
365
  content = agent_file.read_text(encoding="utf-8-sig")
324
- tree = ast.parse(content, filename=str(agent_file))
325
366
  except Exception:
326
367
  return DetectionResult(
327
368
  type=FrameworkType.UNKNOWN,
328
369
  name=self.project_dir.name,
329
- entry_point=str(agent_file.relative_to(self.project_dir)),
330
- package_path=str(package_path),
331
- )
332
-
333
- imports = self._extract_imports(tree)
334
-
335
- # 检测 ADK
336
- if self._is_adk(imports, content):
337
- return DetectionResult(
338
- type=FrameworkType.ADK,
339
- name=package_path.name,
340
- entry_point=str(agent_file.relative_to(self.project_dir)),
341
- package_path=str(package_path),
342
- agent_variable="root_agent",
343
- confidence=0.9,
344
- )
345
-
346
- # 检测 DeepAgents (LangChain 生态, 底层基于 LangGraph)
347
- if self._is_deepagents(imports, content):
348
- return DetectionResult(
349
- type=FrameworkType.DEEPAGENTS,
350
- name=package_path.name,
351
- entry_point=str(agent_file.relative_to(self.project_dir)),
352
- package_path=str(package_path),
353
- agent_variable="root_agent",
354
- confidence=0.9,
355
- )
356
-
357
- # 检测 LangGraph
358
- if self._is_langgraph(imports, content):
359
- return DetectionResult(
360
- type=FrameworkType.LANGGRAPH,
361
- name=package_path.name,
362
- entry_point=str(agent_file.relative_to(self.project_dir)),
370
+ entry_point=entry_point,
363
371
  package_path=str(package_path),
364
- agent_variable="root_agent",
365
- confidence=0.9,
366
372
  )
367
373
 
368
- # 检测 LangChain
369
- if self._is_langchain(imports, content):
370
- return DetectionResult(
371
- type=FrameworkType.LANGCHAIN,
372
- name=package_path.name,
373
- entry_point=str(agent_file.relative_to(self.project_dir)),
374
- package_path=str(package_path),
375
- agent_variable="root_agent",
376
- confidence=0.8,
377
- )
374
+ calls: set = set()
375
+ try:
376
+ tree = ast.parse(content, filename=str(agent_file))
377
+ imports = self._extract_imports(tree)
378
+ calls = self._extract_call_names(tree)
379
+ framework = self._classify(imports, calls, content)
380
+ except Exception:
381
+ # AST 解析失败(语法错误等)时退化为字符串判定,避免直接判 UNKNOWN
382
+ framework = self._classify_from_strings(content)
378
383
 
384
+ name = package_path.name if framework != FrameworkType.UNKNOWN else self.project_dir.name
379
385
  return DetectionResult(
380
- type=FrameworkType.UNKNOWN,
381
- name=self.project_dir.name,
382
- entry_point=str(agent_file.relative_to(self.project_dir)),
386
+ type=framework,
387
+ name=name,
388
+ entry_point=entry_point,
383
389
  package_path=str(package_path),
390
+ agent_variable="root_agent",
391
+ confidence=self._confidence_for(framework, calls),
384
392
  )
385
393
 
394
+ def _classify(self, imports: set, calls: set, content: str) -> FrameworkType:
395
+ """AST 级统一分类,顺序:
396
+ ADK → DeepAgents → LangChain(高层) → LangGraph → LangChain(legacy) → UNKNOWN"""
397
+ if self._is_adk(imports, content):
398
+ return FrameworkType.ADK
399
+ if self._is_deepagents(imports, calls, content):
400
+ return FrameworkType.DEEPAGENTS
401
+ if self._is_langchain_high_level(imports, calls):
402
+ return FrameworkType.LANGCHAIN
403
+ if self._is_langgraph(calls):
404
+ return FrameworkType.LANGGRAPH
405
+ if self._is_langchain_legacy(imports, calls):
406
+ return FrameworkType.LANGCHAIN
407
+ return FrameworkType.UNKNOWN
408
+
409
+ def _classify_from_strings(self, content: str) -> FrameworkType:
410
+ """AST 解析失败时的字符串兜底,顺序与 _classify 保持一致"""
411
+ if "google.adk" in content or "from google.adk" in content:
412
+ return FrameworkType.ADK
413
+ if "deepagents" in content or "create_deep_agent(" in content:
414
+ return FrameworkType.DEEPAGENTS
415
+ if "create_agent(" in content:
416
+ return FrameworkType.LANGCHAIN
417
+ if (
418
+ "StateGraph" in content
419
+ or "langgraph.graph" in content
420
+ or "create_react_agent(" in content
421
+ ):
422
+ return FrameworkType.LANGGRAPH
423
+ if any(m in content for m in self._LANGCHAIN_MODULES):
424
+ return FrameworkType.LANGCHAIN
425
+ return FrameworkType.UNKNOWN
426
+
427
+ def _confidence_for(self, framework: FrameworkType, calls: set) -> float:
428
+ if framework == FrameworkType.UNKNOWN:
429
+ return 0.0
430
+ if framework == FrameworkType.LANGCHAIN:
431
+ # 高层(create_agent 调用) 0.9,legacy 兜底 0.8
432
+ return 0.9 if "create_agent" in calls else 0.8
433
+ return 0.9
434
+
386
435
  def _extract_imports(self, tree: ast.AST) -> set:
387
436
  """提取导入的模块"""
388
437
  imports = set()
@@ -395,6 +444,19 @@ class FrameworkDetector:
395
444
  imports.add(node.module.split(".")[0])
396
445
  return imports
397
446
 
447
+ def _extract_call_names(self, tree: ast.AST) -> set:
448
+ """提取代码中实际调用的函数/方法名(AST 级,避免注释/字符串误判)"""
449
+ calls = set()
450
+ for node in ast.walk(tree):
451
+ if not isinstance(node, ast.Call):
452
+ continue
453
+ func = node.func
454
+ if isinstance(func, ast.Name):
455
+ calls.add(func.id)
456
+ elif isinstance(func, ast.Attribute):
457
+ calls.add(func.attr)
458
+ return calls
459
+
398
460
  def _is_adk(self, imports: set, content: str) -> bool:
399
461
  """检测是否为 ADK 项目"""
400
462
  # 检查 google.adk 导入
@@ -402,30 +464,31 @@ class FrameworkDetector:
402
464
  return True
403
465
  return False
404
466
 
405
- def _is_langgraph(self, imports: set, content: str) -> bool:
406
- """检测是否为 LangGraph 项目"""
407
- if "langgraph" in imports:
408
- return True
409
- if "StateGraph" in content or "langgraph.graph" in content:
410
- return True
411
- return False
467
+ def _is_langgraph(self, calls: set) -> bool:
468
+ """检测是否为 LangGraph 项目:直接编排 StateGraph 或调用 create_react_agent。
469
+ 不再用 `"StateGraph" in content` 字符串包含,避免注释/类型注解误命中
470
+ 导致 deepagents/langchain 塌缩。"""
471
+ return "StateGraph" in calls or "create_react_agent" in calls
412
472
 
413
- def _is_langchain(self, imports: set, content: str) -> bool:
414
- """检测是否为 LangChain 项目"""
415
- langchain_modules = {
416
- "langchain",
417
- "langchain_openai",
418
- "langchain_core",
419
- "langchain_community",
420
- }
421
- if langchain_modules & imports:
422
- return True
423
- return False
473
+ def _is_langchain_high_level(self, imports: set, calls: set) -> bool:
474
+ """新版 LangChain 高层 API:langchain 系 import 且调用 create_agent。"""
475
+ if not (self._LANGCHAIN_MODULES & imports):
476
+ return False
477
+ return "create_agent" in calls
478
+
479
+ def _is_langchain_legacy(self, imports: set, calls: set) -> bool:
480
+ """LangChain legacy 兜底:langchain 系 import 且无 LangGraph 直接编排
481
+ 信号(覆盖 LCEL 链等旧用法)。"""
482
+ if not (self._LANGCHAIN_MODULES & imports):
483
+ return False
484
+ return "StateGraph" not in calls and "create_react_agent" not in calls
424
485
 
425
- def _is_deepagents(self, imports: set, content: str) -> bool:
486
+ def _is_deepagents(self, imports: set, calls: set, content: str) -> bool:
426
487
  """检测是否为 DeepAgents 项目"""
427
488
  if "deepagents" in imports:
428
489
  return True
490
+ if "create_deep_agent" in calls:
491
+ return True
429
492
  if "from deepagents import" in content or "create_deep_agent(" in content:
430
493
  return True
431
494
  return False
@@ -3,12 +3,14 @@ MCP 检测器 - 自动检测 FastMCP 项目
3
3
  """
4
4
 
5
5
  import ast
6
- from dataclasses import dataclass
6
+ from dataclasses import dataclass, field
7
7
  from pathlib import Path
8
8
  from typing import List, Optional
9
9
 
10
10
  import yaml
11
11
 
12
+ from ksadk.detection.detector import FrameworkType
13
+
12
14
 
13
15
  @dataclass
14
16
  class MCPDetectionResult:
@@ -19,17 +21,18 @@ class MCPDetectionResult:
19
21
  entry_point: str
20
22
  package_path: str
21
23
  mcp_variable: str = "mcp"
22
- tools: List[str] = None # 检测到的工具名称
24
+ tools: List[str] = field(default_factory=list) # 检测到的工具名称
23
25
  confidence: float = 0.0
24
26
 
25
- def __post_init__(self):
26
- if self.tools is None:
27
- self.tools = []
28
-
29
27
  @property
30
28
  def is_valid(self) -> bool:
31
29
  return self.is_mcp
32
30
 
31
+ @property
32
+ def type(self) -> FrameworkType:
33
+ """Expose the framework contract expected by shared builders."""
34
+ return FrameworkType.FASTMCP
35
+
33
36
 
34
37
  class MCPDetector:
35
38
  """MCP 检测器 - 检测 FastMCP 项目"""