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
@@ -14,6 +14,8 @@ from pathlib import Path
14
14
  from typing import Any
15
15
  from uuid import uuid4
16
16
 
17
+ from jsonschema import Draft202012Validator
18
+
17
19
  from ksadk.agui.a2ui_projection import project_a2ui_operations
18
20
  from ksadk.conversations.projector import (
19
21
  project_conversation_item,
@@ -60,6 +62,7 @@ from ksadk.runtime import (
60
62
  RuntimeLaunchContext,
61
63
  StartRequest,
62
64
  )
65
+ from ksadk.runtime.executor import RuntimeStartPreparation
63
66
  from ksadk.sessions.base import BaseSessionService
64
67
  from ksadk.sessions.local_service import LocalSessionService
65
68
  from ksadk.studio.contracts import RunEvent, RunRecord, RunStatus, Usage
@@ -68,6 +71,7 @@ from ksadk.studio.event_store import RunEventStore
68
71
  from ksadk.studio.workspace import Workspace
69
72
 
70
73
  _CANCEL_TIMEOUT_SECONDS = 2.0
74
+ _INTERACTION_SUBMIT_TIMEOUT_SECONDS = 10.0
71
75
 
72
76
 
73
77
  logger = logging.getLogger(__name__)
@@ -107,13 +111,16 @@ class StudioRunService:
107
111
  )
108
112
  self.runtime_events = runtime_events or RuntimeEventStore(self.session_service)
109
113
  self.plugin_runtime = plugin_runtime
114
+ self.schedule_assistant: Any | None = None
110
115
  self._active_handles: dict[str, Any] = {}
116
+ self._active_sessions: set[tuple[str, str]] = set()
111
117
  self._cancel_flags: dict[str, bool] = {}
112
118
  self._control_queues: dict[
113
119
  str,
114
120
  asyncio.Queue[tuple[str, ResumePayload | None, asyncio.Future[None] | None]],
115
121
  ] = {}
116
122
  self._waiting_modes: dict[str, str] = {}
123
+ self._submitted_interactions: dict[str, set[str]] = {}
117
124
  # Interaction resolution appends to one run-level event file. Serialise
118
125
  # every decision for that run, not only identical interaction ids, so
119
126
  # two concurrently visible cards cannot overwrite each other's receipt.
@@ -142,6 +149,7 @@ class StudioRunService:
142
149
  "run.interrupted",
143
150
  {"reason": "local_studio_restarted", "recoverable": False},
144
151
  )
152
+ self._expire_unresolved_interactions(record)
145
153
 
146
154
  async def events(self, run_id: str, *, after: int = 0) -> list[RunEvent]:
147
155
  """Read the durable Studio event timeline for API/SSE replay."""
@@ -155,6 +163,38 @@ class StudioRunService:
155
163
  runtime_input: Any = None,
156
164
  session_id: str | None = None,
157
165
  on_event: Callable[[RunEvent], None] | None = None,
166
+ ) -> RunRecord:
167
+ session = session_id or f"ses_{uuid4().hex}"
168
+ key = (spec.agent_id, session)
169
+ # Claim before the first await, including preparation and plugin runs.
170
+ # A second turn must never attach another adapter to the live thread.
171
+ if key in self._active_sessions:
172
+ raise StudioError(
173
+ "SESSION_RUN_ACTIVE",
174
+ "上一轮仍在运行或等待回答,请先完成回答或停止运行。",
175
+ status_code=409,
176
+ details={"sessionId": session},
177
+ )
178
+ self._active_sessions.add(key)
179
+ try:
180
+ return await self._run_owned(
181
+ spec,
182
+ user_input,
183
+ runtime_input=runtime_input,
184
+ session_id=session,
185
+ on_event=on_event,
186
+ )
187
+ finally:
188
+ self._active_sessions.discard(key)
189
+
190
+ async def _run_owned(
191
+ self,
192
+ spec: StudioRunSpec,
193
+ user_input: str,
194
+ *,
195
+ runtime_input: Any,
196
+ session_id: str,
197
+ on_event: Callable[[RunEvent], None] | None,
158
198
  ) -> RunRecord:
159
199
  run_id = f"run_{uuid4().hex}"
160
200
  session = session_id or f"ses_{uuid4().hex}"
@@ -193,7 +233,27 @@ class StudioRunService:
193
233
  if on_event is not None:
