agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.0__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 (371) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
  2. agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
  3. ksadk/a2a/__init__.py +178 -11
  4. ksadk/a2a/bootstrap.py +334 -0
  5. ksadk/a2a/card.py +120 -0
  6. ksadk/a2a/context_store.py +203 -0
  7. ksadk/a2a/control_plane.py +818 -0
  8. ksadk/a2a/credential.py +99 -0
  9. ksadk/a2a/event_adapter.py +149 -0
  10. ksadk/a2a/executor.py +406 -89
  11. ksadk/a2a/external_transport.py +516 -0
  12. ksadk/a2a/identity.py +304 -0
  13. ksadk/a2a/ids.py +22 -0
  14. ksadk/a2a/langgraph.py +285 -0
  15. ksadk/a2a/resume_store.py +201 -0
  16. ksadk/a2a/routes.py +105 -0
  17. ksadk/a2a/server.py +107 -60
  18. ksadk/a2a/space_client.py +1101 -0
  19. ksadk/a2a/task_adapter.py +423 -0
  20. ksadk/a2a/task_event_dispatcher.py +167 -0
  21. ksadk/a2a/task_event_outbox.py +326 -0
  22. ksadk/a2a/task_store.py +206 -0
  23. ksadk/a2ui/__init__.py +27 -0
  24. ksadk/a2ui/core.py +186 -0
  25. ksadk/a2ui/models.py +166 -0
  26. ksadk/a2ui/renderer.py +198 -0
  27. ksadk/agui/__init__.py +9 -0
  28. ksadk/agui/a2ui_projection.py +92 -0
  29. ksadk/agui/agent.py +857 -0
  30. ksadk/agui/config.py +86 -0
  31. ksadk/agui/routes.py +55 -0
  32. ksadk/api/client.py +233 -191
  33. ksadk/builders/__init__.py +2 -0
  34. ksadk/builders/base.py +16 -14
  35. ksadk/builders/code_builder.py +318 -236
  36. ksadk/builders/container_builder.py +187 -167
  37. ksadk/builders/framework_requirements.py +29 -11
  38. ksadk/builders/ks3_uploader.py +58 -27
  39. ksadk/builders/managed_runtime_builder.py +145 -0
  40. ksadk/builders/mcp_builder.py +91 -92
  41. ksadk/builders/requirements_utils.py +1 -5
  42. ksadk/cli/__init__.py +89 -171
  43. ksadk/cli/cmd_a2a.py +254 -70
  44. ksadk/cli/cmd_agent.py +19 -5
  45. ksadk/cli/cmd_build.py +158 -29
  46. ksadk/cli/cmd_completion.py +47 -35
  47. ksadk/cli/cmd_config.py +267 -198
  48. ksadk/cli/cmd_create.py +500 -720
  49. ksadk/cli/cmd_dashboard.py +120 -45
  50. ksadk/cli/cmd_deploy.py +117 -58
  51. ksadk/cli/cmd_destroy.py +44 -14
  52. ksadk/cli/cmd_files.py +63 -24
  53. ksadk/cli/cmd_hermes.py +168 -89
  54. ksadk/cli/cmd_invoke.py +184 -122
  55. ksadk/cli/cmd_launch.py +64 -28
  56. ksadk/cli/cmd_mcp.py +98 -64
  57. ksadk/cli/cmd_model.py +14 -5
  58. ksadk/cli/cmd_openclaw.py +483 -227
  59. ksadk/cli/cmd_replay.py +71 -0
  60. ksadk/cli/cmd_run.py +33 -10
  61. ksadk/cli/cmd_status.py +80 -31
  62. ksadk/cli/cmd_version.py +20 -13
  63. ksadk/cli/cmd_web.py +89 -13
  64. ksadk/cli/deploy_utils.py +20 -20
  65. ksadk/cli/dry_run.py +5 -3
  66. ksadk/cli/error_utils.py +37 -12
  67. ksadk/cli/global_options.py +1 -2
  68. ksadk/cli/local_runtime.py +1 -2
  69. ksadk/cli/model_catalog.py +6 -2
  70. ksadk/cli/network_options.py +34 -14
  71. ksadk/cli/resource_common.py +6 -2
  72. ksadk/cli/storage.py +0 -1
  73. ksadk/cli/ui.py +5 -3
  74. ksadk/cli/workflow_common.py +51 -17
  75. ksadk/codex/__init__.py +12 -0
  76. ksadk/codex/client.py +408 -0
  77. ksadk/codex/phase.py +143 -0
  78. ksadk/codex/runtime.py +449 -0
  79. ksadk/common/aicp_env.py +0 -1
  80. ksadk/common/auth.py +2 -2
  81. ksadk/common/constants.py +1 -3
  82. ksadk/common/llm_utils.py +17 -13
  83. ksadk/compat/__init__.py +5 -0
  84. ksadk/compat/adk_compat.py +200 -0
  85. ksadk/compat/copilotkit_a2ui.py +330 -0
  86. ksadk/configs/__init__.py +12 -12
  87. ksadk/configs/env_registry.py +500 -100
  88. ksadk/configs/global_config.py +2 -1
  89. ksadk/configs/settings.py +151 -124
  90. ksadk/conversations/__init__.py +7 -5
  91. ksadk/conversations/attachment_storage.py +16 -11
  92. ksadk/conversations/attachments.py +44 -36
  93. ksadk/conversations/compaction_pipeline.py +12 -12
  94. ksadk/conversations/compaction_prompt.py +9 -5
  95. ksadk/conversations/context.py +221 -6
  96. ksadk/conversations/message_projection.py +438 -51
  97. ksadk/conversations/model_context.py +12 -6
  98. ksadk/conversations/model_options.py +0 -1
  99. ksadk/conversations/normalize.py +20 -16
  100. ksadk/conversations/reasoning_markup.py +1 -1
  101. ksadk/conversations/runtime.py +339 -5255
  102. ksadk/conversations/runtime_compaction.py +333 -0
  103. ksadk/conversations/runtime_constants.py +27 -0
  104. ksadk/conversations/runtime_governance.py +185 -0
  105. ksadk/conversations/runtime_input.py +652 -0
  106. ksadk/conversations/runtime_invocation.py +395 -0
  107. ksadk/conversations/runtime_metadata.py +475 -0
  108. ksadk/conversations/runtime_observability.py +355 -0
  109. ksadk/conversations/runtime_payloads.py +272 -0
  110. ksadk/conversations/runtime_persistence.py +440 -0
  111. ksadk/conversations/runtime_preparation.py +418 -0
  112. ksadk/conversations/runtime_resume.py +816 -0
  113. ksadk/conversations/runtime_stream_events.py +902 -0
  114. ksadk/conversations/runtime_streaming.py +547 -0
  115. ksadk/conversations/semantic_summary.py +17 -5
  116. ksadk/conversations/session_title.py +6 -3
  117. ksadk/deployment/__init__.py +15 -16
  118. ksadk/deployment/agent_access.py +12 -23
  119. ksadk/deployment/base.py +51 -38
  120. ksadk/deployment/manager.py +63 -65
  121. ksadk/deployment/providers/serverless.py +309 -202
  122. ksadk/deployment/registry.py +38 -32
  123. ksadk/deployment/state.py +11 -11
  124. ksadk/deployment/ui_config.py +1 -1
  125. ksadk/detection/__init__.py +1 -1
  126. ksadk/detection/detector.py +146 -83
  127. ksadk/detection/mcp_detector.py +9 -6
  128. ksadk/events/__init__.py +25 -0
  129. ksadk/events/parser.py +191 -0
  130. ksadk/events/replay.py +37 -0
  131. ksadk/events/runtime_event.py +264 -0
  132. ksadk/events/store.py +317 -0
  133. ksadk/harness/__init__.py +34 -0
  134. ksadk/harness/app.py +278 -0
  135. ksadk/harness/config.py +181 -0
  136. ksadk/harness/reasoner.py +105 -0
  137. ksadk/harness/runner.py +211 -0
  138. ksadk/harness/sandbox.py +141 -0
  139. ksadk/harness/tools.py +222 -0
  140. ksadk/hermes_terminal.py +23 -12
  141. ksadk/identity/resolver.py +15 -9
  142. ksadk/ids.py +32 -0
  143. ksadk/knowledge_base/adk_tool.py +1 -1
  144. ksadk/knowledge_base/client.py +23 -29
  145. ksadk/managed_runtime.py +188 -0
  146. ksadk/markdown.py +5 -2
  147. ksadk/mcp_runtime/__init__.py +9 -6
  148. ksadk/memory/__init__.py +1 -1
  149. ksadk/memory/adk/__init__.py +2 -0
  150. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  151. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  152. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  153. ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
  154. ksadk/memory/adk/long_term_memory.py +31 -35
  155. ksadk/memory/adk/resilient_session_service.py +4 -5
  156. ksadk/memory/adk/short_term_memory.py +12 -21
  157. ksadk/memory/adk_tool.py +3 -2
  158. ksadk/memory/backends/base.py +19 -19
  159. ksadk/memory/backends/memory.py +24 -25
  160. ksadk/memory/backends/redis.py +31 -30
  161. ksadk/memory/langchain_tool.py +2 -1
  162. ksadk/memory/manager.py +52 -47
  163. ksadk/memory/service.py +10 -8
  164. ksadk/model_policy.py +15 -7
  165. ksadk/model_proxy/__init__.py +51 -0
  166. ksadk/model_proxy/bootstrap.py +80 -0
  167. ksadk/model_proxy/cache.py +165 -0
  168. ksadk/model_proxy/config.py +45 -0
  169. ksadk/model_proxy/demo_webui.py +115 -0
  170. ksadk/model_proxy/detect.py +145 -0
  171. ksadk/model_proxy/gate.py +68 -0
  172. ksadk/model_proxy/namespace.py +173 -0
  173. ksadk/model_proxy/protocol_proxy.py +22 -0
  174. ksadk/model_proxy/server.py +300 -0
  175. ksadk/model_proxy/transform.py +691 -0
  176. ksadk/openclaw_gateway.py +29 -14
  177. ksadk/runners/adk_runner.py +345 -120
  178. ksadk/runners/base_runner.py +46 -29
  179. ksadk/runners/codex_runner.py +132 -0
  180. ksadk/runners/deepagents_runner.py +0 -1
  181. ksadk/runners/factory.py +17 -5
  182. ksadk/runners/langchain_runner.py +29 -742
  183. ksadk/runners/langgraph_runner.py +352 -90
  184. ksadk/runners/patch_langchain.py +16 -16
  185. ksadk/runners/remote_runner.py +134 -33
  186. ksadk/runners/usage_accumulator.py +1 -0
  187. ksadk/runners/utils/langfuse.py +3 -3
  188. ksadk/runners/utils/loader.py +7 -7
  189. ksadk/runtime/__init__.py +41 -0
  190. ksadk/runtime/adapter.py +345 -0
  191. ksadk/runtime/framework_adapters.py +124 -0
  192. ksadk/runtime/preprocessing.py +118 -0
  193. ksadk/runtime/runner_adapter.py +873 -0
  194. ksadk/runtime_context.py +18 -3
  195. ksadk/runtime_state.py +0 -1
  196. ksadk/sandbox/__init__.py +4 -1
  197. ksadk/sandbox/backends/__init__.py +4 -1
  198. ksadk/sandbox/backends/e2b.py +13 -5
  199. ksadk/sandbox/backends/local_process.py +11 -3
  200. ksadk/sandbox/base.py +10 -15
  201. ksadk/sandbox/factory.py +14 -4
  202. ksadk/sandbox/registry.py +57 -6
  203. ksadk/server/api_models.py +15 -5
  204. ksadk/server/app.py +455 -3885
  205. ksadk/server/composition.py +21 -0
  206. ksadk/server/factory.py +624 -0
  207. ksadk/server/routes/__init__.py +1 -0
  208. ksadk/server/routes/checkpoint_resolution.py +116 -0
  209. ksadk/server/routes/common.py +713 -0
  210. ksadk/server/routes/control.py +327 -0
  211. ksadk/server/routes/dependencies.py +98 -0
  212. ksadk/server/routes/misc.py +448 -0
  213. ksadk/server/routes/models.py +443 -0
  214. ksadk/server/routes/openai_compat.py +207 -0
  215. ksadk/server/routes/projection.py +795 -0
  216. ksadk/server/routes/routers.py +52 -0
  217. ksadk/server/routes/run.py +726 -0
  218. ksadk/server/routes/sessions.py +649 -0
  219. ksadk/server/routes/streaming.py +223 -0
  220. ksadk/server/routes/workspace.py +381 -0
  221. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
  222. ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
  223. ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
  224. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
  225. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
  226. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
  227. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
  228. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
  229. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
  230. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
  231. ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
  232. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
  233. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
  234. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
  235. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
  236. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
  237. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
  238. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
  239. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
  240. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
  241. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
  242. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
  243. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
  244. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
  245. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
  246. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
  247. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
  248. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
  249. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
  250. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
  251. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
  252. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
  253. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
  254. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
  255. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
  256. ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
  257. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
  258. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
  259. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
  260. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
  261. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
  262. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
  263. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
  264. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
  265. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
  266. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
  267. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
  268. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
  269. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
  270. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
  271. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
  272. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
  273. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
  274. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
  275. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
  276. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
  277. ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
  278. ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
  279. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
  280. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
  281. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
  282. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
  283. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
  284. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
  285. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
  286. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
  287. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
  288. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
  289. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
  290. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
  291. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
  292. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
  293. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
  294. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
  295. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
  296. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
  297. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
  298. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
  299. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
  300. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
  301. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
  302. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
  303. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
  304. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
  305. ksadk/server/static/index.html +2 -2
  306. ksadk/server/terminal_sessions.py +111 -58
  307. ksadk/sessions/__init__.py +69 -19
  308. ksadk/sessions/base.py +31 -11
  309. ksadk/sessions/continuity.py +2 -3
  310. ksadk/sessions/in_memory.py +46 -2
  311. ksadk/sessions/local_service.py +148 -17
  312. ksadk/sessions/postgres_service.py +143 -25
  313. ksadk/sessions/resilient.py +36 -8
  314. ksadk/skills/models.py +17 -5
  315. ksadk/skills/package_store.py +5 -2
  316. ksadk/skills/runtime/agent.py +20 -5
  317. ksadk/skills/runtime/artifacts.py +1 -5
  318. ksadk/skills/runtime/backends/e2b.py +10 -4
  319. ksadk/skills/runtime/backends/local.py +15 -3
  320. ksadk/skills/runtime/base.py +1 -2
  321. ksadk/skills/runtime/executor.py +10 -3
  322. ksadk/skills/runtime/factory.py +4 -2
  323. ksadk/skills/runtime/loader.py +1 -2
  324. ksadk/skills/runtime/registry.py +15 -10
  325. ksadk/skills/runtime/request.py +3 -1
  326. ksadk/skills/service_client.py +38 -17
  327. ksadk/skills/tool_defs.py +15 -10
  328. ksadk/terminal_exec_policy.py +3 -4
  329. ksadk/tools/gateway.py +92 -15
  330. ksadk/tools/result_budget.py +12 -4
  331. ksadk/toolsets/__init__.py +134 -36
  332. ksadk/toolsets/platform.py +21 -5
  333. ksadk/toolsets/sandbox.py +82 -16
  334. ksadk/toolsets/skills.py +200 -39
  335. ksadk/toolsets/web.py +123 -26
  336. ksadk/toolsets/workspace.py +212 -101
  337. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  338. ksadk/tracing/exporters/langfuse_exporter.py +91 -76
  339. ksadk/tracing/setup.py +69 -53
  340. ksadk/tracing/span_utils.py +5 -2
  341. ksadk/tui/loop.py +78 -30
  342. ksadk/tui/stream_render.py +1 -0
  343. ksadk/ui_config.py +5 -3
  344. ksadk/version.py +1 -1
  345. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  346. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  347. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  348. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  349. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  350. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  351. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  352. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  353. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  354. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  355. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  356. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  357. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  358. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  359. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  360. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  361. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  362. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  363. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  364. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  365. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  366. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  367. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  368. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
  369. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
  370. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
  371. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,443 @@
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.runners.base_runner import BaseRunner
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(active_runner: BaseRunner) -> str:
262
+ runtime_id = _clean_optional_string(os.getenv("AGENT_RUNTIME_ID"))
263
+ if runtime_id:
264
+ return runtime_id
265
+ return str(getattr(active_runner.detection_result, "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
+ run_mode = str(metadata.get("run_mode") or RUN_MODE_UNKNOWN)
429
+ run_trigger = str(metadata.get("run_trigger") or RUN_TRIGGER_UNKNOWN)
430
+ break
431
+ return invocation_id, status, run_mode, run_trigger
432
+
433
+
434
+ class WorkspaceDeleteActionRequest(BaseModel):
435
+ AgentId: Optional[str] = None
436
+ Path: str
437
+
438
+
439
+ class CancelRunActionRequest(BaseModel):
440
+ AgentId: Optional[str] = None
441
+ UserId: Optional[str] = None
442
+ SessionId: Optional[str] = None
443
+ InvocationId: str
@@ -0,0 +1,207 @@
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.run_kinds import RUN_MODE_FOREGROUND, trigger_from_resume_input
13
+
14
+ from . import dependencies as deps
15
+ from .checkpoint_resolution import _resolve_checkpoint_resume_input_from_session
16
+ from .common import _prepare_runner_for_model, _resolve_active_runner
17
+ from .models import (
18
+ ResponsesRequest,
19
+ _clean_optional_string,
20
+ _metadata_invocation_id,
21
+ _resolve_responses_session_and_user,
22
+ _runtime_agent_id,
23
+ _split_custom_metadata,
24
+ )
25
+ from .routers import openai_compat_router
26
+ from .streaming import _detached_resume_key_from_input, _reject_if_detached_resume_active
27
+ from .workspace import _build_models_payload
28
+
29
+
30
+ class ChatCompletionRequest(BaseModel):
31
+ messages: List[Dict[str, Any]]
32
+ model: Optional[str] = None
33
+ model_metadata: Optional[Dict[str, Any]] = None
34
+ model_options: Optional[Dict[str, Any]] = None
35
+ stream: bool = False
36
+ session_id: Optional[str] = None
37
+ user: Optional[str] = None
38
+ account_id: Optional[str] = None
39
+ metadata: Optional[Dict[str, Any]] = None
40
+ temperature: Optional[float] = 0.7
41
+ max_tokens: Optional[int] = None
42
+
43
+
44
+ @openai_compat_router.get("/v1/models")
45
+ async def list_openai_models():
46
+ """Expose the current model catalog through the OpenAI-compatible path."""
47
+
48
+ payload = await _build_models_payload()
49
+ return {
50
+ "object": "list",
51
+ "data": payload.get("data", []),
52
+ "current": payload.get("current"),
53
+ "source": payload.get("source", ""),
54
+ }
55
+
56
+
57
+ @openai_compat_router.post("/v1/responses")
58
+ async def responses(request: ResponsesRequest):
59
+ """OpenAI Responses 兼容接口。"""
60
+ active_runner = _resolve_active_runner()
61
+ resolved_session_id, resolved_user_id = _resolve_responses_session_and_user(request)
62
+ agent_id = _runtime_agent_id(active_runner)
63
+
64
+ resume_input = deps.conversation().extract_responses_resume_input(request.input)
65
+ resume_input = await _resolve_checkpoint_resume_input_from_session(
66
+ service=deps.resolve_session_service(),
67
+ agent_id=agent_id,
68
+ session_id=resolved_session_id,
69
+ resume_input=resume_input,
70
+ )
71
+ messages = (
72
+ []
73
+ if resume_input is not None
74
+ else deps.conversation().normalize_responses_input(request.input)
75
+ )
76
+ custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
77
+ if request.previous_response_id:
78
+ request_metadata["previous_response_id"] = request.previous_response_id
79
+ if request.prompt_cache_key:
80
+ request_metadata["prompt_cache_key"] = request.prompt_cache_key
81
+ if request.safety_identifier:
82
+ request_metadata["safety_identifier"] = request.safety_identifier
83
+ if request.user:
84
+ request_metadata["user"] = request.user
85
+ if request.conversation is not None:
86
+ request_metadata["conversation"] = request.conversation
87
+ if request.store is not None:
88
+ request_metadata["store"] = request.store
89
+ account_id = _clean_optional_string(request.account_id)
90
+ invocation_id = _metadata_invocation_id(request_metadata)
91
+
92
+ if request.stream:
93
+ resume_key = _detached_resume_key_from_input(resolved_session_id, resume_input)
94
+ _reject_if_detached_resume_active(resume_key)
95
+ return deps.detached_streaming_response(
96
+ deps.conversation().stream_responses_conversation_turn(
97
+ runner=active_runner,
98
+ agent_id=agent_id,
99
+ user_id=resolved_user_id,
100
+ messages=messages,
101
+ session_id=resolved_session_id,
102
+ model=request.model,
103
+ model_metadata=request.model_metadata,
104
+ model_options=request.model_options,
105
+ instructions=request.instructions,
106
+ request_metadata=request_metadata,
107
+ custom_metadata=custom_metadata,
108
+ resume_input=resume_input,
109
+ account_id=account_id,
110
+ invocation_id=invocation_id,
111
+ prepare_runner=_prepare_runner_for_model,
112
+ session_service_provider=deps.resolve_session_service,
113
+ run_mode=RUN_MODE_FOREGROUND,
114
+ ),
115
+ invocation_id=invocation_id,
116
+ resume_key=resume_key,
117
+ run_mode=RUN_MODE_FOREGROUND,
118
+ run_trigger=trigger_from_resume_input(resume_input),
119
+ )
120
+
121
+ response_id = f"resp_{uuid.uuid4().hex}"
122
+ resolved_session_id, result = await deps.conversation().invoke_conversation_once(
123
+ runner=active_runner,
124
+ agent_id=agent_id,
125
+ user_id=resolved_user_id,
126
+ messages=messages,
127
+ session_id=resolved_session_id,
128
+ model=request.model,
129
+ model_metadata=request.model_metadata,
130
+ model_options=request.model_options,
131
+ instructions=request.instructions,
132
+ request_metadata=request_metadata,
133
+ custom_metadata=custom_metadata,
134
+ resume_input=resume_input,
135
+ response_id=response_id,
136
+ account_id=account_id,
137
+ invocation_id=invocation_id,
138
+ prepare_runner=_prepare_runner_for_model,
139
+ session_service_provider=deps.resolve_session_service,
140
+ run_mode=RUN_MODE_FOREGROUND,
141
+ )
142
+ return deps.conversation().build_responses_payload(
143
+ output_text=result["output_text"],
144
+ model=request.model,
145
+ session_id=resolved_session_id,
146
+ response_id=response_id,
147
+ metadata=custom_metadata,
148
+ usage=result.get("usage") if isinstance(result.get("usage"), Mapping) else None,
149
+ )
150
+
151
+
152
+ @openai_compat_router.post("/v1/chat/completions")
153
+ async def chat_completions(request: ChatCompletionRequest):
154
+ """OpenAI 兼容的聊天补全接口 (支持流式和非流式)"""
155
+ active_runner = _resolve_active_runner()
156
+ messages = deps.conversation().normalize_kop_messages(request.messages)
157
+ agent_id = _runtime_agent_id(active_runner)
158
+ resolved_user_id = _clean_optional_string(request.user) or "user"
159
+ account_id = _clean_optional_string(request.account_id)
160
+ custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
161
+ invocation_id = _metadata_invocation_id(request_metadata)
162
+
163
+ if request.stream:
164
+ return StreamingResponse(
165
+ deps.conversation().stream_conversation_turn(
166
+ runner=active_runner,
167
+ agent_id=agent_id,
168
+ user_id=resolved_user_id,
169
+ messages=messages,
170
+ session_id=request.session_id,
171
+ model=request.model,
172
+ model_metadata=request.model_metadata,
173
+ model_options=request.model_options,
174
+ request_metadata=request_metadata,
175
+ custom_metadata=custom_metadata,
176
+ invocation_id=invocation_id,
177
+ account_id=account_id,
178
+ prepare_runner=_prepare_runner_for_model,
179
+ session_service_provider=deps.resolve_session_service,
180
+ run_mode=RUN_MODE_FOREGROUND,
181
+ ),
182
+ media_type="text/event-stream",
183
+ )
184
+
185
+ resolved_session_id, result = await deps.conversation().invoke_conversation_once(
186
+ runner=active_runner,
187
+ agent_id=agent_id,
188
+ user_id=resolved_user_id,
189
+ messages=messages,
190
+ session_id=request.session_id,
191
+ model=request.model,
192
+ model_metadata=request.model_metadata,
193
+ model_options=request.model_options,
194
+ request_metadata=request_metadata,
195
+ custom_metadata=custom_metadata,
196
+ invocation_id=invocation_id,
197
+ account_id=account_id,
198
+ prepare_runner=_prepare_runner_for_model,
199
+ session_service_provider=deps.resolve_session_service,
200
+ run_mode=RUN_MODE_FOREGROUND,
201
+ )
202
+ return deps.conversation().build_chat_completions_payload(
203
+ output_text=result["output_text"],
204
+ model=request.model,
205
+ session_id=resolved_session_id,
206
+ metadata=result.get("metadata"),
207
+ )