agentengine-sdk-python 0.6.9__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 (384) hide show
  1. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +41 -23
  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 +252 -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 +533 -726
  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 +173 -90
  54. ksadk/cli/cmd_invoke.py +388 -159
  55. ksadk/cli/cmd_launch.py +64 -28
  56. ksadk/cli/cmd_mcp.py +103 -64
  57. ksadk/cli/cmd_model.py +14 -5
  58. ksadk/cli/cmd_openclaw.py +488 -228
  59. ksadk/cli/cmd_replay.py +71 -0
  60. ksadk/cli/cmd_run.py +44 -14
  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 +38 -16
  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 +501 -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 +656 -0
  97. ksadk/conversations/model_context.py +22 -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 -5187
  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 +52 -39
  120. ksadk/deployment/manager.py +63 -65
  121. ksadk/deployment/providers/serverless.py +326 -209
  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 +267 -0
  156. ksadk/memory/adk/short_term_memory.py +33 -27
  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 +1248 -164
  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 -530
  183. ksadk/runners/langgraph_runner.py +490 -95
  184. ksadk/runners/patch_langchain.py +16 -16
  185. ksadk/runners/remote_runner.py +264 -38
  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 -3743
  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-C0meuOdi.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-bj2rZnP5.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-2u1ltDIj.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
  229. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-D6fvdK20.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
  230. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-BK82L5n5.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
  231. ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
  232. ksadk/server/static/assets/{chunk-2J33WTMH-DLVdkeyQ.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
  233. ksadk/server/static/assets/{chunk-4BX2VUAB-BbwsYcbW.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
  234. ksadk/server/static/assets/{chunk-55IACEB6-DOairxzw.js → chunk-55IACEB6-BK8paA20.js} +1 -1
  235. ksadk/server/static/assets/{chunk-727SXJPM-hCO487gs.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
  236. ksadk/server/static/assets/{chunk-AQP2D5EJ-XU8vDOuG.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
  237. ksadk/server/static/assets/{chunk-FMBD7UC4-PrapyfMu.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
  238. ksadk/server/static/assets/{chunk-ND2GUHAM-CboKhTZ3.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-_N8bJ-EU.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
  243. ksadk/server/static/assets/{dagre-BM42HDAG-FoDlo5J2.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
  244. ksadk/server/static/assets/{diagram-2AECGRRQ-BBp6ebBw.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
  245. ksadk/server/static/assets/{diagram-5GNKFQAL-CqOvG1PR.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
  246. ksadk/server/static/assets/{diagram-KO2AKTUF-O9T3t6ba.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
  247. ksadk/server/static/assets/{diagram-LMA3HP47-CGG8ekBO.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
  248. ksadk/server/static/assets/{diagram-OG6HWLK6-4BmH1EEg.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
  249. ksadk/server/static/assets/{dist-CiZHB6ZW.js → dist-6CVKuTAe.js} +1 -1
  250. ksadk/server/static/assets/{dist-BMKM66B4.js → dist-BUHRxvDG.js} +1 -1
  251. ksadk/server/static/assets/{dist-CZ6C3x8B.js → dist-BZ9n9AjO.js} +1 -1
  252. ksadk/server/static/assets/{dist-DbaH3p5h.js → dist-BibcG1V9.js} +1 -1
  253. ksadk/server/static/assets/{dist-BVzcWa6D.js → dist-Bs-jQcRX.js} +1 -1
  254. ksadk/server/static/assets/{dist-D99wf6_X.js → dist-C2xjE7cO.js} +1 -1
  255. ksadk/server/static/assets/{dist-DLMjL01k.js → dist-C7-3jInC.js} +1 -1
  256. ksadk/server/static/assets/{dist-DI-oVAXw.js → dist-C99THtIA.js} +1 -1
  257. ksadk/server/static/assets/{dist-BkJjNih3.js → dist-CGcp2ex8.js} +1 -1
  258. ksadk/server/static/assets/{dist-D5JGcxBx.js → dist-CVQRZjPu.js} +1 -1
  259. ksadk/server/static/assets/{dist-CWiTDN_V.js → dist-Cf23NY4L.js} +1 -1
  260. ksadk/server/static/assets/{dist-DLeM1OCK.js → dist-CgF3fj15.js} +1 -1
  261. ksadk/server/static/assets/{dist-BmuTWcm7.js → dist-Cwt7koer.js} +1 -1
  262. ksadk/server/static/assets/{dist-C2DKRFVK.js → dist-D82mtD2s.js} +1 -1
  263. ksadk/server/static/assets/{dist-B67uF2uK.js → dist-DF06ORQo.js} +1 -1
  264. ksadk/server/static/assets/{dist-Cwhk4lwI.js → dist-DHn6nBzr.js} +1 -1
  265. ksadk/server/static/assets/{dist-S4klkK5W.js → dist-Djgl2wVZ.js} +1 -1
  266. ksadk/server/static/assets/{dist-DCpZrjaK.js → dist-DlzCRy0S.js} +1 -1
  267. ksadk/server/static/assets/{dist-Cp1_jKwf.js → dist-DqNnNFrw.js} +1 -1
  268. ksadk/server/static/assets/{dist-6kSZvCZh.js → dist-DyvYLMW9.js} +1 -1
  269. ksadk/server/static/assets/{dist-DM0rEQPk.js → dist-eoW6tZXA.js} +1 -1
  270. ksadk/server/static/assets/{dist-Bk1l05Ni.js → dist-ivOya1LD.js} +1 -1
  271. ksadk/server/static/assets/{erDiagram-TEJ5UH35-oJhaci7S.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-DtTmUan-.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
  274. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BSsb_eij.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-BR5s6Pws.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-DYPc5cvh.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
  281. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-MoBdALDg.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
  282. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-DgLiQT8l.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
  283. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-CsFx112F.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
  284. ksadk/server/static/assets/{katex-DRsiwpM2.js → katex-DATssjp1.js} +1 -1
  285. ksadk/server/static/assets/{linear-TNRQ5Orv.js → linear-CvMBw9cA.js} +1 -1
  286. ksadk/server/static/assets/{mermaid-parser.core-D2eMVOgo.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
  287. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-BtByYFhL.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-DPnuCB8c.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
  291. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-miFpCPv4.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-mjB_yYkW.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
  294. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-D7hSlZZZ.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
  295. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-D9Cx6hC3.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
  296. ksadk/server/static/assets/{stateDiagram-AJRCARHV-D_zrg47o.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-CwSec0Wa.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-agCVobiF.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-TmrlhWNt.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
  304. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-DV71V-ah.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 +86 -40
  308. ksadk/sessions/base.py +31 -11
  309. ksadk/sessions/continuity.py +28 -5
  310. ksadk/sessions/in_memory.py +46 -2
  311. ksadk/sessions/local_service.py +148 -17
  312. ksadk/sessions/postgres_service.py +216 -35
  313. ksadk/sessions/resilience.py +52 -0
  314. ksadk/sessions/resilient.py +388 -0
  315. ksadk/skills/models.py +17 -5
  316. ksadk/skills/package_store.py +5 -2
  317. ksadk/skills/runtime/agent.py +20 -5
  318. ksadk/skills/runtime/artifacts.py +1 -5
  319. ksadk/skills/runtime/backends/e2b.py +10 -4
  320. ksadk/skills/runtime/backends/local.py +15 -3
  321. ksadk/skills/runtime/base.py +1 -2
  322. ksadk/skills/runtime/executor.py +10 -3
  323. ksadk/skills/runtime/factory.py +4 -2
  324. ksadk/skills/runtime/loader.py +1 -2
  325. ksadk/skills/runtime/registry.py +15 -10
  326. ksadk/skills/runtime/request.py +3 -1
  327. ksadk/skills/service_client.py +38 -17
  328. ksadk/skills/tool_defs.py +15 -10
  329. ksadk/terminal_exec_policy.py +3 -4
  330. ksadk/tools/gateway.py +92 -15
  331. ksadk/tools/result_budget.py +12 -4
  332. ksadk/toolsets/__init__.py +136 -36
  333. ksadk/toolsets/platform.py +21 -5
  334. ksadk/toolsets/sandbox.py +82 -16
  335. ksadk/toolsets/skills.py +200 -39
  336. ksadk/toolsets/web.py +123 -26
  337. ksadk/toolsets/workspace.py +264 -114
  338. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  339. ksadk/tracing/exporters/langfuse_exporter.py +91 -76
  340. ksadk/tracing/setup.py +132 -53
  341. ksadk/tracing/span_utils.py +5 -2
  342. ksadk/tui/__init__.py +22 -7
  343. ksadk/tui/loop.py +1925 -0
  344. ksadk/tui/stream_render.py +69 -0
  345. ksadk/ui_config.py +5 -3
  346. ksadk/version.py +1 -1
  347. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  348. agentengine_sdk_python-0.6.9.dist-info/RECORD +0 -487
  349. ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +0 -9
  350. ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +0 -8
  351. ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +0 -303
  352. ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +0 -1
  353. ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +0 -1
  354. ksadk/server/static/assets/channel-BSSOwFIb.js +0 -1
  355. ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +0 -1
  356. ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +0 -1
  357. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +0 -1
  358. ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +0 -1
  359. ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +0 -1
  360. ksadk/server/static/assets/index-BH7-pC0B.js +0 -165
  361. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  362. ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +0 -1
  363. ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +0 -1
  364. ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +0 -1
  365. ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +0 -1
  366. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +0 -1
  367. ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +0 -1
  368. ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +0 -1
  369. ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +0 -1
  370. ksadk/tui/app.py +0 -400
  371. ksadk/tui/clipboard.py +0 -100
  372. ksadk/tui/widgets/__init__.py +0 -22
  373. ksadk/tui/widgets/assistant.py +0 -89
  374. ksadk/tui/widgets/base.py +0 -54
  375. ksadk/tui/widgets/chat_input.py +0 -246
  376. ksadk/tui/widgets/history.py +0 -156
  377. ksadk/tui/widgets/system.py +0 -87
  378. ksadk/tui/widgets/thinking.py +0 -110
  379. ksadk/tui/widgets/tool_call.py +0 -161
  380. ksadk/tui/widgets/user.py +0 -37
  381. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
  382. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
  383. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
  384. {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
ksadk/codex/phase.py ADDED
@@ -0,0 +1,143 @@
1
+ """codex_phase — Codex app-server agent message 的相位(phase)翻译 (goal-09 契约 2)。
2
+
3
+ 镜像 `Wegent/executor/src/codex_phase.rs`:
4
+
5
+ - 流式 live 事件**不在每个 delta 上重复相位**——``item/started`` 带
6
+ ``params.item.id`` + ``params.item.phase``;后续 ``item/agentMessage/delta`` 只带
7
+ ``params.itemId`` + ``params.delta``(无 phase)。
8
+ - 因此必须**按 itemId 追踪相位,按解析出的相位路由 delta**;**不从文本内容推断相位**,
9
+ 不等 ``item/completed`` 才更新 UI。
10
+ - 映射到 RuntimeEvent schema 的 ``phase`` 字段(commentary/final_answer),
11
+ **相位翻译独立成模块,不揉进 CodexRuntime 主逻辑,不混入最终答案**。
12
+
13
+ Codex 相位:``commentary`` / ``analysis`` 属过程解说(process),``final_answer`` 是
14
+ 最终答案。映射到 RuntimeEvent:process → ``commentary``,final_answer → ``final_answer``。
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import Any, Optional
20
+
21
+ #: Codex 相位 → RuntimeEvent phase 字段。analysis/commentary 都是过程解说。
22
+ _PROCESS_PHASES = frozenset({"analysis", "commentary"})
23
+
24
+ _PHASE_KEYS = ("phase", "channel")
25
+ _ITEM_ID_KEYS = ("itemId", "item_id", "id", "messageId", "message_id")
26
+
27
+
28
+ def _normalize_phase(value: str) -> str:
29
+ # Pydantic's Python-mode dump renders enums as ``MessagePhase.final_answer``.
30
+ # JSON-mode is used by the production client, while accepting this spelling
31
+ # keeps replayed samples from older KSADK builds readable.
32
+ return value.rsplit(".", 1)[-1].replace("_", "").replace("-", "").strip().lower()
33
+
34
+
35
+ def codex_phase_name(value: dict[str, Any]) -> Optional[str]:
36
+ """从事件 params 里读相位字段(phase / channel)并归一化。"""
37
+ if not isinstance(value, dict):
38
+ return None
39
+ for key in _PHASE_KEYS:
40
+ raw = value.get(key)
41
+ if isinstance(raw, str):
42
+ normalized = _normalize_phase(raw)
43
+ if normalized:
44
+ return normalized
45
+ return None
46
+
47
+
48
+ def codex_item_id(value: dict[str, Any]) -> Optional[str]:
49
+ """从事件 params 里读 itemId(itemId/item_id/id/messageId/message_id)。"""
50
+ if not isinstance(value, dict):
51
+ return None
52
+ for key in _ITEM_ID_KEYS:
53
+ raw = value.get(key)
54
+ if isinstance(raw, str) and raw:
55
+ return raw
56
+ return None
57
+
58
+
59
+ def runtime_phase_for(codex_phase: Optional[str]) -> Optional[str]:
60
+ """把 codex 相位映射为 RuntimeEvent phase(commentary / final_answer)。"""
61
+ if codex_phase is None:
62
+ return None
63
+ if codex_phase in _PROCESS_PHASES:
64
+ return "commentary"
65
+ if codex_phase == "finalanswer" or codex_phase == "final_answer":
66
+ return "final_answer"
67
+ return None
68
+
69
+
70
+ def _item_params(params: dict[str, Any]) -> dict[str, Any]:
71
+ """取事件里嵌套的 ``item`` 子对象(若无则返回 params 本身),类型收窄为 dict。"""
72
+ item = params.get("item")
73
+ return item if isinstance(item, dict) else params
74
+
75
+
76
+ class CodexPhaseTracker:
77
+ """按 itemId 追踪 assistant message 的相位,按相位路由流式 delta。"""
78
+
79
+ def __init__(self) -> None:
80
+ self._phases_by_item_id: dict[str, str] = {}
81
+
82
+ def observe_item(self, params: dict[str, Any]) -> None:
83
+ """item/started(或 reload/completed):记录 itemId -> phase。
84
+
85
+ codex 真实流 agentMessage 的 phase 常为 null,但 agentMessage 就是最终回复
86
+ (final_answer),reasoning 才是 commentary。phase 为 null 时按 item type 兜底:
87
+ agentMessage → final_answer,reasoning → commentary。
88
+ """
89
+ item = _item_params(params)
90
+ item_id = codex_item_id(item) or codex_item_id(params)
91
+ phase = codex_phase_name(item) or codex_phase_name(params)
92
+ if not phase and item_id:
93
+ item_type = item.get("type") if isinstance(item, dict) else None
94
+ if item_type == "agentMessage":
95
+ phase = "final_answer"
96
+ elif item_type == "reasoning":
97
+ phase = "commentary"
98
+ if item_id and phase:
99
+ self._phases_by_item_id[item_id] = phase
100
+
101
+ def phase_for_delta(self, params: dict[str, Any]) -> Optional[str]:
102
+ """item/agentMessage/delta:优先事件自带 phase,否则按 itemId 查追踪表。"""
103
+ direct = codex_phase_name(params)
104
+ if direct:
105
+ return direct
106
+ item_id = codex_item_id(params)
107
+ if item_id:
108
+ return self._phases_by_item_id.get(item_id)
109
+ return None
110
+
111
+ def phase_for_item(self, params: dict[str, Any]) -> Optional[str]:
112
+ """item/completed / reload:事件或 item 内的 phase,再退回追踪表。"""
113
+ item = _item_params(params)
114
+ direct = codex_phase_name(item) or codex_phase_name(params)
115
+ if direct:
116
+ return direct
117
+ item_id = codex_item_id(item) or codex_item_id(params)
118
+ if item_id:
119
+ return self._phases_by_item_id.get(item_id)
120
+ return None
121
+
122
+ def runtime_phase_for_delta(self, params: dict[str, Any]) -> Optional[str]:
123
+ """delta 的 RuntimeEvent phase(commentary/final_answer)。"""
124
+ return runtime_phase_for(self.phase_for_delta(params))
125
+
126
+ def runtime_phase_for_item(self, params: dict[str, Any]) -> Optional[str]:
127
+ """item 的 RuntimeEvent phase(commentary/final_answer)。"""
128
+ return runtime_phase_for(self.phase_for_item(params))
129
+
130
+ def forget_item(self, params: dict[str, Any]) -> None:
131
+ """item/completed 后清理追踪项。"""
132
+ item = _item_params(params)
133
+ item_id = codex_item_id(item) or codex_item_id(params)
134
+ if item_id:
135
+ self._phases_by_item_id.pop(item_id, None)
136
+
137
+
138
+ __all__ = [
139
+ "CodexPhaseTracker",
140
+ "codex_item_id",
141
+ "codex_phase_name",
142
+ "runtime_phase_for",
143
+ ]
ksadk/codex/runtime.py ADDED
@@ -0,0 +1,449 @@
1
+ """CodexRuntime — 非 ADK 体系的第三验证样本,按 Wegent 重托管模式 (goal-09)。
2
+
3
+ 对执行生命周期负责(不做 veadk 式薄桥接),后端能力面对齐 ``openai-codex`` SDK 真实线程模型
4
+ (``thread_start``/``thread.turn``/``handle.stream``/``handle.interrupt``/``thread_resume``):
5
+
6
+ - **cancel 状态机**(不薄委托给上层):活跃 turn → ``client.interrupt_active_turn``
7
+ (真实 SDK ``handle.interrupt``,终止当前 turn 执行;thread 由 codex 后端托管,无"杀进程"
8
+ 概念);无活跃 turn → 记 pending 下个 turn 消费;**级联丢弃 pending 工具审批**(runtime
9
+ 自跟踪的 pending 集);返回 ``CancelResult`` 枚举;**被中断的 turn 不持久化其 session**
10
+ (避免 resume 捡到写了一半的会话)。
11
+ - **phase 翻译**(:mod:`ksadk.codex.phase`):按 itemId 路由 commentary/final_answer delta,
12
+ 映射 RuntimeEvent phase,不混入主逻辑。
13
+ - **resume 建模为 thread id**(真实 SDK ``thread_resume``),不套 ADK invocation 模型;
14
+ ResumeTarget(thread id)/ResumePayload(工具结果/HITL 回答)分离。
15
+
16
+ 环境约束:read-only sandbox(默认),单轮含一次工具调用即可跑通。
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import asyncio
22
+ import json
23
+ import logging
24
+ from dataclasses import dataclass, field
25
+ from typing import Any, AsyncIterator, Optional
26
+
27
+ from ksadk.codex.client import CodexClient
28
+ from ksadk.codex.phase import CodexPhaseTracker
29
+ from ksadk.events.runtime_event import EventType, RuntimeEvent
30
+ from ksadk.runtime.adapter import (
31
+ BaseRuntime,
32
+ CancelResult,
33
+ CheckpointCapability,
34
+ CheckpointDescriptor,
35
+ ResumePayload,
36
+ ResumeTarget,
37
+ RunHandle,
38
+ RuntimeAdapter,
39
+ StartRequest,
40
+ )
41
+
42
+ logger = logging.getLogger(__name__)
43
+
44
+
45
+ class _CodexAsBaseRuntime(BaseRuntime):
46
+ """把 CodexClient 包装为 BaseRuntime(原生能力面)。"""
47
+
48
+ def __init__(self, client: CodexClient) -> None:
49
+ self._client = client
50
+ self.runtime_type = "codex"
51
+
52
+ def native_capabilities(self) -> dict[str, Any]:
53
+ return {"Framework": "codex", "cancel": "thread", "resume": "thread_id"}
54
+
55
+
56
+ @dataclass
57
+ class _CodexThread:
58
+ thread_id: str
59
+ turn_id: Optional[str] = None
60
+ streaming: bool = False
61
+ interrupt_event: asyncio.Event = field(default_factory=asyncio.Event)
62
+ pending_approvals: set[str] = field(default_factory=set)
63
+ done: bool = False
64
+ interrupted: bool = False
65
+
66
+
67
+ class CodexRuntime(RuntimeAdapter):
68
+ """Codex 的 RuntimeAdapter(重托管)。"""
69
+
70
+ def __init__(
71
+ self,
72
+ client: CodexClient,
73
+ *,
74
+ sandbox_read_only: bool = True,
75
+ turn_timeout_seconds: Optional[float] = None,
76
+ ) -> None:
77
+ super().__init__(_CodexAsBaseRuntime(client))
78
+ self._client = client
79
+ self._sandbox_read_only = sandbox_read_only
80
+ self._turn_timeout_seconds = turn_timeout_seconds
81
+ self._threads: dict[str, _CodexThread] = {}
82
+ self._known_threads: set[str] = set()
83
+ self._pending_cancels: set[str] = set()
84
+ # 被杀/interrupt 的 session 不持久化(goal-09 契约 1)。
85
+ self._do_not_persist: set[str] = set()
86
+ # 可观测:最近一次 cancel 级联丢弃的审批集(contract test 断言用)。
87
+ self.last_cancel_dropped_approvals: set[str] = set()
88
+ self._seq = 0
89
+
90
+ # ---- 六动词 ----
91
+
92
+ async def start(self, request: StartRequest) -> RunHandle:
93
+ # 新 thread 由后端分配真实 thread_id(thread_start);metadata 携带的 thread_id
94
+ # 表示接入既有 thread(resume 语义,run_turn 时按 resume 接入)。
95
+ provided = request.metadata.get("thread_id")
96
+ if provided:
97
+ thread_id = str(provided)
98
+ else:
99
+ # 把 model + base_instructions 传给 codex thread(配置契约,见 plan C)
100
+ thread_config: dict[str, Any] = {"sandbox_read_only": self._sandbox_read_only}
101
+ if request.model:
102
+ thread_config["model"] = request.model
103
+ base_instructions = request.config.get("base_instructions")
104
+ if base_instructions:
105
+ thread_config["base_instructions"] = base_instructions
106
+ thread_id = await self._client.start_thread(thread_config)
107
+ self._known_threads.add(thread_id)
108
+ thread = _CodexThread(thread_id=thread_id)
109
+ thread.__dict__["_start_request"] = request
110
+ self._threads[thread_id] = thread
111
+ return RunHandle(
112
+ run_id=thread_id,
113
+ session_id=request.session_id,
114
+ runtime_type="codex",
115
+ native_ref={"thread_id": thread_id, "user_id": request.user_id},
116
+ )
117
+
118
+ def stream(self, handle: RunHandle) -> AsyncIterator[RuntimeEvent]:
119
+ return self._stream_events(handle)
120
+
121
+ async def cancel(self, handle: RunHandle) -> CancelResult:
122
+ thread_id = handle.run_id
123
+ thread = self._threads.get(thread_id)
124
+ is_active = thread is not None and not thread.done and thread.streaming
125
+ if not is_active:
126
+ if thread_id in self._known_threads:
127
+ self._pending_cancels.add(thread_id)
128
+ return CancelResult.PENDING_CANCEL_RECORDED
129
+ return CancelResult.NOT_RUNNING
130
+ assert thread is not None
131
+ try:
132
+ # 级联丢弃 pending 工具审批(快照 runtime 自跟踪的 pending 集,供观测)。
133
+ # 真实 SDK 无独立 drain API:interrupt 后 turn 停止,pending 审批随之失效。
134
+ self.last_cancel_dropped_approvals = set(thread.pending_approvals)
135
+ thread.pending_approvals.clear()
136
+ # 真实中断:handle.interrupt() 停活跃 turn(真实 SDK 机制;无"杀进程"概念,
137
+ # thread 由 codex 后端托管,interrupt 即终止当前 turn 的执行)。
138
+ interrupted = await self._client.interrupt_active_turn(thread.thread_id)
139
+ if not interrupted:
140
+ # 无活跃 handle 可 interrupt(竞态:turn 刚好结束)→ 视为未在运行。
141
+ return CancelResult.NOT_RUNNING
142
+ thread.interrupt_event.set()
143
+ # 被中断的 session 不持久化(goal-09 契约 1)。
144
+ self._do_not_persist.add(thread_id)
145
+ thread.done = True
146
+ self._threads.pop(thread_id, None)
147
+ self._pending_cancels.discard(thread_id)
148
+ return CancelResult.INTERRUPTED_ACTIVE_TURN
149
+ except Exception: # noqa: BLE001
150
+ logger.exception("codex cancel thread %s 失败", thread_id)
151
+ return CancelResult.FAILED
152
+
153
+ async def resume(
154
+ self,
155
+ handle: RunHandle,
156
+ target: ResumeTarget,
157
+ payload: Optional[ResumePayload],
158
+ ) -> RunHandle:
159
+ # resume 用 thread id 语义(resume_thread_id),不套 ADK invocation 模型。
160
+ if target.kind != "thread_id":
161
+ raise ValueError(f"CodexRuntime resume 仅支持 thread_id 目标,得到 {target.kind!r}")
162
+ if handle.run_id in self._do_not_persist:
163
+ raise ValueError(f"thread {handle.run_id} 已被中断/杀进程,不持久化,不可 resume")
164
+ self._pending_cancels.discard(handle.run_id)
165
+ self._known_threads.add(target.id)
166
+ thread = _CodexThread(thread_id=target.id)
167
+ thread.__dict__["_resume"] = {"target": target, "payload": payload}
168
+ self._threads[handle.run_id] = thread
169
+ # 真实恢复:thread_resume 接入后端既有 thread(thread_id 语义,不套 ADK invocation)。
170
+ await self._client.resume_thread(target.id, {"sandbox_read_only": self._sandbox_read_only})
171
+ handle.native_ref["thread_id"] = target.id
172
+ handle.native_ref["resume_thread_id"] = target.id
173
+ handle.native_ref["resume_payload"] = payload.data if payload else None
174
+ # 与 ADK/LangGraph 一致的 resume_input 结构(供共用 contract test 断言)。
175
+ handle.native_ref["resume_input"] = {
176
+ "type": "codex.resume_thread",
177
+ "thread_id": target.id,
178
+ "payload": payload.data if payload else None,
179
+ "payload_kind": payload.kind if payload else None,
180
+ "call_id": payload.call_id if payload else None,
181
+ }
182
+ return handle
183
+
184
+ async def checkpoint(self, handle: RunHandle) -> CheckpointDescriptor:
185
+ return CheckpointDescriptor(
186
+ checkpoint_id=str(handle.native_ref.get("thread_id") or handle.run_id),
187
+ invocation_id=handle.run_id,
188
+ capability=CheckpointCapability(
189
+ supported=True,
190
+ granularity="snapshot",
191
+ rollback_scope="turn",
192
+ fork_supported=True,
193
+ durable=False,
194
+ shared_across_pods=False,
195
+ reason="Codex resume/fork by thread id",
196
+ ),
197
+ ref={"thread_id": handle.native_ref.get("thread_id")},
198
+ )
199
+
200
+ async def close(self, handle: RunHandle) -> None:
201
+ thread = self._threads.pop(handle.run_id, None)
202
+ if thread is not None:
203
+ thread.interrupt_event.set()
204
+ try:
205
+ active_thread_id = thread.thread_id if thread is not None else handle.run_id
206
+ await self._client.interrupt_active_turn(active_thread_id)
207
+ finally:
208
+ # AsyncCodex.close owns terminate/wait/kill for the app-server child.
209
+ await self._client.close()
210
+ self._do_not_persist.add(handle.run_id)
211
+ self._known_threads.discard(handle.run_id)
212
+ self._pending_cancels.discard(handle.run_id)
213
+
214
+ # ---- stream → RuntimeEvent(phase 翻译 + 中断竞速) ----
215
+
216
+ def _next_thread_id(self) -> str:
217
+ self._seq += 1
218
+ return f"codex_thread_{self._seq}"
219
+
220
+ def _next_seq(self) -> int:
221
+ self._seq += 1
222
+ return self._seq
223
+
224
+ async def _stream_events(self, handle: RunHandle) -> AsyncIterator[RuntimeEvent]:
225
+ thread = self._threads.get(handle.run_id)
226
+ if thread is None:
227
+ thread = _CodexThread(thread_id=handle.run_id)
228
+ self._threads[handle.run_id] = thread
229
+
230
+ if handle.run_id in self._pending_cancels:
231
+ self._pending_cancels.discard(handle.run_id)
232
+ yield self._event(
233
+ handle,
234
+ EventType.RUN_CANCELED,
235
+ {
236
+ "status": "cancelled",
237
+ "cancel_result": CancelResult.PENDING_CANCEL_RECORDED.value,
238
+ },
239
+ )
240
+ return
241
+
242
+ yield self._event(handle, EventType.RUN_STARTED, {"status": "in_progress"})
243
+ tracker = CodexPhaseTracker()
244
+ request = thread.__dict__.get("_start_request")
245
+ resume_state = thread.__dict__.get("_resume")
246
+ if request is not None:
247
+ prompt = request.input
248
+ elif resume_state is not None:
249
+ prompt = _resume_prompt(resume_state.get("payload"))
250
+ else:
251
+ prompt = ""
252
+ thread.streaming = True
253
+ thread.turn_id = thread.turn_id or f"turn_{thread.thread_id}"
254
+ try:
255
+ async for event in self._map_codex_stream(handle, thread, tracker, prompt):
256
+ yield event
257
+ # 正常结束(非 interrupt):补 RUN_COMPLETED(AGUI 投射器据此发 RunFinished success)
258
+ if not thread.interrupted:
259
+ yield self._event(handle, EventType.RUN_COMPLETED, {"status": "completed"})
260
+ except TimeoutError:
261
+ self.last_cancel_dropped_approvals = set(thread.pending_approvals)
262
+ thread.pending_approvals.clear()
263
+ self._do_not_persist.add(handle.run_id)
264
+ # Closing the SDK transport terminates and waits for the app-server
265
+ # child even when the stream is stuck between notifications.
266
+ await self._client.close()
267
+ yield self._event(
268
+ handle,
269
+ EventType.RUN_FAILED,
270
+ {"status": "failed", "error": "codex turn timed out"},
271
+ )
272
+ except Exception as exc: # noqa: BLE001 通用兜底:任何异常都发 RUN_FAILED
273
+ self._do_not_persist.add(handle.run_id)
274
+ yield self._event(
275
+ handle,
276
+ EventType.RUN_FAILED,
277
+ {"status": "failed", "error": str(exc)},
278
+ )
279
+ finally:
280
+ thread.streaming = False
281
+ thread.done = True
282
+ self._threads.pop(handle.run_id, None)
283
+
284
+ async def _map_codex_stream(
285
+ self,
286
+ handle: RunHandle,
287
+ thread: _CodexThread,
288
+ tracker: CodexPhaseTracker,
289
+ prompt: Any,
290
+ ) -> AsyncIterator[RuntimeEvent]:
291
+ codex_gen = self._client.run_turn(
292
+ thread.thread_id,
293
+ prompt,
294
+ config={"sandbox_read_only": self._sandbox_read_only},
295
+ )
296
+ deadline = (
297
+ asyncio.get_running_loop().time() + self._turn_timeout_seconds
298
+ if self._turn_timeout_seconds is not None
299
+ else None
300
+ )
301
+ try:
302
+ while True:
303
+ chunk_task = asyncio.ensure_future(_anext_or_stop(codex_gen))
304
+ interrupt_task = asyncio.ensure_future(thread.interrupt_event.wait())
305
+ remaining = (
306
+ max(0.0, deadline - asyncio.get_running_loop().time())
307
+ if deadline is not None
308
+ else None
309
+ )
310
+ done, pending = await asyncio.wait(
311
+ {chunk_task, interrupt_task},
312
+ timeout=remaining,
313
+ return_when=asyncio.FIRST_COMPLETED,
314
+ )
315
+ if not done:
316
+ # Keep handle.stream's turn queue registered until transport
317
+ # close calls SDK MessageRouter.fail_all. Cancelling the
318
+ # asyncio.to_thread waiter first would strand queue.get in
319
+ # the executor and hang interpreter shutdown.
320
+ interrupt_task.cancel()
321
+ await self._client.close()
322
+ await asyncio.gather(chunk_task, interrupt_task, return_exceptions=True)
323
+ raise TimeoutError("codex turn timed out")
324
+ for task in pending:
325
+ task.cancel()
326
+ if interrupt_task in done:
327
+ chunk_task.cancel()
328
+ thread.interrupted = True
329
+ # AGUI 投射器对 RUN_INTERRUPTED 无兜底,必须显式发,否则 raise
330
+ yield self._event(
331
+ handle, EventType.RUN_INTERRUPTED, {"status": "interrupted"}
332
+ )
333
+ return
334
+ chunk = chunk_task.result()
335
+ if chunk is _STREAM_STOP:
336
+ return
337
+ event = self._codex_chunk_to_event(handle, thread, tracker, chunk)
338
+ if event is not None:
339
+ yield event
340
+ finally:
341
+ aclose = getattr(codex_gen, "aclose", None)
342
+ if callable(aclose):
343
+ try:
344
+ await aclose()
345
+ except Exception: # noqa: BLE001
346
+ pass
347
+
348
+ def _codex_chunk_to_event(
349
+ self,
350
+ handle: RunHandle,
351
+ thread: _CodexThread,
352
+ tracker: CodexPhaseTracker,
353
+ chunk: dict[str, Any],
354
+ ) -> Optional[RuntimeEvent]:
355
+ if not isinstance(chunk, dict):
356
+ return None
357
+ method = str(chunk.get("method") or chunk.get("type") or "")
358
+ params = chunk.get("params") or chunk
359
+
360
+ if method == "item/started":
361
+ tracker.observe_item(params)
362
+ return None
363
+ if method == "item/completed":
364
+ item = params.get("item") or params
365
+ if item.get("type") != "agentMessage":
366
+ tracker.forget_item(params)
367
+ return None
368
+ phase = tracker.runtime_phase_for_item(params)
369
+ tracker.forget_item(params)
370
+ text = str(item.get("text") or "")
371
+ return self._event(
372
+ handle,
373
+ EventType.TEXT_COMPLETED,
374
+ {"text": text},
375
+ phase=phase or "final_answer",
376
+ )
377
+ if "delta" in method or method == "item/agentMessage/delta":
378
+ phase = tracker.runtime_phase_for_delta(params)
379
+ delta = str(params.get("delta") or "")
380
+ if not delta:
381
+ return None
382
+ return self._event(
383
+ handle, EventType.TEXT_DELTA, {"text": delta}, phase=phase or "commentary"
384
+ )
385
+ if method == "item/autoApprovalReview/started":
386
+ review_id = str(params.get("review_id") or params.get("reviewId") or "")
387
+ if review_id:
388
+ thread.pending_approvals.add(review_id)
389
+ return None
390
+ if method == "item/autoApprovalReview/completed":
391
+ review_id = str(params.get("review_id") or params.get("reviewId") or "")
392
+ thread.pending_approvals.discard(review_id)
393
+ return None
394
+ if (
395
+ "approval" in method
396
+ or "requestPermission" in method
397
+ or "approval" in str(chunk.get("type") or "")
398
+ ):
399
+ call_id = str(
400
+ params.get("id") or params.get("call_id") or params.get("requestId") or ""
401
+ )
402
+ if call_id:
403
+ thread.pending_approvals.add(call_id)
404
+ return self._event(
405
+ handle,
406
+ EventType.APPROVAL_REQUESTED,
407
+ {"approval_id": call_id, "call_id": call_id, "kind": "tool", "detail": params},
408
+ )
409
+ return None
410
+
411
+ def _event(
412
+ self,
413
+ handle: RunHandle,
414
+ event_type: str,
415
+ payload: dict,
416
+ *,
417
+ phase: Optional[str] = None,
418
+ ) -> RuntimeEvent:
419
+ return RuntimeEvent.create(
420
+ event_type,
421
+ agent_id="codex",
422
+ user_id=str(handle.native_ref.get("user_id") or "user"),
423
+ session_id=handle.session_id,
424
+ invocation_id=handle.run_id,
425
+ seq_id=self._next_seq(),
426
+ phase=phase,
427
+ payload=payload,
428
+ )
429
+
430
+
431
+ _STREAM_STOP = object()
432
+
433
+
434
+ async def _anext_or_stop(gen: AsyncIterator[Any]) -> Any:
435
+ try:
436
+ return await gen.__anext__()
437
+ except StopAsyncIteration:
438
+ return _STREAM_STOP
439
+
440
+
441
+ def _resume_prompt(payload: Optional[ResumePayload]) -> Any:
442
+ if payload is None:
443
+ return ""
444
+ if isinstance(payload.data, str):
445
+ return payload.data
446
+ return json.dumps(payload.data, ensure_ascii=False, sort_keys=True)
447
+
448
+
449
+ __all__ = ["CodexRuntime"]
ksadk/common/aicp_env.py CHANGED
@@ -5,7 +5,6 @@ from __future__ import annotations
5
5
  import os
6
6
  import socket
7
7
 
8
-
9
8
  DEFAULT_AICP_REGION = "cn-beijing-6"
10
9
  DEFAULT_AICP_ENDPOINT = "aicp.api.ksyun.com"
11
10
  INTERNAL_AICP_ENDPOINT = "aicp.internal.api.ksyun.com"
ksadk/common/auth.py CHANGED
@@ -22,11 +22,11 @@ AWS Signature V4 签名认证
22
22
  response = requests.post(url, auth=auth.get_auth(), headers=headers)
23
23
  """
24
24
 
25
- import os
26
25
  import logging
26
+ import os
27
27
  from typing import Dict, Optional
28
28
 
29
- from requests_aws4auth import AWS4Auth
29
+ from requests_aws4auth import AWS4Auth # type: ignore[import-untyped]
30
30
 
31
31
  logger = logging.getLogger(__name__)
32
32
 
ksadk/common/constants.py CHANGED
@@ -3,9 +3,7 @@
3
3
  """
4
4
 
5
5
  # Serverless Endpoint (默认内网预发环境)
6
- DEFAULT_SERVERLESS_ENDPOINT = (
7
- "http://kmr.pre-online.inner.api.ksyun.com"
8
- )
6
+ DEFAULT_SERVERLESS_ENDPOINT = "http://kmr.pre-online.inner.api.ksyun.com"
9
7
 
10
8
  # KS3 Region 映射表
11
9
  # 用户输入的 region (如 cn-beijing-6) -> (外网endpoint, 内网endpoint, region_code)