194
234
  on_event(created)
195
235
 
196
- kernel_runtime = self._kernel_runtime_for_spec(spec)
236
+ if self.schedule_assistant is not None and (
237
+ self.schedule_assistant.matches(user_input)
238
+ or self.schedule_assistant.matches_followup(spec.agent_id, session, user_input)
239
+ ):
240
+ handled = await self._schedule_run(record, user_input, on_event=on_event)
241
+ if handled is not None:
242
+ return handled
243
+
244
+ provider_runtime_adapter = (
245
+ spec.plugin_bundle_root is not None
246
+ and (
247
+ runtime_type == "codex"
248
+ or bool(spec.request_config.get("provider_runtime_adapter"))
249
+ )
250
+ )
251
+ # A process-global Codex Kernel can share Agent/cwd with this Build
252
+ # while owning a legacy direct factory. New Builds must retain their
253
+ # exact Provider activation, including when that global Kernel exists.
254
+ kernel_runtime = (
255
+ None if provider_runtime_adapter else self._kernel_runtime_for_spec(spec)
256
+ )
197
257
  if kernel_runtime is not None:
198
258
  return await self._kernel_run(
199
259
  spec,
@@ -202,7 +262,7 @@ class StudioRunService:
202
262
  on_event=on_event,
203
263
  kernel_runtime=kernel_runtime,
204
264
  )
205
- if spec.plugin_bundle_root is not None:
265
+ if spec.plugin_bundle_root is not None and not provider_runtime_adapter:
206
266
  return await self._plugin_run(
207
267
  spec,
208
268
  user_input,
@@ -269,10 +329,29 @@ class StudioRunService:
269
329
  metadata={
270
330
  "invocation_id": run_id,
271
331
  CONVERSATION_PREPROCESSING_METADATA_KEY: conversation_request,
272
- **self._native_session_metadata(spec.agent_id, session, runtime_type),
332
+ **self._native_session_metadata(
333
+ spec.agent_id,
334
+ session,
335
+ str(
336
+ spec.request_config.get("provider_runtime_type")
337
+ or runtime_type
338
+ ),
339
+ spec.build_id,
340
+ ),
273
341
  },
274
342
  )
275
- handle = await self.executor.start(spec.launch_context, request)
343
+ preparation = None
344
+ if provider_runtime_adapter:
345
+ if self.plugin_runtime is None:
346
+ raise StudioError(
347
+ "PLUGIN_RUNTIME_UNAVAILABLE", "Codex Provider Runtime 不可用",
348
+ status_code=503,
349
+ )
350
+ adapter = self.plugin_runtime.kernel_adapter_provider(spec)()
351
+ preparation = RuntimeStartPreparation(context=spec.launch_context, adapter=adapter)
352
+ handle = await self.executor.start(
353
+ spec.launch_context, request, preparation=preparation,
354
+ )
276
355
  record.runtime_handle = handle.model_dump(mode="json")
277
356
  self.event_store.save(record)
278
357
  self._active_handles[run_id] = handle
@@ -280,6 +359,27 @@ class StudioRunService:
280
359
  terminal_seen = False
281
360
  should_resume = False
282
361
  async for event in self.executor.stream(handle):
362
+ if (
363
+ isinstance(event, RunInterrupted)
364
+ and event.interaction_id
365
+ and record.status == RunStatus.WAITING_INPUT
366
+ and event.source.framework == "codex"
367
+ ):
368
+ # Codex emits this companion event immediately after a
369
+ # live JSON-RPC approval request. The native turn stays
370
+ # attached and must be released through submit; trying
371
+ # to resume it deadlocks that request and later breaks
372
+ # the app-server pipe.
373
+ self._waiting_modes[run_id] = "live"
374
+ continue
375
+ if isinstance(event, InteractionResolved) and event.source.framework == "codex":
376
+ submitted = self._submitted_interactions.get(run_id, set())
377
+ provider_call_id = str(getattr(event.response, "call_id", None) or "")
378
+ if event.interaction_id in submitted or provider_call_id in submitted:
379
+ # submit_interaction atomically persists the public
380
+ # terminal fact and receipt. Ignore the provider's
381
+ # echo so replay never shows the approval twice.
382
+ continue
283
383
  await persist(event)
284
384
  if self._cancel_flags.get(run_id):
285
385
  raise asyncio.CancelledError()
