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,451 @@
1
+ """Runtime HTTP request models and pure projection helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from datetime import datetime, timezone
7
+ from typing import Any, Dict, List, Mapping, Optional
8
+
9
+ from fastapi import HTTPException
10
+ from pydantic import BaseModel, Field, field_validator
11
+
12
+ from ksadk.conversations.run_kinds import RUN_MODE_UNKNOWN, RUN_TRIGGER_UNKNOWN
13
+ from ksadk.conversations.run_status import RUN_STATUS_ACTIVE, RUN_STATUS_TERMINAL
14
+ from ksadk.runtime.launch import RuntimeLaunchContext
15
+ from ksadk.sessions import SessionEvent
16
+
17
+ _RUN_TERMINAL_STATUSES = RUN_STATUS_TERMINAL
18
+ _RUN_ACTIVE_STATUSES = RUN_STATUS_ACTIVE
19
+ _EVENT_SCAN_PAGE_SIZE = 500
20
+ _MAX_PREVIEW_TOOL_RECEIPTS = 500
21
+ _RUNTIME_RUN_STATUS_BY_EVENT_TYPE = {
22
+ "run.started": "in_progress",
23
+ "run.progress": "in_progress",
24
+ "run.interrupted": "interrupted",
25
+ "run.completed": "completed",
26
+ "run.failed": "failed",
27
+ "run.canceled": "cancelled",
28
+ }
29
+
30
+
31
+ def _parse_iso_datetime(value: Any) -> datetime | None:
32
+ raw = str(value or "").strip()
33
+ if not raw:
34
+ return None
35
+ if raw.endswith("Z"):
36
+ raw = f"{raw[:-1]}+00:00"
37
+ try:
38
+ parsed = datetime.fromisoformat(raw)
39
+ except ValueError:
40
+ return None
41
+ if parsed.tzinfo is None:
42
+ return parsed.replace(tzinfo=timezone.utc)
43
+ return parsed.astimezone(timezone.utc)
44
+
45
+
46
+ class UiBootstrapRequest(BaseModel):
47
+ AgentId: Optional[str] = None
48
+ SessionId: Optional[str] = None
49
+
50
+
51
+ class CreateSessionActionRequest(BaseModel):
52
+ AgentId: str
53
+ UserId: Optional[str] = "user"
54
+ SessionId: Optional[str] = None
55
+
56
+
57
+ class ListSessionsActionRequest(BaseModel):
58
+ AgentId: str
59
+ UserId: Optional[str] = None
60
+ Page: int = Field(1, ge=1)
61
+ PageSize: int = Field(20, ge=1, le=200)
62
+
63
+
64
+ class SessionIdRequest(BaseModel):
65
+ SessionId: str
66
+ AgentId: Optional[str] = None
67
+ UserId: Optional[str] = None
68
+
69
+
70
+ class ListSessionEventsActionRequest(BaseModel):
71
+ AgentId: Optional[str] = None
72
+ SessionId: Optional[str] = None
73
+ UserId: Optional[str] = None
74
+ Offset: Optional[int] = Field(None, ge=0)
75
+ Limit: int = Field(200, ge=1, le=2000)
76
+ AfterSeqId: Optional[int] = Field(None, ge=0)
77
+ BeforeSeqId: Optional[int] = Field(None, ge=1)
78
+
79
+
80
+ class ListSessionMessagesActionRequest(BaseModel):
81
+ AgentId: Optional[str] = None
82
+ UserId: Optional[str] = None
83
+ SessionId: str
84
+ AfterSeqId: Optional[int] = Field(None, ge=0)
85
+ BeforeSeqId: Optional[int] = Field(None, ge=1)
86
+ Limit: int = Field(50, ge=1, le=200)
87
+ IncludeReasoning: bool = False
88
+ IncludeToolEvents: bool = False
89
+ IncludeAttachments: bool = True
90
+
91
+
92
+ class ListSessionCheckpointsActionRequest(BaseModel):
93
+ AgentId: str
94
+ SessionId: Optional[str] = None
95
+ UserId: Optional[str] = None
96
+ RunId: Optional[str] = None
97
+ OnlyResumable: bool = False
98
+ Framework: Optional[str] = None
99
+ Offset: Optional[int] = Field(None, ge=0)
100
+ Limit: int = Field(100, ge=1, le=500)
101
+
102
+
103
+ class ListToolReceiptsActionRequest(BaseModel):
104
+ AgentId: str
105
+ UserId: Optional[str] = None
106
+ SessionId: str
107
+ RunId: Optional[str] = None
108
+ CheckpointId: Optional[str] = None
109
+ Offset: int = Field(0, ge=0)
110
+ Limit: int = Field(200, ge=1, le=500)
111
+
112
+
113
+ class ResumeRunActionRequest(BaseModel):
114
+ AgentId: str
115
+ UserId: Optional[str] = None
116
+ SessionId: str
117
+ RunId: str
118
+ CheckpointId: str
119
+ ResumeAttemptId: Optional[str] = None
120
+ InvocationId: Optional[str] = None
121
+ Stream: bool = False
122
+ Model: Optional[str] = None
123
+ ModelMetadata: Optional[Dict[str, Any]] = None
124
+ ModelOptions: Optional[Dict[str, Any]] = None
125
+ Metadata: Optional[Dict[str, Any]] = None
126
+ ResumeInstructionEnabled: bool = False
127
+ ResumeInstruction: Optional[str] = None
128
+
129
+
130
+ class GetCheckpointResumePreviewActionRequest(BaseModel):
131
+ AgentId: str
132
+ UserId: Optional[str] = None
133
+ SessionId: str
134
+ RunId: str
135
+ CheckpointId: str
136
+
137
+
138
+ class RunAgentActionRequest(BaseModel):
139
+ AgentId: str
140
+ Messages: List[Dict[str, Any]] = Field(default_factory=list)
141
+ UserId: Optional[str] = "user"
142
+ AccountId: Optional[str] = None
143
+ SessionId: Optional[str] = None
144
+ InvocationId: Optional[str] = None
145
+ ApiFormat: str = "responses"
146
+ Stream: bool = False
147
+ Background: bool = False # 立即返回 job 句柄,后台执行,进度走 SubscribeRunEvents
148
+ Model: Optional[str] = None
149
+ ModelMetadata: Optional[Dict[str, Any]] = None
150
+ ModelOptions: Optional[Dict[str, Any]] = None
151
+ Metadata: Optional[Dict[str, Any]] = None
152
+ ResponsesInput: Optional[Any] = None
153
+ PreviousResponseId: Optional[str] = None
154
+
155
+
156
+ class ResponseFeedbackRefActionRequest(BaseModel):
157
+ AgentId: str
158
+ SessionId: str
159
+ ResponseId: str
160
+
161
+
162
+ class UpsertResponseFeedbackActionRequest(ResponseFeedbackRefActionRequest):
163
+ Rating: str
164
+ Comment: Optional[str] = ""
165
+ EventId: Optional[str] = None
166
+ TraceId: Optional[str] = None
167
+ RootSpanId: Optional[str] = None
168
+
169
+
170
+ class ResponsesRequest(BaseModel):
171
+ input: Any
172
+ model: Optional[str] = None
173
+ model_metadata: Optional[Dict[str, Any]] = None
174
+ model_options: Optional[Dict[str, Any]] = None
175
+ instructions: Optional[str] = None
176
+ metadata: Optional[Dict[str, Any]] = None
177
+ conversation: Optional[Any] = None
178
+ safety_identifier: Optional[str] = None
179
+ prompt_cache_key: Optional[str] = None
180
+ user: Optional[str] = None
181
+ account_id: Optional[str] = None
182
+ store: Optional[bool] = None
183
+ previous_response_id: Optional[str] = None
184
+ stream: bool = False
185
+ session_id: Optional[str] = None
186
+
187
+ @field_validator("metadata")
188
+ @classmethod
189
+ def validate_metadata(cls, value: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
190
+ if value is None:
191
+ return None
192
+ public_items = [(key, item) for key, item in value.items() if key != "agentengine"]
193
+ if len(public_items) > 16:
194
+ raise ValueError("Responses metadata supports at most 16 key-value pairs")
195
+ for key, item in public_items:
196
+ if len(key) > 64:
197
+ raise ValueError("Responses metadata keys must be at most 64 characters")
198
+ if not isinstance(item, str):
199
+ raise ValueError("Responses metadata values must be strings")
200
+ if len(item) > 512:
201
+ raise ValueError("Responses metadata values must be at most 512 characters")
202
+ return value
203
+
204
+
205
+ class WorkspaceListActionRequest(BaseModel):
206
+ AgentId: Optional[str] = None
207
+ Path: str = "."
208
+ Recursive: bool = False
209
+
210
+
211
+ def _clean_optional_string(value: Any) -> str | None:
212
+ if value is None:
213
+ return None
214
+ text = str(value).strip()
215
+ return text or None
216
+
217
+
218
+ def _resolve_responses_conversation_id(conversation_value: Any) -> str | None:
219
+ if conversation_value is None:
220
+ return None
221
+ if isinstance(conversation_value, str):
222
+ return _clean_optional_string(conversation_value)
223
+ if isinstance(conversation_value, Mapping):
224
+ return _clean_optional_string(conversation_value.get("id"))
225
+ raise HTTPException(
226
+ status_code=400,
227
+ detail="Responses field 'conversation' must be a string or an object with an 'id'.",
228
+ )
229
+
230
+
231
+ def _resolve_responses_session_and_user(request: ResponsesRequest) -> tuple[str | None, str]:
232
+ conversation_id = _resolve_responses_conversation_id(request.conversation)
233
+ legacy_session_id = _clean_optional_string(request.session_id)
234
+
235
+ if conversation_id and legacy_session_id and conversation_id != legacy_session_id:
236
+ raise HTTPException(
237
+ status_code=400,
238
+ detail=(
239
+ "Responses field 'conversation' conflicts with ksadk legacy field "
240
+ "'session_id'. Use 'conversation' for OpenAI-compatible calls."
241
+ ),
242
+ )
243
+ if conversation_id and request.previous_response_id:
244
+ raise HTTPException(
245
+ status_code=400,
246
+ detail=(
247
+ "Responses fields 'conversation' and 'previous_response_id' cannot be "
248
+ "used together."
249
+ ),
250
+ )
251
+
252
+ resolved_session_id = conversation_id or legacy_session_id
253
+ resolved_user_id = (
254
+ _clean_optional_string(request.safety_identifier)
255
+ or _clean_optional_string(request.user)
256
+ or "user"
257
+ )
258
+ return resolved_session_id, resolved_user_id
259
+
260
+
261
+ def _runtime_agent_id(launch_context: RuntimeLaunchContext) -> str:
262
+ runtime_id = _clean_optional_string(os.getenv("AGENT_RUNTIME_ID"))
263
+ if runtime_id:
264
+ return runtime_id
265
+ return str(getattr(launch_context.detection, "name", "") or "agent")
266
+
267
+
268
+ def _metadata_invocation_id(metadata: Mapping[str, Any] | None) -> str | None:
269
+ if not isinstance(metadata, Mapping):
270
+ return None
271
+ agentengine_metadata = metadata.get("agentengine")
272
+ if not isinstance(agentengine_metadata, Mapping):
273
+ return None
274
+ return _clean_optional_string(agentengine_metadata.get("invocation_id"))
275
+
276
+
277
+ def _split_custom_metadata(
278
+ metadata: Mapping[str, Any] | None,
279
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
280
+ public_metadata = dict(metadata or {})
281
+ runtime_metadata: dict[str, Any] = {}
282
+ agentengine_metadata = public_metadata.get("agentengine")
283
+ public_metadata.pop("agentengine", None)
284
+ if isinstance(agentengine_metadata, Mapping):
285
+ runtime_metadata["agentengine"] = dict(agentengine_metadata)
286
+ # The approval profile is a small, validated-by-the-agent runtime control.
287
+ # It must not be mixed into caller-visible public metadata.
288
+ tool_approval_mode = agentengine_metadata.get("tool_approval_mode")
289
+ if isinstance(tool_approval_mode, str):
290
+ runtime_metadata["tool_approval_mode"] = tool_approval_mode
291
+ return public_metadata, runtime_metadata
292
+
293
+
294
+ def _run_agent_response_metadata(
295
+ custom_metadata: Mapping[str, Any] | None,
296
+ result: Mapping[str, Any] | None,
297
+ ) -> dict[str, Any]:
298
+ response_metadata = dict(custom_metadata or {})
299
+ result_metadata = result.get("metadata") if isinstance(result, Mapping) else None
300
+ if isinstance(result_metadata, Mapping):
301
+ agentengine_metadata = result_metadata.get("agentengine")
302
+ if isinstance(agentengine_metadata, Mapping):
303
+ response_metadata["agentengine"] = dict(agentengine_metadata)
304
+ return response_metadata
305
+
306
+
307
+ def _event_text(event: SessionEvent) -> str:
308
+ parts = (event.content or {}).get("parts")
309
+ if isinstance(parts, list):
310
+ text_parts: list[str] = []
311
+ for part in parts:
312
+ if isinstance(part, Mapping):
313
+ text_parts.append(str(part.get("text") or ""))
314
+ else:
315
+ text_parts.append(str(part or ""))
316
+ text = "".join(text_parts).strip()
317
+ if text:
318
+ return text
319
+ return str((event.content or {}).get("text") or "").strip()
320
+
321
+
322
+ def _truncate_session_text(text: str, limit: int = 512) -> str:
323
+ normalized = " ".join(str(text or "").strip().split())
324
+ if len(normalized) <= limit:
325
+ return normalized
326
+ return f"{normalized[: max(limit - 1, 0)].rstrip()}…"
327
+
328
+
329
+ def _session_user_prompt_from_event(event: SessionEvent) -> str:
330
+ metadata = event.metadata or {}
331
+ content = event.content or {}
332
+ return str(
333
+ metadata.get("agent_input")
334
+ or metadata.get("user_input")
335
+ or content.get("agent_input")
336
+ or _event_text(event)
337
+ or ""
338
+ ).strip()
339
+
340
+
341
+ def _run_status_payload_status(event: SessionEvent) -> str:
342
+ legacy_status = str(
343
+ (event.metadata or {}).get("status")
344
+ or (event.metadata or {}).get("run_status")
345
+ or (event.content or {}).get("status")
346
+ or ""
347
+ ).strip()
348
+ if legacy_status:
349
+ return legacy_status
350
+ runtime_payload = (event.content or {}).get("payload")
351
+ runtime_status = (
352
+ str(runtime_payload.get("status") or "").strip()
353
+ if isinstance(runtime_payload, Mapping)
354
+ else ""
355
+ )
356
+ return runtime_status or _RUNTIME_RUN_STATUS_BY_EVENT_TYPE.get(event.event_type, "")
357
+
358
+
359
+ def _is_run_lifecycle_event(event: SessionEvent) -> bool:
360
+ return event.event_type == "run_status" or event.event_type in _RUNTIME_RUN_STATUS_BY_EVENT_TYPE
361
+
362
+
363
+ def _event_run_id(event: SessionEvent) -> str:
364
+ return str(
365
+ (event.metadata or {}).get("run_id")
366
+ or (event.metadata or {}).get("invocation_id")
367
+ or event.invocation_id
368
+ or ""
369
+ ).strip()
370
+
371
+
372
+ def _session_topic_from_events(events: list[SessionEvent]) -> str:
373
+ for event in reversed(events):
374
+ metadata = event.metadata or {}
375
+ tool_output = metadata.get("tool_output")
376
+ if isinstance(tool_output, Mapping):
377
+ topic = str(tool_output.get("topic") or tool_output.get("research_title") or "").strip()
378
+ if topic:
379
+ return topic
380
+ topic = str(metadata.get("research_title") or metadata.get("task_title") or "").strip()
381
+ if topic:
382
+ return topic
383
+ return ""
384
+
385
+
386
+ def _latest_session_run_status(events: list[SessionEvent]) -> tuple[str, str]:
387
+ latest_by_invocation: dict[str, tuple[str, SessionEvent]] = {}
388
+ for event in reversed(events):
389
+ if not _is_run_lifecycle_event(event):
390
+ continue
391
+ status = _run_status_payload_status(event)
392
+ invocation_id = _event_run_id(event)
393
+ if status or invocation_id:
394
+ latest_by_invocation.setdefault(invocation_id, (status, event))
395
+ for invocation_id, (status, _) in latest_by_invocation.items():
396
+ if status in _RUN_ACTIVE_STATUSES:
397
+ return invocation_id, status
398
+ for invocation_id, (status, _) in latest_by_invocation.items():
399
+ if status not in _RUN_TERMINAL_STATUSES:
400
+ return invocation_id, status
401
+ if latest_by_invocation:
402
+ invocation_id, (status, _) = next(iter(latest_by_invocation.items()))
403
+ return invocation_id, status
404
+ for event in reversed(events):
405
+ invocation_id = _event_run_id(event)
406
+ if invocation_id:
407
+ return invocation_id, ""
408
+ return "", ""
409
+
410
+
411
+ def _latest_session_run_metadata(
412
+ events: list[SessionEvent],
413
+ ) -> tuple[str, str, str, str]:
414
+ """返回 (invocation_id, status, run_mode, run_trigger)。
415
+
416
+ 与 _latest_session_run_status 同语义,但额外从最新 run_status 事件的 metadata
417
+ 读取 run_mode/run_trigger。旧事件缺字段降级 unknown。原 _latest_session_run_status
418
+ 不动,保护现有 ActiveInvocationId/ActiveRunStatus 契约。
419
+ """
420
+ invocation_id, status = _latest_session_run_status(events)
421
+ run_mode = RUN_MODE_UNKNOWN
422
+ run_trigger = RUN_TRIGGER_UNKNOWN
423
+ if invocation_id:
424
+ for event in reversed(events):
425
+ if not _is_run_lifecycle_event(event) or _event_run_id(event) != invocation_id:
426
+ continue
427
+ metadata = event.metadata or {}
428
+ candidate_mode = str(metadata.get("run_mode") or RUN_MODE_UNKNOWN)
429
+ candidate_trigger = str(metadata.get("run_trigger") or RUN_TRIGGER_UNKNOWN)
430
+ # Canonical RuntimeEvents and their legacy ``run_status`` projection
431
+ # coexist in the session log. RuntimeEvents intentionally carry only
432
+ # the transport-neutral marker, while the projection owns run kind
433
+ # metadata. Keep scanning past an unclassified RuntimeEvent so the UI
434
+ # does not downgrade a known background/foreground run to ``unknown``.
435
+ if candidate_mode != RUN_MODE_UNKNOWN or candidate_trigger != RUN_TRIGGER_UNKNOWN:
436
+ run_mode = candidate_mode
437
+ run_trigger = candidate_trigger
438
+ break
439
+ return invocation_id, status, run_mode, run_trigger
440
+
441
+
442
+ class WorkspaceDeleteActionRequest(BaseModel):
443
+ AgentId: Optional[str] = None
444
+ Path: str
445
+
446
+
447
+ class CancelRunActionRequest(BaseModel):
448
+ AgentId: Optional[str] = None
449
+ UserId: Optional[str] = None
450
+ SessionId: Optional[str] = None
451
+ InvocationId: str
@@ -0,0 +1,229 @@
1
+ """OpenAI Responses and Chat Completions compatibility routes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import uuid
6
+ from collections.abc import Mapping
7
+ from typing import Any, Dict, List, Optional
8
+
9
+ from fastapi.responses import StreamingResponse
10
+ from pydantic import BaseModel
11
+
12
+ from ksadk.conversations.normalize import normalize_kop_messages, normalize_responses_input
13
+ from ksadk.conversations.run_kinds import RUN_MODE_FOREGROUND, trigger_from_resume_input
14
+ from ksadk.conversations.runtime_payloads import (
15
+ build_chat_completions_payload,
16
+ build_responses_payload,
17
+ extract_responses_resume_input,
18
+ )
19
+ from ksadk.conversations.runtime_streaming import (
20
+ stream_runtime_conversation_turn,
21
+ stream_runtime_responses_conversation_turn,
22
+ )
23
+ from ksadk.runtime.conversation_execution import invoke_runtime_conversation_once
24
+ from ksadk.server.factory import get_runtime_execution
25
+
26
+ from . import dependencies as deps
27
+ from .checkpoint_resolution import _resolve_checkpoint_resume_input_from_session
28
+ from .models import (
29
+ ResponsesRequest,
30
+ _clean_optional_string,
31
+ _metadata_invocation_id,
32
+ _resolve_responses_session_and_user,
33
+ _runtime_agent_id,
34
+ _split_custom_metadata,
35
+ )
36
+ from .routers import openai_compat_router
37
+ from .streaming import (
38
+ _detached_resume_key_from_input,
39
+ _reject_if_detached_resume_active,
40
+ )
41
+ from .workspace import _build_models_payload
42
+
43
+
44
+ class ChatCompletionRequest(BaseModel):
45
+ messages: List[Dict[str, Any]]
46
+ model: Optional[str] = None
47
+ model_metadata: Optional[Dict[str, Any]] = None
48
+ model_options: Optional[Dict[str, Any]] = None
49
+ stream: bool = False
50
+ session_id: Optional[str] = None
51
+ user: Optional[str] = None
52
+ account_id: Optional[str] = None
53
+ metadata: Optional[Dict[str, Any]] = None
54
+ temperature: Optional[float] = 0.7
55
+ max_tokens: Optional[int] = None
56
+
57
+
58
+ @openai_compat_router.get("/v1/models")
59
+ async def list_openai_models():
60
+ """Expose the current model catalog through the OpenAI-compatible path."""
61
+
62
+ payload = await _build_models_payload()
63
+ return {
64
+ "object": "list",
65
+ "data": payload.get("data", []),
66
+ "current": payload.get("current"),
67
+ "source": payload.get("source", ""),
68
+ }
69
+
70
+
71
+ @openai_compat_router.post("/v1/responses")
72
+ async def responses(request: ResponsesRequest):
73
+ """OpenAI Responses 兼容接口。"""
74
+ executor, launch_context = get_runtime_execution()
75
+ resolved_session_id, resolved_user_id = _resolve_responses_session_and_user(request)
76
+ agent_id = _runtime_agent_id(launch_context)
77
+
78
+ resume_input = extract_responses_resume_input(request.input)
79
+ resume_input = await _resolve_checkpoint_resume_input_from_session(
80
+ service=deps.resolve_session_service(),
81
+ agent_id=agent_id,
82
+ session_id=resolved_session_id,
83
+ resume_input=resume_input,
84
+ )
85
+ messages = (
86
+ []
87
+ if resume_input is not None
88
+ else normalize_responses_input(request.input)
89
+ )
90
+ custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
91
+ if request.previous_response_id:
92
+ request_metadata["previous_response_id"] = request.previous_response_id
93
+ if request.prompt_cache_key:
94
+ request_metadata["prompt_cache_key"] = request.prompt_cache_key
95
+ if request.safety_identifier:
96
+ request_metadata["safety_identifier"] = request.safety_identifier
97
+ if request.user:
98
+ request_metadata["user"] = request.user
99
+ if request.conversation is not None:
100
+ request_metadata["conversation"] = request.conversation
101
+ if request.store is not None:
102
+ request_metadata["store"] = request.store
103
+ account_id = _clean_optional_string(request.account_id)
104
+ invocation_id = _metadata_invocation_id(request_metadata)
105
+
106
+ if request.stream:
107
+ runtime_preparation = (
108
+ None
109
+ if resume_input is not None
110
+ else await executor.prepare_start(launch_context)
111
+ )
112
+ resume_key = _detached_resume_key_from_input(resolved_session_id, resume_input)
113
+ _reject_if_detached_resume_active(resume_key)
114
+ return deps.detached_streaming_response(
115
+ stream_runtime_responses_conversation_turn(
116
+ executor=executor,
117
+ launch_context=launch_context,
118
+ agent_id=agent_id,
119
+ user_id=resolved_user_id,
120
+ messages=messages,
121
+ session_id=resolved_session_id,
122
+ model=request.model,
123
+ model_metadata=request.model_metadata,
124
+ model_options=request.model_options,
125
+ instructions=request.instructions,
126
+ request_metadata=request_metadata,
127
+ custom_metadata=custom_metadata,
128
+ resume_input=resume_input,
129
+ account_id=account_id,
130
+ invocation_id=invocation_id,
131
+ session_service_provider=deps.resolve_session_service,
132
+ run_mode=RUN_MODE_FOREGROUND,
133
+ runtime_preparation=runtime_preparation,
134
+ ),
135
+ invocation_id=invocation_id,
136
+ resume_key=resume_key,
137
+ run_mode=RUN_MODE_FOREGROUND,
138
+ run_trigger=trigger_from_resume_input(resume_input),
139
+ )
140
+
141
+ response_id = f"resp_{uuid.uuid4().hex}"
142
+ resolved_session_id, result = await invoke_runtime_conversation_once(
143
+ executor=executor,
144
+ launch_context=launch_context,
145
+ agent_id=agent_id,
146
+ user_id=resolved_user_id,
147
+ messages=messages,
148
+ session_id=resolved_session_id,
149
+ model=request.model,
150
+ model_metadata=request.model_metadata,
151
+ model_options=request.model_options,
152
+ instructions=request.instructions,
153
+ request_metadata=request_metadata,
154
+ custom_metadata=custom_metadata,
155
+ resume_input=resume_input,
156
+ response_id=response_id,
157
+ account_id=account_id,
158
+ invocation_id=invocation_id,
159
+ session_service_provider=deps.resolve_session_service,
160
+ run_mode=RUN_MODE_FOREGROUND,
161
+ )
162
+ return build_responses_payload(
163
+ output_text=result["output_text"],
164
+ model=request.model,
165
+ session_id=resolved_session_id,
166
+ response_id=response_id,
167
+ metadata=custom_metadata,
168
+ usage=result.get("usage") if isinstance(result.get("usage"), Mapping) else None,
169
+ )
170
+
171
+
172
+ @openai_compat_router.post("/v1/chat/completions")
173
+ async def chat_completions(request: ChatCompletionRequest):
174
+ """OpenAI 兼容的聊天补全接口 (支持流式和非流式)"""
175
+ executor, launch_context = get_runtime_execution()
176
+ messages = normalize_kop_messages(request.messages)
177
+ agent_id = _runtime_agent_id(launch_context)
178
+ resolved_user_id = _clean_optional_string(request.user) or "user"
179
+ account_id = _clean_optional_string(request.account_id)
180
+ custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
181
+ invocation_id = _metadata_invocation_id(request_metadata)
182
+
183
+ if request.stream:
184
+ runtime_preparation = await executor.prepare_start(launch_context)
185
+ return StreamingResponse(
186
+ stream_runtime_conversation_turn(
187
+ executor=executor,
188
+ launch_context=launch_context,
189
+ agent_id=agent_id,
190
+ user_id=resolved_user_id,
191
+ messages=messages,
192
+ session_id=request.session_id,
193
+ model=request.model,
194
+ model_metadata=request.model_metadata,
195
+ model_options=request.model_options,
196
+ request_metadata=request_metadata,
197
+ custom_metadata=custom_metadata,
198
+ invocation_id=invocation_id,
199
+ account_id=account_id,
200
+ session_service_provider=deps.resolve_session_service,
201
+ run_mode=RUN_MODE_FOREGROUND,
202
+ runtime_preparation=runtime_preparation,
203
+ ),
204
+ media_type="text/event-stream",
205
+ )
206
+
207
+ resolved_session_id, result = await invoke_runtime_conversation_once(
208
+ executor=executor,
209
+ launch_context=launch_context,
210
+ agent_id=agent_id,
211
+ user_id=resolved_user_id,
212
+ messages=messages,
213
+ session_id=request.session_id,
214
+ model=request.model,
215
+ model_metadata=request.model_metadata,
216
+ model_options=request.model_options,
217
+ request_metadata=request_metadata,
218
+ custom_metadata=custom_metadata,
219
+ invocation_id=invocation_id,
220
+ account_id=account_id,
221
+ session_service_provider=deps.resolve_session_service,
222
+ run_mode=RUN_MODE_FOREGROUND,
223
+ )
224
+ return build_chat_completions_payload(
225
+ output_text=result["output_text"],
226
+ model=request.model,
227
+ session_id=resolved_session_id,
228
+ metadata=result.get("metadata"),
229
+ )