agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.4__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 (509) hide show
  1. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
  2. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
  3. ksadk/_build_provenance.json +1 -1
  4. ksadk/api/client.py +105 -91
  5. ksadk/builders/code_builder.py +36 -9
  6. ksadk/builders/framework_requirements.py +2 -1
  7. ksadk/builders/ks3_uploader.py +36 -7
  8. ksadk/builders/managed_runtime_builder.py +1 -0
  9. ksadk/cli/__init__.py +32 -3
  10. ksadk/cli/cmd_managed_runtime.py +13 -1
  11. ksadk/cli/cmd_plugin.py +6 -1
  12. ksadk/cli/cmd_web.py +2 -5
  13. ksadk/cli/runtime_bootstrap.py +23 -1
  14. ksadk/codex/client.py +424 -96
  15. ksadk/codex/projection.py +24 -0
  16. ksadk/codex/runtime.py +56 -298
  17. ksadk/common/auth.py +16 -10
  18. ksadk/configs/env_registry.py +29 -1
  19. ksadk/conversations/message_projection.py +135 -14
  20. ksadk/conversations/projector.py +4 -6
  21. ksadk/conversations/runtime_invocation.py +5 -0
  22. ksadk/conversations/runtime_payloads.py +1 -0
  23. ksadk/conversations/runtime_preparation.py +30 -27
  24. ksadk/conversations/runtime_resume.py +50 -2
  25. ksadk/conversations/runtime_stream_events.py +5 -0
  26. ksadk/conversations/runtime_streaming.py +25 -7
  27. ksadk/deployment/env_forward.py +2 -2
  28. ksadk/deployment/providers/serverless.py +1 -1
  29. ksadk/events/adapters/_codex_validators.py +18 -7
  30. ksadk/events/adapters/langgraph.py +15 -1
  31. ksadk/events/canonical_store.py +3 -1
  32. ksadk/events/projections.py +1 -1
  33. ksadk/harness/config.py +2 -2
  34. ksadk/harness/runtime.py +27 -27
  35. ksadk/harness/tools.py +38 -13
  36. ksadk/interaction/provider.py +1 -0
  37. ksadk/interaction/providers/langgraph.py +1 -0
  38. ksadk/kernel/bootstrap.py +28 -4
  39. ksadk/kernel/ingress.py +15 -2
  40. ksadk/kernel/sqlite_store.py +27 -0
  41. ksadk/kernel/store.py +3 -0
  42. ksadk/kernel/worker.py +65 -10
  43. ksadk/knowledge_base/client.py +57 -27
  44. ksadk/mcp_runtime/__init__.py +12 -4
  45. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  46. ksadk/memory/adk/resilient_session_service.py +25 -17
  47. ksadk/memory/adk/short_term_memory.py +26 -9
  48. ksadk/memory/models.py +7 -4
  49. ksadk/memory/provider_resolver.py +3 -0
  50. ksadk/model_proxy/server.py +10 -5
  51. ksadk/plugins/__init__.py +4 -0
  52. ksadk/plugins/artifacts.py +275 -0
  53. ksadk/plugins/bridges/__init__.py +4 -2
  54. ksadk/plugins/bridges/codex.py +120 -13
  55. ksadk/plugins/bridges/dsh.py +340 -156
  56. ksadk/plugins/builtins.py +35 -36
  57. ksadk/plugins/bundle_security.py +28 -4
  58. ksadk/plugins/codex_manifest.py +983 -0
  59. ksadk/plugins/composition.py +8 -0
  60. ksadk/plugins/contracts.py +118 -0
  61. ksadk/plugins/delivery.py +153 -0
  62. ksadk/plugins/dsh_installation_digest.py +71 -0
  63. ksadk/plugins/dsh_toolchain.py +110 -21
  64. ksadk/plugins/ecosystem_probe.py +6 -6
  65. ksadk/plugins/host.py +102 -39
  66. ksadk/plugins/kernel_adapter.py +205 -0
  67. ksadk/plugins/providers/__init__.py +23 -0
  68. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  69. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  70. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  71. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  72. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  73. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  74. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  75. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  76. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  77. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  78. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  79. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  80. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  81. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  82. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  83. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  84. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  85. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  86. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  87. ksadk/plugins/providers/codex.py +335 -69
  88. ksadk/plugins/providers/codex_native.py +368 -0
  89. ksadk/plugins/providers/codex_turn.py +301 -0
  90. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  91. ksadk/plugins/providers/dsh_mcp.py +467 -0
  92. ksadk/plugins/providers/harness.py +118 -113
  93. ksadk/plugins/providers/mcp_projection.py +150 -0
  94. ksadk/plugins/providers/platform_resources.py +657 -0
  95. ksadk/plugins/resolver.py +8 -1
  96. ksadk/resource_runtime/__init__.py +4 -0
  97. ksadk/resource_runtime/broker.py +616 -0
  98. ksadk/resource_runtime/build_artifacts.py +165 -0
  99. ksadk/resource_runtime/contracts.py +138 -0
  100. ksadk/resource_runtime/discovery_receipts.py +100 -0
  101. ksadk/resource_runtime/discovery_skills.py +172 -0
  102. ksadk/resource_runtime/errors.py +6 -0
  103. ksadk/resource_runtime/ipc.py +142 -0
  104. ksadk/resource_runtime/kernel_approval.py +165 -0
  105. ksadk/resource_runtime/knowledge.py +114 -0
  106. ksadk/resource_runtime/langgraph.py +94 -0
  107. ksadk/resource_runtime/leases.py +191 -0
  108. ksadk/resource_runtime/managed_projection.py +186 -0
  109. ksadk/resource_runtime/mcp_server.py +138 -0
  110. ksadk/resource_runtime/memory_provider.py +318 -0
  111. ksadk/resource_runtime/memory_receipts.py +34 -0
  112. ksadk/resource_runtime/operation_ledger.py +211 -0
  113. ksadk/resource_runtime/plugin_config.py +48 -0
  114. ksadk/resource_runtime/policy_authorization.py +54 -0
  115. ksadk/resource_runtime/process.py +110 -0
  116. ksadk/resource_runtime/skill_artifacts.py +153 -0
  117. ksadk/resource_runtime/skill_runtime.py +42 -0
  118. ksadk/resource_runtime/skill_workspace.py +118 -0
  119. ksadk/resource_runtime/skills.py +215 -0
  120. ksadk/resource_runtime/snapshots.py +180 -0
  121. ksadk/resource_runtime/socket_server.py +103 -0
  122. ksadk/resource_runtime/supervisor.py +380 -0
  123. ksadk/resource_runtime/worker.py +504 -0
  124. ksadk/runners/_langgraph_runner_streams.py +74 -6
  125. ksadk/runners/adk_runner.py +149 -11
  126. ksadk/runners/base_runner.py +29 -1
  127. ksadk/runners/langgraph_runner.py +475 -145
  128. ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
  129. ksadk/runtime/adapter.py +2 -0
  130. ksadk/runtime/conversation_execution.py +92 -16
  131. ksadk/runtime/executor.py +78 -2
  132. ksadk/runtime/factory.py +29 -273
  133. ksadk/runtime/framework_adapters.py +23 -0
  134. ksadk/runtime/preprocessing.py +10 -2
  135. ksadk/runtime/runner_adapter.py +73 -14
  136. ksadk/runtime_context.py +40 -2
  137. ksadk/sandbox/backends/e2b.py +52 -11
  138. ksadk/sandbox/backends/local_process.py +9 -0
  139. ksadk/sandbox/base.py +2 -0
  140. ksadk/sandbox/e2b_connection.py +66 -0
  141. ksadk/scheduler/sqlite_store.py +18 -0
  142. ksadk/server/composition.py +2 -0
  143. ksadk/server/factory.py +5 -0
  144. ksadk/server/persistence_capability.py +516 -0
  145. ksadk/server/routes/control.py +210 -46
  146. ksadk/server/routes/dependencies.py +15 -0
  147. ksadk/server/routes/models.py +47 -4
  148. ksadk/server/routes/projection.py +252 -12
  149. ksadk/server/routes/sessions.py +284 -107
  150. ksadk/server/routes/streaming.py +43 -9
  151. ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  152. ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
  153. ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  154. ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  155. ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  156. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  157. ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
  158. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  159. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  160. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  161. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  162. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  163. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  164. ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  165. ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  166. ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  167. ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  168. ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  169. ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  170. ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  171. ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  172. ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  173. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  174. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  175. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  176. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  177. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  178. ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  179. ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
  180. ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  181. ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  182. ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  183. ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  184. ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  185. ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
  186. ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
  187. ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
  188. ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
  189. ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
  190. ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
  191. ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
  192. ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
  193. ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
  194. ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
  195. ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
  196. ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
  197. ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
  198. ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
  199. ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
  200. ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
  201. ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
  202. ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
  203. ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
  204. ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
  205. ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
  206. ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
  207. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  208. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  209. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  210. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  211. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  212. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  213. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  214. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  215. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  216. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  217. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  218. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  219. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  220. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  221. ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
  222. ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
  223. ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  224. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  225. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  226. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  227. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  228. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  229. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  230. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  231. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  232. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  233. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  234. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  235. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  236. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  237. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  238. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  239. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  240. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  241. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  242. ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  243. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  244. ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  245. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  246. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  247. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  248. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  249. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  250. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  251. ksadk/server/static/index.html +2 -2
  252. ksadk/session_context.py +66 -0
  253. ksadk/sessions/__init__.py +11 -21
  254. ksadk/sessions/_local_service_sync.py +263 -1
  255. ksadk/sessions/base.py +176 -0
  256. ksadk/sessions/errors.py +4 -0
  257. ksadk/sessions/in_memory.py +309 -19
  258. ksadk/sessions/local_service.py +83 -1
  259. ksadk/sessions/persistence.py +275 -0
  260. ksadk/sessions/postgres_service.py +358 -0
  261. ksadk/sessions/resilience.py +8 -0
  262. ksadk/sessions/resilient.py +362 -4
  263. ksadk/sessions/topology.py +135 -0
  264. ksadk/skills/models.py +26 -4
  265. ksadk/skills/package_store.py +186 -38
  266. ksadk/skills/runtime/agent.py +31 -6
  267. ksadk/skills/runtime/artifact_delivery.py +139 -0
  268. ksadk/skills/runtime/backends/e2b.py +98 -6
  269. ksadk/skills/runtime/backends/local.py +73 -8
  270. ksadk/skills/runtime/base.py +3 -0
  271. ksadk/skills/runtime/executor.py +2 -0
  272. ksadk/skills/runtime/loader.py +10 -2
  273. ksadk/skills/runtime/pinned.py +114 -0
  274. ksadk/skills/runtime/request.py +31 -0
  275. ksadk/skills/service_client.py +167 -28
  276. ksadk/studio/api.py +224 -42
  277. ksadk/studio/api_catalog_routes.py +18 -0
  278. ksadk/studio/api_plugin_routes.py +526 -95
  279. ksadk/studio/api_resource_connections.py +183 -0
  280. ksadk/studio/authoring_coordinator.py +19 -14
  281. ksadk/studio/builder.py +76 -0
  282. ksadk/studio/cloud.py +342 -104
  283. ksadk/studio/cloud_shared_web.py +565 -0
  284. ksadk/studio/codex_agent_service.py +128 -26
  285. ksadk/studio/codex_builder.py +241 -2
  286. ksadk/studio/codex_credentials.py +90 -0
  287. ksadk/studio/codex_manifest.py +31 -4
  288. ksadk/studio/codex_plugin_store.py +746 -0
  289. ksadk/studio/codex_provider_build.py +231 -0
  290. ksadk/studio/codex_run.py +184 -25
  291. ksadk/studio/compatibility_report.py +12 -1
  292. ksadk/studio/compiler.py +78 -14
  293. ksadk/studio/contracts.py +132 -6
  294. ksadk/studio/dsh_application.py +137 -0
  295. ksadk/studio/dsh_capability_service.py +1107 -0
  296. ksadk/studio/dsh_models.py +59 -0
  297. ksadk/studio/dsh_provider_registration.py +320 -13
  298. ksadk/studio/hosted_kernel.py +88 -13
  299. ksadk/studio/mcp_runtime.py +11 -3
  300. ksadk/studio/model_client.py +2 -2
  301. ksadk/studio/plugin_composition.py +190 -23
  302. ksadk/studio/plugin_kernel_adapter.py +12 -112
  303. ksadk/studio/plugin_runtime.py +224 -45
  304. ksadk/studio/resource_authority.py +637 -0
  305. ksadk/studio/resource_binding_validation.py +77 -0
  306. ksadk/studio/resource_build_admission.py +196 -0
  307. ksadk/studio/resource_build_materializer.py +149 -0
  308. ksadk/studio/resource_catalog.py +143 -2
  309. ksadk/studio/resource_connections.py +220 -0
  310. ksadk/studio/run_service.py +462 -52
  311. ksadk/studio/runtime_source.py +15 -7
  312. ksadk/studio/scheduler_assistant.py +317 -0
  313. ksadk/studio/scheduler_runtime.py +9 -0
  314. ksadk/studio/scheduler_service.py +3 -0
  315. ksadk/studio/service.py +490 -44
  316. ksadk/studio/shared_web.py +446 -62
  317. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  318. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  319. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  320. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  321. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  322. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  323. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  324. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  325. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  326. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  327. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  328. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  329. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  330. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  331. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  332. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  333. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  334. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  335. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  336. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  337. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  338. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  339. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  340. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  341. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  342. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  343. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  344. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  345. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  346. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  347. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  348. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  349. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  350. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  351. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  352. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  353. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  354. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  355. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  356. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  357. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  358. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  359. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  360. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  361. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  362. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  363. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  364. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  365. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  366. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  367. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  368. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  369. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  372. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  373. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  377. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  378. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  379. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  380. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  381. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  382. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  383. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  384. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  385. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  386. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  387. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  388. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  389. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  390. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  391. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  392. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  393. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  394. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  395. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  396. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  397. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  398. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  399. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  400. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  401. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  402. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  403. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  404. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  405. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  406. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  407. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  408. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  409. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  410. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  411. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  412. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  413. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  414. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  415. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  416. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  417. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  418. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  419. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  420. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  421. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  422. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  423. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  424. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  425. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  426. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  427. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  428. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  429. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  430. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  431. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  432. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  433. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  434. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  435. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  436. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  437. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  438. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  439. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  440. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  441. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  442. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  443. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  444. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  445. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  446. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  447. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  448. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  449. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  450. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  451. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  452. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  453. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  454. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  455. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  456. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  457. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  458. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  459. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  460. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  461. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  462. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  463. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  464. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  465. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  466. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  467. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  468. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  469. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  470. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  471. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  472. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  473. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  474. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  475. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  476. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  477. ksadk/studio/static/index.html +2 -2
  478. ksadk/version.py +1 -1
  479. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
  480. ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
  481. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
  482. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
  483. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
  484. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
  485. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
  486. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
  487. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
  488. ksadk/server/static/assets/index-B2k_urY8.js +0 -241
  489. ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
  490. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
  491. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
  492. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
  493. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
  494. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
  495. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
  496. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
  497. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
  498. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
  499. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
  500. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
  501. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
  502. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
  503. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  504. ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
  505. ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
  506. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  507. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  508. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  509. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