@@ -288,9 +388,7 @@ class StudioRunService:
288
388
  elif (
289
389
  isinstance(event, ItemUpdated)
290
390
  and event.item_kind == "message"
291
- and item_phases.get(
292
- (event.scope_id, event.item_id), "final_answer"
293
- )
391
+ and item_phases.get((event.scope_id, event.item_id), "final_answer")
294
392
  == "final_answer"
295
393
  ):
296
394
  text = event.update.text if isinstance(event.update, TextContent) else ""
@@ -304,9 +402,7 @@ class StudioRunService:
304
402
  elif (
305
403
  isinstance(event, ItemCompleted)
306
404
  and event.item_kind == "message"
307
- and item_phases.get(
308
- (event.scope_id, event.item_id), "final_answer"
309
- )
405
+ and item_phases.get((event.scope_id, event.item_id), "final_answer")
310
406
  == "final_answer"
311
407
  ):
312
408
  completed_text_by_item[(event.scope_id, event.item_id)] = "".join(
@@ -492,7 +588,9 @@ class StudioRunService:
492
588
  self._cancel_flags.pop(run_id, None)
493
589
  self._control_queues.pop(run_id, None)
494
590
  self._waiting_modes.pop(run_id, None)
591
+ self._submitted_interactions.pop(run_id, None)
495
592
  record.completed_at = datetime.now(timezone.utc)
593
+ self._expire_unresolved_interactions(record, on_event=on_event)
496
594
  if runtime_duration_ms is not None:
497
595
  record.duration_ms = runtime_duration_ms
498
596
  record.duration_source = "runtime"
@@ -503,6 +601,179 @@ class StudioRunService:
503
601
  await self._sync_trace(record)
504
602
  return record
505
603
 
604
+ async def _schedule_run(
605
+ self,
606
+ record: RunRecord,
607
+ user_input: str,
608
+ *,
609
+ on_event: Callable[[RunEvent], None] | None,
610
+ ) -> RunRecord | None:
611
+ """Persist real host tool receipts on the canonical conversation stream."""
612
+ started = time.monotonic()
613
+
614
+ def envelope(kind: str) -> dict[str, Any]:
615
+ result = _plugin_event_envelope(record, kind)
616
+ result["source"] = SourceRef(
617
+ framework="ksadk",
618
+ metadata={"runtime": "studio-scheduler", "agent_id": record.agent_id},
619
+ )
620
+ return result
621
+
622
+ async def publish(event: RuntimeEvent) -> None:
623
+ persisted = await self.runtime_events.append_one(record.session_id, event)
624
+ kind, data = project_runtime_event(
625
+ persisted, session_id=record.session_id, public_run_id=record.id
626
+ )
627
+ stored = self.event_store.append(record.id, kind, data)
628
+ if on_event is not None:
629
+ on_event(stored)
630
+
631
+ call_id = None
632
+ try:
633
+ intent = await self.schedule_assistant.plan(
634
+ record.agent_id,
635
+ user_input,
636
+ record.session_id,
637
+ build_id=record.build_id,
638
+ model_name=record.model,
639
+ )
640
+ if self._cancel_flags.get(record.id):
641
+ raise asyncio.CancelledError()
642
+ if intent.action == "ignore":
643
+ return None
644
+ record.status = RunStatus.RUNNING
645
+ record.started_at = datetime.now(timezone.utc)
646
+ record.runtime_handle = {"provider": "studio-scheduler"}
647
+ self.event_store.save(record)
648
+ await publish(RunStarted(**envelope("run.started"), status="running"))
649
+ call_id = f"{record.id}:schedule"
650
+ arguments = intent.model_dump(mode="json", exclude_none=True)
651
+ await publish(
652
+ ItemStarted(
653
+ **envelope("tool.started"),
654
+ item_id=call_id,
655
+ item_kind="tool_call",
656
+ initial=ContentSnapshot(
657
+ parts=(
658
+ ToolCallContent(
659
+ part_id=f"{call_id}:call",
660
+ call_id=call_id,
661
+ name="studio_schedule",
662
+ arguments=arguments,
663
+ ),
664
+ )
665
+ ),
666
+ )
667
+ )
668
+ result = await self.schedule_assistant.execute(
669
+ record.agent_id, record.session_id, intent
670
+ )
671
+ await publish(
672
+ ItemCompleted(
673
+ **envelope("tool.completed"),
674
+ item_id=call_id,
675
+ item_kind="tool_call",
676
+ snapshot=ContentSnapshot(
677
+ parts=(
678
+ ToolResultContent(
679
+ part_id=f"{call_id}:result", call_id=call_id, result=result
680
+ ),
681
+ )
682
+ ),
683
+ )
684
+ )
685
+ output = result["message"]
686
+ item_id, part_id = f"{record.id}:assistant", f"{record.id}:text"
687
+ await publish(
688
+ ItemStarted(
689
+ **envelope("item.started"),
690
+ item_id=item_id,
691
+ item_kind="message",
692
+ phase="final_answer",
693
+ )
694
+ )
695
+ await publish(
696
+ ItemUpdated(
697
+ **envelope("item.updated"),
698
+ item_id=item_id,
699
+ item_kind="message",
700
+ op="append",
701
+ update=TextContent(part_id=part_id, text=output),
702
+ )
703
+ )
704
+ await publish(
705
+ ItemCompleted(
706
+ **envelope("item.completed"),
707
+ item_id=item_id,
708
+ item_kind="message",
709
+ snapshot=ContentSnapshot(parts=(TextContent(part_id=part_id, text=output),)),
710
+ )
711
+ )
712
+ if intent._usage is not None and intent._usage.reported:
713
+ record.usage = intent._usage.model_copy(update={"source": "studio-scheduler"})
714
+ await publish(
715
+ UsageReported(
716
+ **envelope("usage.reported"),
717
+ input_tokens=record.usage.input_tokens,
718
+ output_tokens=record.usage.output_tokens,
719
+ total_tokens=record.usage.total_tokens,
720
+ cached_tokens=record.usage.cached_input_tokens,
721
+ reasoning_tokens=record.usage.reasoning_output_tokens,
722
+ )
723
+ )
724
+ await publish(
725
+ RunCompleted(
726
+ **envelope("run.completed"),
727
+ status="completed",
728
+ output_refs=(OutputRef(scope_id=record.id, item_id=item_id, part_id=part_id),),
729
+ )
730
+ )
731
+ record.output = output
732
+ record.status = RunStatus.COMPLETED
733
+ except asyncio.CancelledError:
734
+ record.status = RunStatus.CANCELLED
735
+ record.completed_at = datetime.now(timezone.utc)
736
+ self._cancel_flags.pop(record.id, None)
737
+ await publish(
738
+ RunCanceled(**envelope("run.canceled"), status="canceled", reason="cancelled")
739
+ )
740
+ self.event_store.save(record)
741
+ raise
742
+ except Exception as error:
743
+ code = str(getattr(error, "code", "SCHEDULE_REQUEST_FAILED"))
744
+ record.status = RunStatus.FAILED
745
+ record.error = {"code": code, "message": str(error)}
746
+ if call_id is not None:
747
+ await publish(
748
+ ItemFailed(
749
+ **envelope("tool.failed"),
750
+ item_id=call_id,
751
+ item_kind="tool_call",
752
+ error=ErrorInfo(
753
+ code=code,
754
+ message=str(error),
755
+ source="studio-scheduler",
756
+ scope_id=record.id,
757
+ ),
758
+ )
759
+ )
760
+ await publish(
761
+ RunFailed(
762
+ **envelope("run.failed"),
763
+ status="failed",
764
+ error=ErrorInfo(
765
+ code=code, message=str(error), source="studio-scheduler", scope_id=record.id
766
+ ),
767
+ )
768
+ )
769
+ record.completed_at = datetime.now(timezone.utc)
770
+ record.duration_ms = int((time.monotonic() - started) * 1000)
771
+ record.duration_source = "studio"
772
+ self._cancel_flags.pop(record.id, None)
773
+ self.event_store.save(record)
774
+ await self._sync_trace(record)
775
+ return record
776
+
506
777
  async def _sync_trace(self, record: RunRecord) -> None:
507
778
  self.event_store.trace_store.sync(record, await self.events(record.id))
508
779
 
@@ -672,9 +943,7 @@ class StudioRunService:
672
943
  ) -> list[RuntimeEvent]:
