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
@@ -0,0 +1,425 @@
1
+ """Static UI, builder, trace, feedback, and ADK compatibility routes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import time
7
+ import uuid
8
+ from collections.abc import Mapping
9
+ from typing import Any, Dict, List, Optional, cast
10
+
11
+ from fastapi import HTTPException, Request
12
+
13
+ from ksadk.sessions import SessionEvent
14
+ from ksadk.tracing import get_memory_exporter
15
+
16
+ from . import dependencies as deps
17
+ from .common import (
18
+ _action_response,
19
+ _ensure_session,
20
+ _hydrate_session,
21
+ _resolve_ui_static_response,
22
+ )
23
+ from .models import ResponseFeedbackRefActionRequest, UpsertResponseFeedbackActionRequest
24
+ from .routers import (
25
+ builder_router,
26
+ debug_router,
27
+ feedback_router,
28
+ health_meta_router,
29
+ models_router,
30
+ sessions_adk_compat_router,
31
+ )
32
+ from .workspace import ListAgentModelsRequest, _build_models_payload
33
+
34
+
35
+ @health_meta_router.get("/{requested_path:path}", include_in_schema=False)
36
+ async def serve_agent_ui_static(requested_path: str):
37
+ response = _resolve_ui_static_response(requested_path)
38
+ if response is not None:
39
+ return response
40
+ raise HTTPException(status_code=404, detail="Not Found")
41
+
42
+
43
+ # ============================================================
44
+ # goal-01: create_runtime_app factory 装配(普通 runtime app 与 HarnessApp 共用入口)
45
+ # ============================================================
46
+
47
+ # ---- builder 域(ADK-Web stub)----
48
+
49
+
50
+ @builder_router.get("/builder/app/{app_name}")
51
+ async def get_agent_builder(
52
+ app_name: str, ts: int = 0, tmp: bool = False, file_path: Optional[str] = None
53
+ ):
54
+ """Get agent builder config - stub for ADK-Web"""
55
+ # Return minimal YAML config for non-ADK projects
56
+ return f"""name: {app_name}
57
+ model: glm-5.1
58
+ description: {app_name} agent
59
+ instruction: You are a helpful assistant.
60
+ """
61
+
62
+
63
+ @builder_router.post("/builder/save")
64
+ async def save_agent_builder(request: Request, tmp: bool = False):
65
+ """Save agent builder config - stub for ADK-Web"""
66
+ return True
67
+
68
+
69
+ # ---- models 域 ----
70
+
71
+
72
+ @models_router.post("/agentengine/api/v1/ListAgentModels")
73
+ async def list_agent_models_action(_request: ListAgentModelsRequest):
74
+ payload = await _build_models_payload()
75
+ return _action_response(
76
+ "ListAgentModels",
77
+ {
78
+ "Models": payload.get("data", []),
79
+ "Current": payload.get("current"),
80
+ "Source": payload.get("source", ""),
81
+ },
82
+ )
83
+
84
+
85
+ # ---- debug 域(OpenTelemetry trace 查询)----
86
+
87
+
88
+ @debug_router.get("/debug/trace/session/{session_id}")
89
+ async def get_session_trace(session_id: str):
90
+ """Get traces for a session - returns array of Span objects"""
91
+ exporter = get_memory_exporter()
92
+ if not exporter:
93
+ return [] # Return empty array, not object
94
+
95
+ # Get all spans and transform to ADK-Web expected format
96
+ raw_spans = exporter.get_finished_spans()
97
+
98
+ # Get session events for invocation mapping
99
+ service = deps.resolve_session_service()
100
+ events = await service.get_events(session_id)
101
+
102
+ # Build invocation ID mapping from session events
103
+ invocation_ids = {}
104
+ for event in events:
105
+ if event.id and event.invocation_id:
106
+ invocation_ids[event.id] = event.invocation_id
107
+
108
+ # Transform spans to ADK-Web format
109
+ spans = []
110
+ for span in raw_spans:
111
+ # Use session_id as trace_id for grouping
112
+ trace_id = span.get("trace_id", session_id)
113
+
114
+ # Get or create invocation_id
115
+ invocation_id = span.get("attributes", {}).get("gcp.vertex.agent.invocation_id")
116
+ if not invocation_id:
117
+ # Try to derive from event association
118
+ invocation_id = trace_id[:36] if len(trace_id) >= 36 else trace_id
119
+
120
+ # Build attributes with required ADK fields
121
+ attrs = span.get("attributes", {}).copy()
122
+ attrs["gcp.vertex.agent.invocation_id"] = invocation_id
123
+
124
+ # If this is a LLM span, add request/response
125
+ if "llm" in span.get("name", "").lower() or "invoke" in span.get("name", "").lower():
126
+ if "user.input" in attrs:
127
+ attrs["gcp.vertex.agent.llm_request"] = json.dumps(
128
+ {
129
+ "contents": [
130
+ {"role": "user", "parts": [{"text": attrs.get("user.input", "")}]}
131
+ ]
132
+ }
133
+ )
134
+ if "agent.output" in attrs:
135
+ attrs["gcp.vertex.agent.llm_response"] = json.dumps(
136
+ {
137
+ "candidates": [
138
+ {
139
+ "content": {
140
+ "role": "model",
141
+ "parts": [{"text": attrs.get("agent.output", "")}],
142
+ }
143
+ }
144
+ ]
145
+ }
146
+ )
147
+
148
+ formatted_span = {
149
+ "trace_id": trace_id,
150
+ "span_id": span.get("span_id", str(uuid.uuid4())[:16]),
151
+ "parent_span_id": span.get("parent_span_id"),
152
+ "name": span.get("name", "unknown"),
153
+ "start_time": span.get("start_time", 0),
154
+ "end_time": span.get("end_time", 0),
155
+ "attributes": attrs,
156
+ "status": span.get("status", {}),
157
+ }
158
+ spans.append(formatted_span)
159
+
160
+ return spans # Return array directly
161
+
162
+
163
+ @debug_router.get("/debug/trace/{event_id}")
164
+ async def get_event_trace(event_id: str):
165
+ """Get trace for a specific event - returns array of Span objects"""
166
+ exporter = get_memory_exporter()
167
+ if not exporter:
168
+ return []
169
+
170
+ spans = exporter.get_finished_spans()
171
+ # Filter by event_id or return recent spans
172
+ filtered = [s for s in spans if s.get("attributes", {}).get("event_id") == event_id]
173
+ return filtered if filtered else spans[-10:]
174
+
175
+
176
+ @debug_router.get("/traces")
177
+ async def get_traces(limit: int = 50):
178
+ """Get recent traces (OpenTelemetry)"""
179
+ exporter = get_memory_exporter()
180
+ if not exporter:
181
+ return {"traces": []}
182
+
183
+ spans = exporter.get_finished_spans()
184
+ traces = []
185
+ for span in spans[-limit:]:
186
+ traces.append(
187
+ {
188
+ "name": span.get("name", "unknown"),
189
+ "status": span.get("status", {}).get("code", "UNSET"),
190
+ "start_time": span.get("start_time"),
191
+ "end_time": span.get("end_time"),
192
+ "attributes": span.get("attributes", {}),
193
+ }
194
+ )
195
+ return {"traces": traces}
196
+
197
+
198
+ # ---- feedback 域 ----
199
+
200
+
201
+ def _feedback_state_key(response_id: str) -> str:
202
+ return str(response_id or "").strip()
203
+
204
+
205
+ def _feedback_payload_from_state(item: Mapping[str, Any] | None) -> dict[str, Any] | None:
206
+ if not isinstance(item, Mapping):
207
+ return None
208
+ rating = str(item.get("Rating") or item.get("rating") or "").strip().lower()
209
+ if rating not in {"up", "down"}:
210
+ return None
211
+ return {
212
+ "AgentId": str(item.get("AgentId") or item.get("agent_id") or ""),
213
+ "SessionId": str(item.get("SessionId") or item.get("session_id") or ""),
214
+ "ResponseId": str(item.get("ResponseId") or item.get("response_id") or ""),
215
+ "EventId": str(item.get("EventId") or item.get("event_id") or ""),
216
+ "Rating": rating,
217
+ "Comment": str(item.get("Comment") or item.get("comment") or ""),
218
+ "TraceId": str(item.get("TraceId") or item.get("trace_id") or ""),
219
+ "RootSpanId": str(item.get("RootSpanId") or item.get("root_span_id") or ""),
220
+ "CreatedAt": str(item.get("CreatedAt") or item.get("created_at") or ""),
221
+ "UpdatedAt": str(item.get("UpdatedAt") or item.get("updated_at") or ""),
222
+ }
223
+
224
+
225
+ async def _find_feedback_assistant_event(
226
+ *,
227
+ session_id: str,
228
+ response_id: str,
229
+ event_id: str | None = None,
230
+ ) -> SessionEvent | None:
231
+ events = await deps.resolve_session_service().get_events(session_id)
232
+ normalized_event_id = str(event_id or "").strip()
233
+ normalized_response_id = str(response_id or "").strip()
234
+ for event in reversed(events):
235
+ if normalized_event_id and event.id != normalized_event_id:
236
+ continue
237
+ metadata = event.metadata or {}
238
+ if (
239
+ normalized_response_id
240
+ and str(metadata.get("response_id") or "") != normalized_response_id
241
+ ):
242
+ continue
243
+ event_type = deps.conversation().canonical_event_type(
244
+ event.event_type,
245
+ author=event.author,
246
+ role=str((event.content or {}).get("role") or ""),
247
+ )
248
+ if event_type == "assistant_message":
249
+ return cast(SessionEvent, event)
250
+ return None
251
+
252
+
253
+ @feedback_router.post("/agentengine/api/v1/GetResponseFeedback")
254
+ async def get_response_feedback_action(request: ResponseFeedbackRefActionRequest):
255
+ session = await deps.resolve_session_service().get_session(request.SessionId)
256
+ if not session or session.agent_id != request.AgentId:
257
+ return _action_response("GetResponseFeedback", {"Feedback": None})
258
+ feedbacks = session.state.get("__ksadk_response_feedback__")
259
+ feedback = None
260
+ if isinstance(feedbacks, Mapping):
261
+ feedback = _feedback_payload_from_state(
262
+ feedbacks.get(_feedback_state_key(request.ResponseId))
263
+ )
264
+ return _action_response("GetResponseFeedback", {"Feedback": feedback})
265
+
266
+
267
+ @feedback_router.post("/agentengine/api/v1/UpsertResponseFeedback")
268
+ async def upsert_response_feedback_action(request: UpsertResponseFeedbackActionRequest):
269
+ rating = str(request.Rating or "").strip().lower()
270
+ if rating not in {"up", "down"}:
271
+ raise HTTPException(status_code=400, detail="Feedback rating must be up or down")
272
+
273
+ service = deps.resolve_session_service()
274
+ session = await service.get_session(request.SessionId)
275
+ if not session or session.agent_id != request.AgentId:
276
+ raise HTTPException(status_code=404, detail="Session not found")
277
+
278
+ assistant_event = await _find_feedback_assistant_event(
279
+ session_id=request.SessionId,
280
+ response_id=request.ResponseId,
281
+ event_id=request.EventId,
282
+ )
283
+ if assistant_event is None:
284
+ raise HTTPException(status_code=404, detail="Assistant response not found")
285
+
286
+ now = str(time.time())
287
+ existing_feedbacks = session.state.get("__ksadk_response_feedback__")
288
+ feedbacks = dict(existing_feedbacks) if isinstance(existing_feedbacks, Mapping) else {}
289
+ existing = (
290
+ _feedback_payload_from_state(feedbacks.get(_feedback_state_key(request.ResponseId))) or {}
291
+ )
292
+ metadata = assistant_event.metadata or {}
293
+ feedback = {
294
+ "AgentId": request.AgentId,
295
+ "SessionId": request.SessionId,
296
+ "ResponseId": request.ResponseId,
297
+ "EventId": request.EventId or assistant_event.id,
298
+ "Rating": rating,
299
+ "Comment": request.Comment or "",
300
+ "TraceId": request.TraceId or str(metadata.get("trace_id") or ""),
301
+ "RootSpanId": request.RootSpanId or str(metadata.get("root_span_id") or ""),
302
+ "CreatedAt": existing.get("CreatedAt") or now,
303
+ "UpdatedAt": now,
304
+ }
305
+ feedbacks[_feedback_state_key(request.ResponseId)] = feedback
306
+ await service.update_state(
307
+ agent_id=session.agent_id,
308
+ user_id=session.user_id,
309
+ session_id=session.id,
310
+ scope="session",
311
+ state_delta={"__ksadk_response_feedback__": feedbacks},
312
+ )
313
+ return _action_response("UpsertResponseFeedback", {"Feedback": feedback})
314
+
315
+
316
+ @feedback_router.post("/agentengine/api/v1/DeleteResponseFeedback")
317
+ async def delete_response_feedback_action(request: ResponseFeedbackRefActionRequest):
318
+ service = deps.resolve_session_service()
319
+ session = await service.get_session(request.SessionId)
320
+ if not session or session.agent_id != request.AgentId:
321
+ return _action_response("DeleteResponseFeedback", {"Deleted": False})
322
+ existing_feedbacks = session.state.get("__ksadk_response_feedback__")
323
+ feedbacks = dict(existing_feedbacks) if isinstance(existing_feedbacks, Mapping) else {}
324
+ deleted = feedbacks.pop(_feedback_state_key(request.ResponseId), None) is not None
325
+ if deleted:
326
+ await service.update_state(
327
+ agent_id=session.agent_id,
328
+ user_id=session.user_id,
329
+ session_id=session.id,
330
+ scope="session",
331
+ state_delta={"__ksadk_response_feedback__": feedbacks},
332
+ )
333
+ return _action_response("DeleteResponseFeedback", {"Deleted": deleted})
334
+
335
+
336
+ # ---- sessions_adk_compat 域(ADK-Web 兼容)----
337
+
338
+
339
+ @sessions_adk_compat_router.post("/apps/{app_name}/users/{user_id}/sessions")
340
+ async def create_session(app_name: str, user_id: str, request: Request):
341
+ """Create a new session"""
342
+ # Check if importing existing events
343
+ body = {}
344
+ try:
345
+ body = await request.json()
346
+ except Exception:
347
+ pass
348
+
349
+ service = deps.resolve_session_service()
350
+ session = await _ensure_session(app_name, user_id, body.get("sessionId") or body.get("id"))
351
+
352
+ for raw_event in body.get("events", []):
353
+ session_event = SessionEvent.from_dict(raw_event, session_id=session.id)
354
+ await service.append_event(session.id, session_event)
355
+
356
+ hydrated = await _hydrate_session(await service.get_session(session.id))
357
+ return hydrated.to_legacy_dict() if hydrated else session.to_legacy_dict()
358
+
359
+
360
+ @sessions_adk_compat_router.get("/apps/{app_name}/users/{user_id}/sessions")
361
+ async def list_sessions(app_name: str, user_id: str):
362
+ """List all sessions for a user"""
363
+ service = deps.resolve_session_service()
364
+ sessions = await service.list_sessions(app_name, user_id)
365
+ hydrated: List[Dict[str, Any]] = []
366
+ for session in sessions:
367
+ session.events = await service.get_events(session.id)
368
+ hydrated.append(session.to_legacy_dict())
369
+ return hydrated
370
+
371
+
372
+ @sessions_adk_compat_router.get("/apps/{app_name}/users/{user_id}/sessions/{session_id}")
373
+ async def get_session(app_name: str, user_id: str, session_id: str):
374
+ """Get a specific session with its events"""
375
+ service = deps.resolve_session_service()
376
+ session = await _hydrate_session(await service.get_session(session_id))
377
+ if not session:
378
+ raise HTTPException(status_code=404, detail="Session not found")
379
+ return session.to_legacy_dict()
380
+
381
+
382
+ @sessions_adk_compat_router.delete("/apps/{app_name}/users/{user_id}/sessions/{session_id}")
383
+ async def delete_session(app_name: str, user_id: str, session_id: str):
384
+ """Delete a session"""
385
+ service = deps.resolve_session_service()
386
+ if await service.delete_session(session_id):
387
+ return {"status": "deleted"}
388
+ raise HTTPException(status_code=404, detail="Session not found")
389
+
390
+
391
+ @sessions_adk_compat_router.post(
392
+ "/apps/{app_name}/users/{user_id}/sessions/{session_id}/save_memory"
393
+ )
394
+ async def save_session_to_memory(app_name: str, user_id: str, session_id: str):
395
+ """Fail closed until long-term memory is exposed as a Runtime capability."""
396
+
397
+ del app_name, user_id, session_id
398
+ raise HTTPException(
399
+ status_code=501,
400
+ detail={
401
+ "code": "RUNTIME_NOT_SUPPORTED",
402
+ "message": "当前 RuntimeAdapter 未声明长期记忆写入能力",
403
+ "hint": "请通过 Runtime Catalog 检查长期记忆能力后重试",
404
+ },
405
+ )
406
+
407
+
408
+ @sessions_adk_compat_router.get(
409
+ "/apps/{app_name}/users/{user_id}/sessions/{session_id}/events/{event_id}/graph"
410
+ )
411
+ async def get_event_graph(app_name: str, user_id: str, session_id: str, event_id: str):
412
+ """Get event graph (DOT format) - placeholder"""
413
+ return {"dotSrc": None}
414
+
415
+
416
+ @sessions_adk_compat_router.get("/apps/{app_name}/eval_sets")
417
+ async def list_eval_sets(app_name: str):
418
+ """List evaluation sets - stub for ADK-Web"""
419
+ return []
420
+
421
+
422
+ @sessions_adk_compat_router.get("/apps/{app_name}/eval_results")
423
+ async def list_eval_results(app_name: str):
424
+ """List evaluation results - stub for ADK-Web"""
425
+ return []