@@ -15,6 +15,7 @@ import logging
15
15
  import time
16
16
  from collections.abc import Mapping
17
17
  from contextlib import nullcontext
18
+ from dataclasses import replace
18
19
  from typing import TYPE_CHECKING, Any, AsyncIterator, Optional, cast
19
20
 
20
21
  from pydantic import JsonValue
@@ -65,6 +66,38 @@ async def _anext_or_stop(gen: AsyncIterator[Any]) -> Any:
65
66
  return _STREAM_STOP
66
67
 
67
68
 
69
+ async def _pump_stream_in_one_context(
70
+ gen: AsyncIterator[Any],
71
+ requests: asyncio.Queue[None],
72
+ results: asyncio.Queue[tuple[str, Any]],
73
+ ) -> None:
74
+ """Own one async generator in one Task without reading ahead."""
75
+ outcome: tuple[str, Any] = ("stop", _STREAM_STOP)
76
+ try:
77
+ while True:
78
+ await requests.get()
79
+ try:
80
+ chunk = await gen.__anext__()
81
+ except StopAsyncIteration:
82
+ break
83
+ await results.put(("chunk", chunk))
84
+ except asyncio.CancelledError:
85
+ raise
86
+ except BaseException as exc:
87
+ outcome = ("error", exc)
88
+ finally:
89
+ aclose = getattr(gen, "aclose", None)
90
+ if callable(aclose):
91
+ try:
92
+ await aclose()
93
+ except asyncio.CancelledError:
94
+ raise
95
+ except BaseException as exc:
96
+ if outcome[0] != "error":
97
+ outcome = ("error", exc)
98
+ await results.put(outcome)
99
+
100
+
68
101
  def _a2ui_surface_event(
69
102
  self: Any,
70
103
  handle: RunHandle,
@@ -192,14 +225,27 @@ class _RunnerStreamMappingMixin:
192
225
  """``_map_runner_stream`` / ``_chunk_to_event`` 的实现载体(纯移动自 runner_adapter)。"""
193
226
 
194
227
  async def _map_runner_stream(
195
- self, handle: RunHandle, runner_input: dict
228
+ self,
229
+ handle: RunHandle,
230
+ runner_input: dict,
231
+ *,
232
+ active_run: Optional[_ActiveRun] = None,
196
233
  ) -> AsyncIterator[RuntimeEvent]:
197
- run: Optional[_ActiveRun] = self._active_runs.get(handle.run_id) # type: ignore[attr-defined]
234
+ run: Optional[_ActiveRun] = active_run
235
+ if run is None:
236
+ run = self._active_runs.get(handle.run_id) # type: ignore[attr-defined]
198
237
  interrupt = run.interrupt_event if run is not None else None
199
238
  prepared_start = run.__dict__.get("_prepared_start") if run is not None else None
200
239
  invocation_context = (
201
240
  prepared_start.context if isinstance(prepared_start, PreparedRuntimeStart) else None
202
241
  )
242
+ if run is not None and run.__dict__.get("_tag_context") is not None:
243
+ tag_context = run.__dict__["_tag_context"]
244
+ invocation_context = (
245
+ replace(invocation_context, session=tag_context.session)
246
+ if invocation_context is not None
247
+ else tag_context
248
+ )
203
249
  scope = (
204
250
  platform_invocation_scope(invocation_context)
205
251
  if invocation_context is not None
@@ -209,6 +255,9 @@ class _RunnerStreamMappingMixin:
209
255
  accumulated_output = ""
210
256
  usage: dict[str, Any] = {}
211
257
  runner_gen: Optional[AsyncIterator[Any]] = None
258
+ pump_requests: asyncio.Queue[None] | None = None
259
+ pump_queue: asyncio.Queue[tuple[str, Any]] | None = None
260
+ pump_task: asyncio.Task[None] | None = None
212
261
  # span scope 经 runner_adapter 模块属性间接解析,保持既有 monkeypatch
213
262
  # patch 点(tests/agui/test_runtime_preprocessing.py)继续生效。
214
263
  from ksadk.runtime import runner_adapter as _runner_adapter_module
@@ -247,10 +296,26 @@ class _RunnerStreamMappingMixin:
247
296
  # 调用返回 coroutine,需 await 得到迭代器。
248
297
  stream_result = await stream_result
249
298
  runner_gen = cast(AsyncIterator[Any], stream_result)
299
+ if self._requires_stable_stream_context():
300
+ pump_requests = asyncio.Queue(maxsize=1)
301
+ pump_queue = asyncio.Queue()
302
+ pump_task = asyncio.create_task(
303
+ _pump_stream_in_one_context(
304
+ runner_gen, pump_requests, pump_queue
305
+ )
306
+ )
307
+ if run is not None:
308
+ run.chunk_task = pump_task
250
309
  while True:
251
310
  # 竞速:下一个 runner chunk vs cancel 中断事件。
252
- chunk_task = asyncio.ensure_future(_anext_or_stop(runner_gen))
253
- if run is not None:
311
+ if pump_requests is not None:
312
+ pump_requests.put_nowait(None)
313
+ chunk_task = asyncio.ensure_future(
314
+ pump_queue.get()
315
+ if pump_queue is not None
316
+ else _anext_or_stop(runner_gen)
317
+ )
318
+ if run is not None and pump_task is None:
254
319
  run.chunk_task = chunk_task
255
320
  wait_set = {chunk_task}
256
321
  interrupt_task = (
@@ -269,17 +334,23 @@ class _RunnerStreamMappingMixin:
269
334
  await asyncio.gather(*pending, return_exceptions=True)
270
335
  if interrupt_task is not None and interrupt_task in done:
271
336
  # cancel 中断:安全关闭 runner 流(同一 task)并停止。
272
- chunk_task.cancel()
273
- await asyncio.gather(chunk_task, return_exceptions=True)
337
+ owner_task = pump_task or chunk_task
338
+ owner_task.cancel()
339
+ await asyncio.gather(owner_task, return_exceptions=True)
274
340
  return
275
341
  try:
276
342
  chunk = chunk_task.result()
343
+ if pump_task is not None:
344
+ outcome, payload = cast(tuple[str, Any], chunk)
345
+ if outcome == "error":
346
+ raise payload
347
+ chunk = payload
277
348
  except asyncio.CancelledError:
278
349
  if interrupt is not None and interrupt.is_set():
279
350
  return
280
351
  raise
281
352
  finally:
282
- if run is not None:
353
+ if run is not None and pump_task is None:
283
354
  run.chunk_task = None
284
355
  if chunk is _STREAM_STOP:
285
356
  return
@@ -333,7 +404,11 @@ class _RunnerStreamMappingMixin:
333
404
  if accumulated_output:
334
405
  _set_conversation_output_attributes(span, accumulated_output)
335
406
  _set_conversation_usage_attributes(span, usage)
336
- if runner_gen is not None:
407
+ if pump_task is not None:
408
+ if not pump_task.done():
409
+ pump_task.cancel()
410
+ await asyncio.gather(pump_task, return_exceptions=True)
411
+ elif runner_gen is not None:
337
412
  aclose = getattr(runner_gen, "aclose", None)
338
413
  if callable(aclose):
339
414
  try:
@@ -341,6 +416,8 @@ class _RunnerStreamMappingMixin:
341
416
  except Exception: # noqa: BLE001
342
417
  pass
343
418
  if run is not None:
419
+ if pump_task is not None:
420
+ run.chunk_task = None
344
421
  run.cancellation_ack.set()
345
422
 
346
423
  def _chunk_to_event(
@@ -387,6 +464,24 @@ class _RunnerStreamMappingMixin:
387
464
  )
388
465
  ]
389
466
 
467
+ def tool_item_id(effective_call_id: str, item_kind: str) -> str:
468
+ components = (effective_call_id, item_kind)
469
+ if run is None:
470
+ return stable_item_id(framework, run_id, *components)
471
+ occurrences = run.__dict__.setdefault("_tool_item_occurrences", {})
472
+ occurrence_key = (scope_id, item_kind, effective_call_id)
473
+ occurrence = int(occurrences.get(occurrence_key, 0))
474
+ occurrences[occurrence_key] = occurrence + 1
475
+ if occurrence == 0:
476
+ return stable_item_id(framework, run_id, *components)
477
+ return stable_item_id(
478
+ framework,
479
+ run_id,
480
+ *components,
481
+ "occurrence",
482
+ occurrence,
483
+ )
484
+
390
485
  chunk_type = chunk.get("type")
391
486
 
392
487
  # ---- reasoning ----
@@ -449,7 +544,7 @@ class _RunnerStreamMappingMixin:
449
544
  )
450
545
  name = str(chunk.get("tool_name") or chunk.get("name") or "tool")
451
546
  effective_call_id = call_id or name
452
- item_id = stable_item_id(framework, run_id, effective_call_id, "tool_call")
547
+ item_id = tool_item_id(effective_call_id, "tool_call")
453
548
  part_id = "tool_call"
454
549
  tc_content = ToolCallContent(
455
550
  part_id=part_id,
@@ -496,7 +591,7 @@ class _RunnerStreamMappingMixin:
496
591
  )
497
592
  name = str(chunk.get("tool_name") or chunk.get("name") or "tool")
498
593
  effective_call_id = call_id or name
499
- item_id = stable_item_id(framework, run_id, effective_call_id, "tool_result")
594
+ item_id = tool_item_id(effective_call_id, "tool_result")
500
595
  part_id = "tool_result"
501
596
  result_data = chunk.get("tool_output", chunk.get("output"))
502
597
  # ToolGateway 审批可能出现在"本已终态"的 tool result 里;识别后转为
@@ -618,26 +713,55 @@ class _RunnerStreamMappingMixin:
618
713
  if isinstance(runtime_ref, dict):
619
714
  handle.native_ref.update(runtime_ref)
620
715
  item_id = stable_item_id(framework, run_id, "$run")
716
+ # Extract checkpoint capability from agentengine metadata so the
717
+ # canonical event carries backend/scope/next_node facts that the
718
+ # projection layer (projection.py) needs for the REST payload.
719
+ capability: dict[str, Any] = {}
720
+ for cap_key in (
721
+ # Capability / resume fields
722
+ "backend", "scope", "durable", "next_node",
723
+ "is_terminal", "is_resumable", "resume_status",
724
+ "resume_disabled_reason",
725
+ # Checkpoint display fields
726
+ "phase", "stage", "stage_name", "stage_key",
727
+ "stage_index", "total_stages", "summary",
728
+ "next_action", "status", "artifact_preview",
729
+ "tool_name", "receipt_key", "artifact_path",
730
+ ):
731
+ cap_val = agentengine.get(cap_key)
732
+ if cap_val is not None:
733
+ capability[cap_key] = cap_val
734
+ canonical_kwargs = self._canonical_kwargs( # type: ignore[attr-defined]
735
+ handle,
736
+ scope_id=scope_id,
737
+ item_id=item_id,
738
+ event_type="continuation.created",
739
+ part_id="continuation",
740
+ )
741
+ if capability:
742
+ base_source = canonical_kwargs["source"]
743
+ canonical_kwargs["source"] = SourceRef(
744
+ framework=base_source.framework,
745
+ protocol=base_source.protocol,
746
+ native_run_id=base_source.native_run_id,
747
+ metadata={**base_source.metadata, "capability": capability},
748
+ )
621
749
  ref_value = cast(
622
750
  JsonValue,
623
751
  framework_ref if isinstance(framework_ref, dict) else {},
624
752
  )
753
+ next_node_val = agentengine.get("next_node")
625
754
  return [
626
755
  ContinuationCreated(
627
- **self._canonical_kwargs( # type: ignore[attr-defined]
628
- handle,
629
- scope_id=scope_id,
630
- item_id=item_id,
631
- event_type="continuation.created",
632
- part_id="continuation",
633
- ),
756
+ **canonical_kwargs,
634
757
  continuation_id=checkpoint_id,
635
758
  continuation_kind="graph_checkpoint",
636
- resumable=True,
759
+ resumable=bool(agentengine.get("is_resumable", True)),
637
760
  ref={
638
761
  "framework": ckpt_framework,
639
762
  "framework_ref": ref_value,
640
763
  "resume_target": ref_value,
764
+ **({"next_node": str(next_node_val)} if next_node_val else {}),
641
765
  },
642
766
  )
643
767
  ]
ksadk/runtime/adapter.py CHANGED
@@ -114,6 +114,8 @@ class ResumePayload(BaseModel):
114
114
  call_id: Optional[str] = None
115
115
  """对应的 ``approval.requested`` / ``tool.call`` 的 id(如有)。"""
116
116
  data: Any = None
117
+ session_context: dict[str, Any] | None = None
118
+ """Platform-owned snapshot for a new resume invocation; never model input."""
117
119
 
118
120
 
119
121
  # ---------------------------------------------------------------------------
@@ -194,12 +194,21 @@ async def iter_runtime_conversation_events(
194
194
  for persisted in await pipeline.ingest(context_event):
195
195
  yield persisted
196
196
  async for event in executor.stream(handle):
197
- _validate_event_scope(event, request)
197
+ _validate_event_scope(
198
+ event,
199
+ request,
200
+ alternate_run_id=(
201
+ prepared.invocation_id if checkpoint_resume is not None else None
202
+ ),
203
+ )
198
204
  for persisted in await pipeline.ingest(event):
199
205
  await _project_runtime_run_status(
200
206
  persisted,
201
207
  session_id=prepared.session_id,
202
208
  author=agent_id,
209
+ invocation_id=(
210
+ prepared.invocation_id if checkpoint_resume is not None else None
211
+ ),
203
212
  run_mode=prepared.run_mode,
204
213
  run_trigger=prepared.run_trigger,
205
214
  session_service_provider=provider,
@@ -223,13 +232,16 @@ async def iter_runtime_conversation_events(
223
232
  raise RuntimeError("runtime stream ended without a terminal or interrupted event")
224
233
  except asyncio.CancelledError:
225
234
  cancel_result = await executor.cancel(handle)
235
+ cancel_run_id = (
236
+ prepared.invocation_id if checkpoint_resume is not None else handle.run_id
237
+ )
226
238
  cancelled_event = RunCanceled(
227
239
  schema_version=2,
228
- event_id=f"cancel:{handle.run_id}:{cancel_result.value}",
240
+ event_id=f"cancel:{cancel_run_id}:{cancel_result.value}",
229
241
  seq=0,
230
242
  timestamp=time.time(),
231
- run_id=handle.run_id,
232
- scope_id=handle.run_id,
243
+ run_id=cancel_run_id,
244
+ scope_id=cancel_run_id,
233
245
  source=SourceRef(
234
246
  framework="ksadk", metadata={"cancel_result": cancel_result.value}
235
247
  ),
@@ -241,6 +253,9 @@ async def iter_runtime_conversation_events(
241
253
  persisted_cancelled,
242
254
  session_id=prepared.session_id,
243
255
  author=agent_id,
256
+ invocation_id=(
257
+ prepared.invocation_id if checkpoint_resume is not None else None
258
+ ),
244
259
  run_mode=prepared.run_mode,
245
260
  run_trigger=prepared.run_trigger,
246
261
  session_service_provider=provider,
@@ -375,6 +390,7 @@ async def _project_runtime_run_status(
375
390
  *,
376
391
  session_id: str,
377
392
  author: str,
393
+ invocation_id: str | None = None,
378
394
  run_mode: str,
379
395
  run_trigger: str,
380
396
  session_service_provider: Callable[[], Any],
@@ -389,7 +405,7 @@ async def _project_runtime_run_status(
389
405
  session_id=session_id,
390
406
  author=author,
391
407
  status=status,
392
- invocation_id=event.run_id,
408
+ invocation_id=str(invocation_id or event.run_id),
393
409
  detail=str(detail) if detail else None,
394
410
  metadata={
395
411
  "runtime_event_id": event.event_id,
@@ -450,10 +466,7 @@ async def _resume_runtime_handle(
450
466
  def _resume_target(resume_input: Mapping[str, Any]) -> ResumeTarget:
451
467
  framework = str(resume_input.get("framework") or "").strip().lower()
452
468
  framework_ref = resume_input.get("framework_ref")
453
- raw_runtime_ref = framework_ref.get(framework) if isinstance(framework_ref, Mapping) else None
454
- runtime_ref: Mapping[str, Any] = (
455
- raw_runtime_ref if isinstance(raw_runtime_ref, Mapping) else {}
456
- )
469
+ runtime_ref = _runtime_ref_from_projection(framework, framework_ref)
457
470
  checkpoint_id = str(resume_input.get("checkpoint_id") or "").strip()
458
471
  run_id = str(resume_input.get("run_id") or "").strip()
459
472
  if framework == "langgraph":
@@ -470,8 +483,7 @@ def _persisted_resume_native_ref(resume_input: Mapping[str, Any]) -> dict[str, A
470
483
  checkpoint_id = str(resume_input.get("checkpoint_id") or "").strip()
471
484
  framework_ref = resume_input.get("framework_ref")
472
485
  normalized_ref = dict(framework_ref) if isinstance(framework_ref, Mapping) else {}
473
- runtime_ref = normalized_ref.get(framework)
474
- native_ref = dict(runtime_ref) if isinstance(runtime_ref, Mapping) else {}
486
+ native_ref = _runtime_ref_from_projection(framework, normalized_ref)
475
487
  native_ref["framework_ref"] = normalized_ref
476
488
  if checkpoint_id:
477
489
  native_ref.setdefault("checkpoint_id", checkpoint_id)
@@ -479,12 +491,45 @@ def _persisted_resume_native_ref(resume_input: Mapping[str, Any]) -> dict[str, A
479
491
  return native_ref
480
492
 
481
493
 
482
- def _validate_event_scope(event: RuntimeEvent, request: StartRequest) -> None:
494
+ def _runtime_ref_from_projection(framework: str, framework_ref: Any) -> dict[str, Any]:
495
+ """Flatten native refs wrapped by checkpoint REST/session projections."""
496
+
497
+ if not framework or not isinstance(framework_ref, Mapping):
498
+ return {}
499
+ raw = framework_ref.get(framework)
500
+ if not isinstance(raw, Mapping):
501
+ return {}
502
+ resolved = dict(raw)
503
+ current = raw
504
+ for _ in range(4):
505
+ nested_ref: Mapping[str, Any] | None = None
506
+ for key in ("framework_ref", "resume_target"):
507
+ container = current.get(key)
508
+ candidate = container.get(framework) if isinstance(container, Mapping) else None
509
+ if isinstance(candidate, Mapping):
510
+ nested_ref = candidate
511
+ break
512
+ if nested_ref is None:
513
+ break
514
+ resolved.update(nested_ref)
515
+ current = nested_ref
516
+ return resolved
517
+
518
+
519
+ def _validate_event_scope(
520
+ event: RuntimeEvent,
521
+ request: StartRequest,
522
+ *,
523
+ alternate_run_id: str | None = None,
524
+ ) -> None:
483
525
  expected_run_id = str(request.metadata["invocation_id"])
484
- if event.schema_version != 2 or event.run_id != expected_run_id:
526
+ expected_run_ids = {expected_run_id}
527
+ if alternate_run_id:
528
+ expected_run_ids.add(str(alternate_run_id))
529
+ if event.schema_version != 2 or event.run_id not in expected_run_ids:
485
530
  raise ValueError(
486
531
  "runtime event scope does not match request: "
487
- f"expected run_id={expected_run_id!r}, got {event.run_id!r}"
532
+ f"expected run_id in {sorted(expected_run_ids)!r}, got {event.run_id!r}"
488
533
  )
489
534
 
490
535
 
@@ -496,6 +541,14 @@ async def iter_runtime_conversation_semantic_events(
496
541
  reducer = StreamReducer()
497
542
  approval: dict[str, Any] | None = None
498
543
  execution_context: dict[str, str] = {}
544
+ # (scope_id, call_id) → tool_name:不同子运行可复用原生 call_id。
545
+ # (ToolResultContent 不带 name,前端靠 name 关联 call/result)。
546
+ _tool_name_by_call_id: dict[tuple[str, str], str] = {}
547
+ # 按 scope 和 call_id 跨 ItemStarted/ItemCompleted 去重,保留其他子运行的调用。
548
+ # 各 adapter 产生 ToolCallContent 的位置不一致:Codex 在 ItemStarted.initial 和
549
+ # ItemCompleted.snapshot 都带(需去重);LangGraph/ADK 的 ItemStarted.initial=None,
550
+ # ToolCallContent 只出现在 ItemCompleted.snapshot(需在 Completed 补发,不能跳过)。
551
+ _emitted_tool_call_ids: set[tuple[str, str]] = set()
499
552
  async for event in iter_runtime_conversation_events(
500
553
  **kwargs, _execution_context=execution_context
501
554
  ):
@@ -543,15 +596,34 @@ async def iter_runtime_conversation_semantic_events(
543
596
  elif isinstance(event, ItemStarted) and event.initial is not None:
544
597
  for part in event.initial.parts:
545
598
  if isinstance(part, ToolCallContent):
599
+ # 记录 call_id → name,供后续 tool_result 反查 name
600
+ # (ToolResultContent 不带 name,否则前端渲染成 "tool")。
601
+ if part.call_id and part.name:
602
+ _tool_name_by_call_id[(event.scope_id, part.call_id)] = part.name
603
+ if (event.scope_id, part.call_id) in _emitted_tool_call_ids:
604
+ continue
605
+ if part.call_id:
606
+ _emitted_tool_call_ids.add((event.scope_id, part.call_id))
546
607
  yield _tool_call_semantic(part)
547
608
  elif isinstance(event, ItemCompleted):
548
609
  for part in event.snapshot.parts:
549
610
  if isinstance(part, ToolCallContent):
611
+ # Codex 的 ItemStarted.initial 已发过 tool_call → 去重跳过;
612
+ # LangGraph/ADK 的 ItemStarted.initial=None 没发过 → 在这里补发,
613
+ # 否则 tool_call 事件会丢失、tool_result 也反查不到 name。
614
+ if part.call_id and part.name:
615
+ _tool_name_by_call_id[(event.scope_id, part.call_id)] = part.name
616
+ if (event.scope_id, part.call_id) in _emitted_tool_call_ids:
617
+ continue
618
+ if part.call_id:
619
+ _emitted_tool_call_ids.add((event.scope_id, part.call_id))
550
620
  yield _tool_call_semantic(part)
551
621
  elif isinstance(part, ToolResultContent):
622
+ # ToolResultContent 不带 name,用 call_id 反查 tool_call 的 name。
623
+ tool_name = _tool_name_by_call_id.get((event.scope_id, part.call_id), "")
552
624
  yield {
553
625
  "type": "tool_result",
554
- "name": "",
626
+ "name": tool_name,
555
627
  "output": part.result,
556
628
  "run_id": part.call_id,
557
629
  }
@@ -596,7 +668,11 @@ async def iter_runtime_conversation_semantic_events(
596
668
  else None
597
669
  )
598
670
  if isinstance(requested_agentengine, Mapping):
599
- completion_metadata["agentengine"] = dict(requested_agentengine)
671
+ completion_metadata["agentengine"] = {
672
+ key: value
673
+ for key, value in requested_agentengine.items()
674
+ if key != "session_context"
675
+ }
600
676
  completion_metadata["runtime"] = {
601
677
  "duration_ms": event.source.metadata.get("duration_ms"),
602
678
  "runtime_type": kwargs["launch_context"].runtime_type,
ksadk/runtime/executor.py CHANGED
@@ -8,6 +8,7 @@
8
8
  from __future__ import annotations
9
9
 
10
10
  import hashlib
11
+ import inspect
11
12
  import json
12
13
  from contextlib import suppress
13
14
  from dataclasses import dataclass
@@ -75,6 +76,7 @@ class RuntimeExecutor:
75
76
  self._registry = registry
76
77
  self._kernel_store = kernel_store
77
78
  self._runs: dict[_HandleKey, _OwnedRun] = {}
79
+ self._capability_adapters: dict[int, tuple[RuntimeLaunchContext, RuntimeAdapter]] = {}
78
80
 
79
81
  def create_adapter(self, context: RuntimeLaunchContext) -> RuntimeAdapter:
80
82
  """从本 executor 的 registry 创建一个 adapter。
@@ -225,6 +227,18 @@ class RuntimeExecutor:
225
227
  first_error = exc
226
228
  finally:
227
229
  self._runs.pop(key, None)
230
+ for key, (_context, adapter) in list(self._capability_adapters.items()):
231
+ runner = getattr(adapter, "_runner", None)
232
+ close_runner = getattr(runner, "close", None)
233
+ if callable(close_runner):
234
+ try:
235
+ result = close_runner()
236
+ if inspect.isawaitable(result):
237
+ await result
238
+ except BaseException as exc:
239
+ if first_error is None:
240
+ first_error = exc
241
+ self._capability_adapters.pop(key, None)
228
242
  if first_error is not None:
229
243
  raise first_error
230
244
 
@@ -295,7 +309,7 @@ class RuntimeExecutor:
295
309
  def native_capabilities(self, context: RuntimeLaunchContext) -> dict[str, object]:
296
310
  """Read the capability declaration from the registered Runtime implementation."""
297
311
 
298
- adapter = self._registry.create(context)
312
+ adapter = self.capability_adapter(context)
299
313
  return dict(adapter.runtime.native_capabilities())
300
314
 
301
315
  def capability_matrix(self, context: RuntimeLaunchContext) -> dict[str, object]:
@@ -306,9 +320,25 @@ class RuntimeExecutor:
306
320
  modes can be exposed only when the selected runtime declares support.
307
321
  """
308
322
 
309
- adapter = self._registry.create(context)
323
+ adapter = self.capability_adapter(context)
310
324
  return adapter.capabilities().model_dump(mode="json")
311
325
 
326
+ def capability_adapter(self, context: RuntimeLaunchContext) -> RuntimeAdapter:
327
+ """Return one stable, non-executing adapter for capability discovery."""
328
+
329
+ key = id(context)
330
+ cached = self._capability_adapters.get(key)
331
+ if cached is None or cached[0] is not context:
332
+ adapter = self._registry.create(context)
333
+ self._capability_adapters[key] = (context, adapter)
334
+ return adapter
335
+ return cached[1]
336
+
337
+ def capability_subject(self, context: RuntimeLaunchContext) -> object | None:
338
+ """Expose the runner whose async capability hooks feed persistence gating."""
339
+
340
+ return getattr(self.capability_adapter(context), "_runner", None)
341
+
312
342
  def registered_runtime_types(self) -> list[str]:
313
343
  """Expose Registry membership without leaking or duplicating the Registry."""
314
344
 
@@ -375,6 +405,51 @@ def _normalize_runtime_type(runtime_type: str) -> str:
375
405
  return runtime_type.strip().lower()
376
406
 
377
407
 
408
+ def project_legacy_runtime_capabilities(
409
+ native: dict[str, object],
410
+ matrix: dict[str, object],
411
+ ) -> dict[str, object]:
412
+ """Fill the legacy PascalCase UI contract from the typed v1 matrix."""
413
+
414
+ projected = dict(native)
415
+
416
+ def capability(name: str) -> dict[str, object]:
417
+ value = matrix.get(name)
418
+ return dict(value) if isinstance(value, dict) else {}
419
+
420
+ cancel = capability("cancel")
421
+ checkpoint = capability("checkpoint")
422
+ resume = capability("resume")
423
+ projected.setdefault(
424
+ "CancelRun",
425
+ {
426
+ "Supported": cancel.get("supported") is True,
427
+ "Reason": str(cancel.get("reason") or ""),
428
+ },
429
+ )
430
+ projected.setdefault(
431
+ "Checkpoint",
432
+ {
433
+ "Supported": checkpoint.get("supported") is True,
434
+ "Backend": "native" if checkpoint.get("supported") is True else "none",
435
+ "Scope": "runtime",
436
+ "Durable": capability("durable_restore").get("supported") is True,
437
+ "SharedAcrossPods": False,
438
+ "ResumeMode": str(resume.get("mode") or "none"),
439
+ "Reason": str(checkpoint.get("reason") or ""),
440
+ },
441
+ )
442
+ projected.setdefault(
443
+ "ResumeRun",
444
+ {
445
+ "Supported": resume.get("supported") is True,
446
+ "ResumeMode": str(resume.get("mode") or "none"),
447
+ "Reason": str(resume.get("reason") or ""),
448
+ },
449
+ )
450
+ return projected
451
+
452
+
378
453
  def _handle_key(handle: RunHandle) -> _HandleKey:
379
454
  return (
380
455
  _normalize_runtime_type(handle.runtime_type),
@@ -389,4 +464,5 @@ __all__ = [
389
464
  "DurableRun",
390
465
  "RunNotFoundError",
391
466
  "handle_digest",
467
+ "project_legacy_runtime_capabilities",
392
468
  ]