673
944
  item_id = f"{record.id}:assistant"
674
945
  part_id = f"{record.id}:text"
675
- snapshot = ContentSnapshot(
676
- parts=(TextContent(part_id=part_id, text=output_text),)
677
- )
946
+ snapshot = ContentSnapshot(parts=(TextContent(part_id=part_id, text=output_text),))
678
947
  events: list[RuntimeEvent] = [
679
948
  RunStarted(
680
949
  **_plugin_event_envelope(record, "run.started"),
@@ -725,10 +994,7 @@ class StudioRunService:
725
994
  ),
726
995
  )
727
996
  )
728
- return [
729
- await self.runtime_events.append_one(record.session_id, event)
730
- for event in events
731
- ]
997
+ return [await self.runtime_events.append_one(record.session_id, event) for event in events]
732
998
 
733
999
  async def _kernel_run(
734
1000
  self,
@@ -764,9 +1030,7 @@ class StudioRunService:
764
1030
  session_id=record.session_id,
765
1031
  operations=("enqueue",),
766
1032
  )
767
- idempotency_key = str(
768
- (spec.request_config or {}).get("idempotency_key") or record.id
769
- )
1033
+ idempotency_key = str((spec.request_config or {}).get("idempotency_key") or record.id)
770
1034
  command = _kernel_ingress.map_studio_request(
771
1035
  session_id=record.session_id,
772
1036
  idempotency_key=idempotency_key,
@@ -774,9 +1038,7 @@ class StudioRunService:
774
1038
  run_id=record.id,
775
1039
  trusted=trusted,
776
1040
  )
777
- receipt = await _kernel_ingress.submit_command(
778
- command, permit=trusted.permit
779
- )
1041
+ receipt = await _kernel_ingress.submit_command(command, permit=trusted.permit)
780
1042
  if receipt.status not in ("accepted", "duplicate"):
781
1043
  record.status = RunStatus.FAILED
782
1044
  record.error = {
@@ -859,17 +1121,13 @@ class StudioRunService:
859
1121
  if active_project != build_project:
860
1122
  return None
861
1123
  defaults = getattr(runtime.config, "start_request_defaults", {}) or {}
862
- bound_agent_id = str(
863
- defaults.get("agent_id") or runtime.config.agent_instance_id
864
- ).strip()
1124
+ bound_agent_id = str(defaults.get("agent_id") or runtime.config.agent_instance_id).strip()
865
1125
  if bound_agent_id != spec.agent_id:
866
1126
  return None
867
1127
  declared_instance = str(
868
1128
  (spec.launch_context.config or {}).get("agent_instance_id") or ""
869
1129
  ).strip()
870
- if declared_instance and declared_instance != str(
871
- runtime.config.agent_instance_id
872
- ):
1130
+ if declared_instance and declared_instance != str(runtime.config.agent_instance_id):
873
1131
  return None
874
1132
  return runtime
875
1133
 
@@ -998,11 +1256,8 @@ class StudioRunService:
998
1256
  "同一幂等键不能提交不同内容",
999
1257
  status_code=409,
1000
1258
  )
1001
- record = self.event_store.get(run_id)
1002
- if record.status == RunStatus.WAITING_INPUT:
1003
- record.status = RunStatus.RUNNING
1004
- self.event_store.save(record)
1005
- self._waiting_modes.pop(run_id, None)
1259
+ # A receipt replay is read-only. The run may already be waiting
1260
+ # for a different interaction; never clear that newer wait state.
1006
1261
  return dict(prior.data.get("receipt") or {})
1007
1262
 
1008
1263
  interaction = next(
@@ -1039,10 +1294,51 @@ class StudioRunService:
1039
1294
  status_code=409,
1040
1295
  )
1041
1296
  kind = str(interaction.data.get("kind") or "form")
1042
- payload_data = {"decision": name, **data}
1297
+ if kind != "approval" and name not in {"cancel", "skip"}:
1298
+ schema = interaction.data.get("inputSchema") or {}
1299
+ errors = list(Draft202012Validator(schema).iter_errors(data))
1300
+ if errors:
1301
+ raise StudioError(
1302
+ "INTERACTION_RESPONSE_INVALID",
1303
+ "请填写必填问题后再提交。",
1304
+ status_code=422,
1305
+ )
1306
+ provider_call_id = str(
1307
+ interaction.data.get("callId") or interaction.data.get("call_id") or ""
1308
+ )
1309
+ if kind == "approval" and not provider_call_id:
1310
+ approval_request = next(
1311
+ (
1312
+ event
1313
+ for event in reversed(events)
1314
+ if event.type == "approval.requested"
1315
+ and str(event.data.get("approvalId") or event.data.get("interactionId") or "")
1316
+ == interaction_id
1317
+ ),
1318
+ None,
1319
+ )
1320
+ if approval_request is not None:
1321
+ provider_call_id = str(
1322
+ approval_request.data.get("callId")
1323
+ or approval_request.data.get("call_id")
1324
+ or ""
1325
+ )
1326
+ provider_call_id = provider_call_id or interaction_id
1327
+ submitted = self._submitted_interactions.setdefault(run_id, set())
1328
+ submitted.update({interaction_id, provider_call_id})
1329
+ decision = str(data.get("decision") or name)
1330
+ if kind == "approval" and record.runtime_type == "codex":
1331
+ # The shared Web action is named `reject`; Codex app-server calls
1332
+ # the same decision `deny`/`decline`. Do not let a UI alias fall
1333
+ # through as an unsupported native approval decision.
1334
+ decision = {
1335
+ "reject": "deny",
1336
+ "rejected": "deny",
1337
+ }.get(decision.lower(), decision)
1338
+ payload_data = {**data, "decision": decision}
1043
1339
  payload = ResumePayload(
1044
1340
  kind="approval_decision" if kind == "approval" else "hitl_answer",
1045
- call_id=interaction_id,
1341
+ call_id=provider_call_id,
1046
1342
  data=payload_data,
1047
1343
  )
1048
1344
  mode = self._waiting_modes.get(run_id)
@@ -1051,8 +1347,19 @@ class StudioRunService:
1051
1347
  if handle is None or not self.executor.is_attached(handle):
1052
1348
  raise StudioError("INTERACTION_EXPIRED", "运行时交互已失效", status_code=409)
1053
1349
  try:
1054
- await self.executor.submit(handle, payload)
1350
+ await asyncio.wait_for(
1351
+ self.executor.submit(handle, payload),
1352
+ timeout=_INTERACTION_SUBMIT_TIMEOUT_SECONDS,
1353
+ )
1354
+ except TimeoutError as exc:
1355
+ submitted.difference_update({interaction_id, provider_call_id})
1356
+ raise StudioError(
1357
+ "INTERACTION_SUBMIT_FAILED",
1358
+ "运行时未及时确认交互提交,请重试",
1359
+ status_code=409,
1360
+ ) from exc
1055
1361
  except Exception as exc: # noqa: BLE001 - provider errors are user-safe here
1362
+ submitted.difference_update({interaction_id, provider_call_id})
1056
1363
  raise StudioError(
1057
1364
  "INTERACTION_SUBMIT_FAILED",
1058
1365
  str(exc),
@@ -1065,22 +1372,51 @@ class StudioRunService:
1065
1372
  submit_ack = asyncio.get_running_loop().create_future()
1066
1373
  queue.put_nowait(("resume", payload, submit_ack))
1067
1374
  try:
1068
- await submit_ack
1375
+ await asyncio.wait_for(
1376
+ submit_ack,
1377
+ timeout=_INTERACTION_SUBMIT_TIMEOUT_SECONDS,
1378
+ )
1379
+ except TimeoutError as exc:
1380
+ submitted.difference_update({interaction_id, provider_call_id})
1381
+ raise StudioError(
1382
+ "INTERACTION_SUBMIT_FAILED",
1383
+ "运行时未及时确认交互提交,请重试",
1384
+ status_code=409,
1385
+ ) from exc
1069
1386
  except Exception as exc: # noqa: BLE001 - provider errors are user-safe here
1387
+ submitted.difference_update({interaction_id, provider_call_id})
1070
1388
  raise StudioError(
1071
1389
  "INTERACTION_SUBMIT_FAILED",
1072
1390
  str(exc),
1073
1391
  status_code=409,
1074
1392
  ) from exc
1075
1393
  else:
1394
+ submitted.difference_update({interaction_id, provider_call_id})
1076
1395
  raise StudioError("INTERACTION_EXPIRED", "运行时交互已失效", status_code=409)
1077
1396
 
1078
1397
  next_revision = revision + 1
1398
+ normalized_action = name.lower()
1399
+ if normalized_action in {"approve", "approved", "accept", "accepted"}:
1400
+ outcome = "approved"
1401
+ response_summary = "已同意"
1402
+ elif normalized_action in {"reject", "rejected", "deny", "denied", "decline"}:
1403
+ outcome = "rejected"
1404
+ response_summary = "已拒绝"
1405
+ elif normalized_action in {"cancel", "cancelled", "canceled"}:
1406
+ outcome = "cancelled"
1407
+ response_summary = "已反馈给 Agent" if data.get("feedback") else "已取消"
1408
+ else:
1409
+ outcome = "submitted"
1410
+ response_summary = "已提交"
1079
1411
  resolved_data = {
1080
1412
  "runId": run_id,
1081
1413
  "interactionId": interaction_id,
1082
- "callId": interaction_id,
1414
+ "callId": provider_call_id,
1083
1415
  "name": name,
1416
+ "action": name,
1417
+ "outcome": outcome,
1418
+ "actor": "user",
1419
+ "responseSummary": response_summary,
1084
1420
  "data": data,
1085
1421
  "revision": next_revision,
1086
1422
  "expectedRevision": expected_revision,
@@ -1092,6 +1428,7 @@ class StudioRunService:
1092
1428
  interaction.data.get("surfaceId") or interaction.data.get("surface_id") or ""
1093
1429
  ),
1094
1430
  "interactionId": interaction_id,
1431
+ "callId": provider_call_id,
1095
1432
  "actionId": f"action-{interaction_id}",
1096
1433
  "name": name,
1097
1434
  "data": data,
@@ -1111,6 +1448,65 @@ class StudioRunService:
1111
1448
  self._waiting_modes.pop(run_id, None)
1112
1449
  return receipt
1113
1450
 
1451
+ def _expire_unresolved_interactions(
1452
+ self,
1453
+ record: RunRecord,
1454
+ *,
1455
+ on_event: Callable[[RunEvent], None] | None = None,
1456
+ ) -> None:
1457
+ """Close orphaned cards whenever their owning run is terminal."""
1458
+
1459
+ if record.status not in {
1460
+ RunStatus.COMPLETED,
1461
+ RunStatus.FAILED,
1462
+ RunStatus.CANCELLED,
1463
+ RunStatus.INTERRUPTED,
1464
+ RunStatus.TIMED_OUT,
1465
+ }:
1466
+ return
1467
+ events = self.event_store.events(record.id)
1468
+ closed_ids = {
1469
+ str(event.data.get("interactionId") or event.data.get("approvalId") or "")
1470
+ for event in events
1471
+ if event.type
1472
+ in {
1473
+ "a2ui.action",
1474
+ "approval.resolved",
1475
+ "interaction.resolved",
1476
+ "interaction.cancelled",
1477
+ "interaction.expired",
1478
+ }
1479
+ }
1480
+ pending: dict[str, RunEvent] = {}
1481
+ for event in events:
1482
+ if event.type != "a2ui.interaction":
1483
+ continue
1484
+ interaction_id = str(
1485
+ event.data.get("interactionId") or event.data.get("interaction_id") or ""
1486
+ )
1487
+ if interaction_id and interaction_id not in closed_ids:
1488
+ pending[interaction_id] = event
1489
+ for interaction_id, requested in pending.items():
1490
+ data = requested.data
1491
+ expired = self.event_store.append(
1492
+ record.id,
1493
+ "interaction.expired",
1494
+ {
1495
+ "runId": record.id,
1496
+ "interactionId": interaction_id,
1497
+ "approvalId": interaction_id,
1498
+ "callId": str(data.get("callId") or data.get("call_id") or ""),
1499
+ "kind": str(data.get("kind") or "form"),
1500
+ "title": data.get("title"),
1501
+ "message": data.get("message"),
1502
+ "detail": data.get("detail"),
1503
+ "outcome": "expired",
1504
+ "revision": _interaction_revision(data) + 1,
1505
+ },
1506
+ )
1507
+ if on_event is not None:
1508
+ on_event(expired)
1509
+
1114
1510
  async def _capture_pcm_evidence(
1115
1511
  self,
1116
1512
  record: RunRecord,
@@ -1255,7 +1651,11 @@ class StudioRunService:
1255
1651
  "runId": record.id,
1256
1652
  "surfaceId": surface_id,
1257
1653
  "interactionId": approval_id,
1654
+ "callId": event.request.call_id or approval_id,
1258
1655
  "kind": "approval",
1656
+ "title": "需要审批",
1657
+ "message": "此次操作需要确认后才能继续。",
1658
+ "detail": detail,
1259
1659
  "revision": 1,
1260
1660
  "inputSchema": {
1261
1661
  "type": "object",
@@ -1293,16 +1693,30 @@ class StudioRunService:
1293
1693
  agent_id: str,
1294
1694
  session_id: str,
1295
1695
  runtime_type: str,
1696
+ build_id: str,
1296
1697
  ) -> dict[str, str]:
1297
1698
  if runtime_type != "codex":
1298
1699
  return {}
1299
- for previous in self.event_store.list_runs(session_id=session_id):
1300
- if previous.agent_id != agent_id or previous.status != RunStatus.COMPLETED:
1301
- continue
1700
+ runs = self.event_store.list_runs(session_id=session_id, agent_id=agent_id)
1701
+ thread_builds: dict[str, str] = {}
1702
+ for previous in runs:
1703
+ native_ref = previous.runtime_handle.get("native_ref") or {}
1704
+ if isinstance(native_ref, dict) and native_ref.get("thread_id"):
1705
+ # Older Studio versions also saved failed cross-build resumes.
1706
+ # The first occurrence identifies the thread's actual home.
1707
+ thread_builds.setdefault(str(native_ref["thread_id"]), previous.build_id)
1708
+ for previous in reversed(runs):
1709
+ # Each immutable build has its own CODEX_HOME and plugin snapshot.
1710
+ # Starting a thread in that home applies the new capabilities; the
1711
+ # transport-neutral history above preserves the Studio conversation.
1712
+ if previous.build_id != build_id:
1713
+ return {}
1302
1714
  native_ref = previous.runtime_handle.get("native_ref")
1303
1715
  native_ref = native_ref if isinstance(native_ref, dict) else {}
1304
1716
  thread_id = str(native_ref.get("thread_id") or "")
1305
1717
  if thread_id:
1718
+ if thread_builds[thread_id] != build_id:
1719
+ return {}
1306
1720
  return {"thread_id": thread_id}
1307
1721
  return {}
1308
1722
 
@@ -1340,17 +1754,13 @@ def _normalized_plugin_usage(usage: Mapping[str, Any]) -> dict[str, Any]:
1340
1754
 
1341
1755
  normalized = {
1342
1756
  "input_tokens": number("input_tokens", "inputTokens", "prompt_tokens"),
1343
- "output_tokens": number(
1344
- "output_tokens", "outputTokens", "completion_tokens"
1345
- ),
1757
+ "output_tokens": number("output_tokens", "outputTokens", "completion_tokens"),
1346
1758
  "total_tokens": number("total_tokens", "totalTokens"),
1347
1759
  "cached_tokens": number("cached_tokens", "cachedTokens"),
1348
1760
  "reasoning_tokens": number("reasoning_tokens", "reasoningTokens"),
1349
1761
  }
1350
1762
  if not normalized["total_tokens"]:
1351
- normalized["total_tokens"] = (
1352
- normalized["input_tokens"] + normalized["output_tokens"]
1353
- )
1763
+ normalized["total_tokens"] = normalized["input_tokens"] + normalized["output_tokens"]
1354
1764
  normalized["reported"] = bool(usage) and any(
1355
1765
  key in usage
1356
1766
  for key in (
@@ -1520,7 +1930,9 @@ def project_runtime_event(
1520
1930
  payload = {
1521
1931
  "interactionId": event.interaction_id,
1522
1932
  "kind": "form",
1523
- "inputSchema": {},
1933
+ "inputSchema": event.request.schema_,
1934
+ "message": event.request.prompt or "",
1935
+ "callId": event.source.native_event_id or event.interaction_id,
1524
1936
  }
1525
1937
  elif isinstance(event, InteractionResolved):
1526
1938
  if event.interaction_kind == "approval":
@@ -1575,9 +1987,7 @@ def project_runtime_event(
1575
1987
  return projected, payload
1576
1988
 
1577
1989
 
1578
- def _first_content(
1579
- snapshot: ContentSnapshot | None, content_type: type
1580
- ) -> Any | None:
1990
+ def _first_content(snapshot: ContentSnapshot | None, content_type: type) -> Any | None:
1581
1991
  if snapshot is None:
1582
1992
  return None
1583
1993
  for part in snapshot.parts: