agentengine-sdk-python 0.8.2__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 (563) hide show
  1. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +22 -28
  2. agentengine_sdk_python-0.8.4.dist-info/RECORD +1070 -0
  3. ksadk/_build_provenance.json +1 -0
  4. ksadk/agui/_agent_helpers.py +4 -0
  5. ksadk/api/client.py +108 -91
  6. ksadk/builders/code_builder.py +36 -9
  7. ksadk/builders/framework_requirements.py +2 -1
  8. ksadk/builders/ks3_uploader.py +36 -7
  9. ksadk/builders/managed_runtime_builder.py +4 -0
  10. ksadk/cli/__init__.py +38 -3
  11. ksadk/cli/cmd_managed_runtime.py +13 -1
  12. ksadk/cli/cmd_plugin.py +662 -0
  13. ksadk/cli/cmd_web.py +2 -5
  14. ksadk/cli/runtime_bootstrap.py +23 -1
  15. ksadk/codex/client.py +424 -96
  16. ksadk/codex/projection.py +24 -0
  17. ksadk/codex/runtime.py +83 -283
  18. ksadk/common/auth.py +16 -10
  19. ksadk/configs/env_registry.py +59 -3
  20. ksadk/configs/settings.py +9 -0
  21. ksadk/context_engine/contributors.py +73 -8
  22. ksadk/conversations/__init__.py +19 -0
  23. ksadk/conversations/context.py +104 -24
  24. ksadk/conversations/contracts.py +266 -0
  25. ksadk/conversations/message_projection.py +154 -15
  26. ksadk/conversations/projector.py +614 -0
  27. ksadk/conversations/reducer.py +98 -0
  28. ksadk/conversations/runtime_invocation.py +5 -0
  29. ksadk/conversations/runtime_payloads.py +1 -0
  30. ksadk/conversations/runtime_preparation.py +30 -27
  31. ksadk/conversations/runtime_resume.py +50 -2
  32. ksadk/conversations/runtime_stream_events.py +5 -0
  33. ksadk/conversations/runtime_streaming.py +25 -7
  34. ksadk/deployment/env_forward.py +2 -2
  35. ksadk/deployment/providers/serverless.py +1 -1
  36. ksadk/events/_v1_compat/projection.py +2 -0
  37. ksadk/events/adapters/_codex_validators.py +18 -7
  38. ksadk/events/adapters/codex.py +190 -0
  39. ksadk/events/adapters/langgraph.py +15 -1
  40. ksadk/events/canonical_store.py +3 -1
  41. ksadk/events/projections.py +1 -1
  42. ksadk/harness/__init__.py +45 -35
  43. ksadk/harness/config.py +2 -2
  44. ksadk/harness/runtime.py +75 -16
  45. ksadk/harness/tools.py +38 -13
  46. ksadk/interaction/provider.py +1 -0
  47. ksadk/interaction/providers/langgraph.py +1 -0
  48. ksadk/kernel/bootstrap.py +28 -4
  49. ksadk/kernel/contract_fingerprints.py +5 -4
  50. ksadk/kernel/contracts.py +8 -0
  51. ksadk/kernel/control.py +1 -0
  52. ksadk/kernel/ingress.py +36 -2
  53. ksadk/kernel/memory_store.py +1 -0
  54. ksadk/kernel/postgres_store.py +1 -0
  55. ksadk/kernel/sqlite_store.py +28 -0
  56. ksadk/kernel/store.py +3 -0
  57. ksadk/kernel/worker.py +76 -10
  58. ksadk/knowledge_base/client.py +57 -27
  59. ksadk/mcp_runtime/__init__.py +12 -4
  60. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  61. ksadk/memory/adk/resilient_session_service.py +25 -17
  62. ksadk/memory/adk/short_term_memory.py +26 -9
  63. ksadk/memory/models.py +7 -4
  64. ksadk/memory/provider_resolver.py +3 -0
  65. ksadk/memory/providers/local_sqlite.py +7 -0
  66. ksadk/model_proxy/server.py +10 -5
  67. ksadk/plugins/__init__.py +171 -0
  68. ksadk/plugins/artifacts.py +275 -0
  69. ksadk/plugins/bridges/__init__.py +47 -0
  70. ksadk/plugins/bridges/codex.py +659 -0
  71. ksadk/plugins/bridges/dsh.py +1300 -0
  72. ksadk/plugins/builtins.py +746 -0
  73. ksadk/plugins/bundle.py +246 -0
  74. ksadk/plugins/bundle_security.py +191 -0
  75. ksadk/plugins/codex_manifest.py +983 -0
  76. ksadk/plugins/composition.py +537 -0
  77. ksadk/plugins/context_contributor.py +437 -0
  78. ksadk/plugins/contracts.py +569 -0
  79. ksadk/plugins/delivery.py +153 -0
  80. ksadk/plugins/dsh_installation_digest.py +71 -0
  81. ksadk/plugins/dsh_toolchain.py +1024 -0
  82. ksadk/plugins/ecosystem_bridge.py +1105 -0
  83. ksadk/plugins/ecosystem_probe.py +191 -0
  84. ksadk/plugins/host.py +787 -0
  85. ksadk/plugins/kernel_adapter.py +205 -0
  86. ksadk/plugins/providers/__init__.py +108 -0
  87. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  88. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  89. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  90. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  91. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  92. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  93. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  94. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  95. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  96. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  97. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  98. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  99. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  100. ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
  101. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
  102. ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
  103. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  104. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  105. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  106. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  107. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  108. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  109. ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
  110. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
  111. ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
  112. ksadk/plugins/providers/codex.py +988 -0
  113. ksadk/plugins/providers/codex_dsh.py +83 -0
  114. ksadk/plugins/providers/codex_native.py +368 -0
  115. ksadk/plugins/providers/codex_turn.py +301 -0
  116. ksadk/plugins/providers/dsh.py +951 -0
  117. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  118. ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
  119. ksadk/plugins/providers/dsh_mcp.py +467 -0
  120. ksadk/plugins/providers/harness.py +632 -0
  121. ksadk/plugins/providers/harness_dsh.py +91 -0
  122. ksadk/plugins/providers/legacy.py +215 -0
  123. ksadk/plugins/providers/legacy_catalog.py +100 -0
  124. ksadk/plugins/providers/mcp_projection.py +150 -0
  125. ksadk/plugins/providers/platform_resources.py +657 -0
  126. ksadk/plugins/providers/shipped_dsh.py +370 -0
  127. ksadk/plugins/resolver.py +338 -0
  128. ksadk/plugins/subagent_providers/__init__.py +12 -0
  129. ksadk/plugins/subagent_providers/codex.py +443 -0
  130. ksadk/plugins/subagents.py +333 -0
  131. ksadk/resource_runtime/__init__.py +4 -0
  132. ksadk/resource_runtime/broker.py +616 -0
  133. ksadk/resource_runtime/build_artifacts.py +165 -0
  134. ksadk/resource_runtime/contracts.py +138 -0
  135. ksadk/resource_runtime/discovery_receipts.py +100 -0
  136. ksadk/resource_runtime/discovery_skills.py +172 -0
  137. ksadk/resource_runtime/errors.py +6 -0
  138. ksadk/resource_runtime/ipc.py +142 -0
  139. ksadk/resource_runtime/kernel_approval.py +165 -0
  140. ksadk/resource_runtime/knowledge.py +114 -0
  141. ksadk/resource_runtime/langgraph.py +94 -0
  142. ksadk/resource_runtime/leases.py +191 -0
  143. ksadk/resource_runtime/managed_projection.py +186 -0
  144. ksadk/resource_runtime/mcp_server.py +138 -0
  145. ksadk/resource_runtime/memory_provider.py +318 -0
  146. ksadk/resource_runtime/memory_receipts.py +34 -0
  147. ksadk/resource_runtime/operation_ledger.py +211 -0
  148. ksadk/resource_runtime/plugin_config.py +48 -0
  149. ksadk/resource_runtime/policy_authorization.py +54 -0
  150. ksadk/resource_runtime/process.py +110 -0
  151. ksadk/resource_runtime/skill_artifacts.py +153 -0
  152. ksadk/resource_runtime/skill_runtime.py +42 -0
  153. ksadk/resource_runtime/skill_workspace.py +118 -0
  154. ksadk/resource_runtime/skills.py +215 -0
  155. ksadk/resource_runtime/snapshots.py +180 -0
  156. ksadk/resource_runtime/socket_server.py +103 -0
  157. ksadk/resource_runtime/supervisor.py +380 -0
  158. ksadk/resource_runtime/worker.py +504 -0
  159. ksadk/runners/_langgraph_runner_streams.py +74 -6
  160. ksadk/runners/adk_runner.py +149 -11
  161. ksadk/runners/base_runner.py +29 -1
  162. ksadk/runners/langgraph_runner.py +475 -145
  163. ksadk/runtime/_runner_adapter/stream_mapping.py +193 -60
  164. ksadk/runtime/adapter.py +3 -0
  165. ksadk/runtime/conversation_execution.py +92 -16
  166. ksadk/runtime/executor.py +78 -2
  167. ksadk/runtime/factory.py +30 -200
  168. ksadk/runtime/framework_adapters.py +41 -0
  169. ksadk/runtime/preprocessing.py +10 -2
  170. ksadk/runtime/runner_adapter.py +78 -14
  171. ksadk/runtime_context.py +40 -2
  172. ksadk/sandbox/__init__.py +2 -1
  173. ksadk/sandbox/backends/e2b.py +52 -11
  174. ksadk/sandbox/backends/local_process.py +9 -0
  175. ksadk/sandbox/base.py +2 -0
  176. ksadk/sandbox/e2b_connection.py +66 -0
  177. ksadk/sandbox/factory.py +72 -0
  178. ksadk/scheduler/__init__.py +18 -0
  179. ksadk/scheduler/calendar.py +102 -0
  180. ksadk/scheduler/contracts.py +254 -0
  181. ksadk/scheduler/dispatcher.py +129 -0
  182. ksadk/scheduler/engine.py +416 -0
  183. ksadk/scheduler/sqlite_store.py +581 -0
  184. ksadk/server/composition.py +2 -0
  185. ksadk/server/factory.py +5 -0
  186. ksadk/server/persistence_capability.py +516 -0
  187. ksadk/server/routes/control.py +210 -46
  188. ksadk/server/routes/dependencies.py +15 -0
  189. ksadk/server/routes/models.py +47 -4
  190. ksadk/server/routes/projection.py +252 -12
  191. ksadk/server/routes/sessions.py +284 -107
  192. ksadk/server/routes/streaming.py +43 -9
  193. ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  194. ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-b4C7upmO.js} +3 -3
  195. ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  196. ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  197. ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  198. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  199. ksadk/server/static/assets/{arc-C4FzinUA.js → arc-bTohInsS.js} +1 -1
  200. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  201. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  202. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  203. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  204. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  205. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  206. ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  207. ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  208. ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  209. ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  210. ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  211. ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  212. ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  213. ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  214. ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  215. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  216. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  217. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  218. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  219. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  220. ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  221. ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-UBpgon5q.js} +1 -1
  222. ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  223. ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  224. ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  225. ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  226. ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  227. ksadk/server/static/assets/{dist-B7seoj3d.js → dist-B2_CVgKv.js} +1 -1
  228. ksadk/server/static/assets/{dist-CSh_DE14.js → dist-B3FR1SKK.js} +1 -1
  229. ksadk/server/static/assets/{dist-DUX-id_F.js → dist-BIr4DSRq.js} +1 -1
  230. ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-BgV_owcB.js} +1 -1
  231. ksadk/server/static/assets/{dist-W-TIVntx.js → dist-Bj730Ib4.js} +1 -1
  232. ksadk/server/static/assets/{dist-BytlxIDT.js → dist-BnaTiyzN.js} +1 -1
  233. ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C1NMAY5a.js} +1 -1
  234. ksadk/server/static/assets/{dist-dDdADKFA.js → dist-C5_ZAZsG.js} +1 -1
  235. ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-CB9iJrvg.js} +1 -1
  236. ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-CFzsn6BG.js} +1 -1
  237. ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-Cf125P_m.js} +1 -1
  238. ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-ClYUxfeK.js} +1 -1
  239. ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DFD6Qa6T.js} +1 -1
  240. ksadk/server/static/assets/{dist-BX8z72IC.js → dist-DVCOWtha.js} +1 -1
  241. ksadk/server/static/assets/{dist-dydu68Fl.js → dist-D_ctSS2i.js} +1 -1
  242. ksadk/server/static/assets/{dist-ClxGviKw.js → dist-DiixqL0J.js} +1 -1
  243. ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-DoVSwoDb.js} +1 -1
  244. ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-DvFK7p5S.js} +1 -1
  245. ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-QfkEHOlb.js} +1 -1
  246. ksadk/server/static/assets/{dist-CttYUqzS.js → dist-btbmmX5O.js} +1 -1
  247. ksadk/server/static/assets/{dist-DmldrHd_.js → dist-fBO2v5Kt.js} +1 -1
  248. ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-ufY3F5p6.js} +1 -1
  249. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  250. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  251. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  252. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  253. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  254. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  255. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  256. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  257. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  258. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  259. ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  260. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  261. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  262. ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  263. ksadk/server/static/assets/{katex-vFWytM5c.js → katex-B4weu383.js} +1 -1
  264. ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-V-MgYHW1.js} +1 -1
  265. ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  266. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  267. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  268. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  269. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  270. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  271. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  272. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  273. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  274. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  275. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  276. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  277. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  278. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  279. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  280. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  281. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  282. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  283. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  284. ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  285. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  286. ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  287. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  288. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  289. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  290. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  291. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  292. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  293. ksadk/server/static/index.html +2 -2
  294. ksadk/session_context.py +66 -0
  295. ksadk/sessions/__init__.py +11 -21
  296. ksadk/sessions/_local_service_sync.py +263 -1
  297. ksadk/sessions/base.py +176 -0
  298. ksadk/sessions/errors.py +4 -0
  299. ksadk/sessions/in_memory.py +309 -19
  300. ksadk/sessions/local_service.py +83 -1
  301. ksadk/sessions/persistence.py +275 -0
  302. ksadk/sessions/postgres_service.py +358 -0
  303. ksadk/sessions/resilience.py +8 -0
  304. ksadk/sessions/resilient.py +362 -4
  305. ksadk/sessions/topology.py +135 -0
  306. ksadk/skills/models.py +26 -4
  307. ksadk/skills/package_store.py +186 -38
  308. ksadk/skills/runtime/agent.py +31 -6
  309. ksadk/skills/runtime/artifact_delivery.py +139 -0
  310. ksadk/skills/runtime/backends/e2b.py +98 -6
  311. ksadk/skills/runtime/backends/local.py +73 -8
  312. ksadk/skills/runtime/base.py +3 -0
  313. ksadk/skills/runtime/executor.py +2 -0
  314. ksadk/skills/runtime/loader.py +10 -2
  315. ksadk/skills/runtime/pinned.py +114 -0
  316. ksadk/skills/runtime/request.py +31 -0
  317. ksadk/skills/service_client.py +211 -24
  318. ksadk/studio/agent_lifecycle.py +26 -20
  319. ksadk/studio/api.py +714 -90
  320. ksadk/studio/api_catalog_routes.py +23 -0
  321. ksadk/studio/api_contracts.py +34 -1
  322. ksadk/studio/api_plugin_routes.py +911 -0
  323. ksadk/studio/api_resource_connections.py +183 -0
  324. ksadk/studio/attachment_store.py +187 -0
  325. ksadk/studio/authoring.py +10 -4
  326. ksadk/studio/authoring_coordinator.py +31 -16
  327. ksadk/studio/builder.py +199 -43
  328. ksadk/studio/cloud.py +346 -104
  329. ksadk/studio/cloud_shared_web.py +565 -0
  330. ksadk/studio/codex_agent_service.py +140 -27
  331. ksadk/studio/codex_builder.py +294 -16
  332. ksadk/studio/codex_credentials.py +90 -0
  333. ksadk/studio/codex_manifest.py +51 -4
  334. ksadk/studio/codex_plugin_store.py +746 -0
  335. ksadk/studio/codex_provider_build.py +231 -0
  336. ksadk/studio/codex_run.py +200 -29
  337. ksadk/studio/compatibility_report.py +456 -0
  338. ksadk/studio/compiler.py +84 -15
  339. ksadk/studio/contracts.py +249 -4
  340. ksadk/studio/dsh_application.py +137 -0
  341. ksadk/studio/dsh_capability_service.py +1107 -0
  342. ksadk/studio/dsh_models.py +59 -0
  343. ksadk/studio/dsh_provider_registration.py +1075 -0
  344. ksadk/studio/event_store.py +54 -6
  345. ksadk/studio/framework_run.py +37 -4
  346. ksadk/studio/hosted_kernel.py +89 -14
  347. ksadk/studio/mcp_runtime.py +11 -3
  348. ksadk/studio/model_client.py +2 -2
  349. ksadk/studio/operations.py +12 -2
  350. ksadk/studio/plugin_composition.py +468 -0
  351. ksadk/studio/plugin_kernel_adapter.py +28 -0
  352. ksadk/studio/plugin_runtime.py +831 -0
  353. ksadk/studio/resource_authority.py +637 -0
  354. ksadk/studio/resource_binding_validation.py +77 -0
  355. ksadk/studio/resource_build_admission.py +196 -0
  356. ksadk/studio/resource_build_materializer.py +149 -0
  357. ksadk/studio/resource_catalog.py +149 -3
  358. ksadk/studio/resource_connections.py +220 -0
  359. ksadk/studio/run_service.py +1144 -96
  360. ksadk/studio/runtime_source.py +24 -8
  361. ksadk/studio/scheduler_assistant.py +317 -0
  362. ksadk/studio/scheduler_runtime.py +383 -0
  363. ksadk/studio/scheduler_service.py +214 -0
  364. ksadk/studio/service.py +1131 -95
  365. ksadk/studio/shared_web.py +610 -87
  366. ksadk/studio/soul.py +52 -0
  367. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  368. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  369. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  372. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  373. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  377. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  378. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  379. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  380. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  381. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  382. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  383. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  384. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  385. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  386. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  387. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  388. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  389. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  390. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  391. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  392. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  393. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  394. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  395. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  396. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  397. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  398. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  399. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  400. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  401. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  402. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  403. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  404. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  405. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  406. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  407. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  408. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  409. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  410. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  411. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  412. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  413. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  414. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  415. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  416. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  417. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  418. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  419. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  420. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  421. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  422. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  423. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  424. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  425. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  426. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  427. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  428. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  429. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  430. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  431. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  432. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  433. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  434. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  435. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  436. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  437. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  438. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  439. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  440. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  441. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  442. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  443. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  444. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  445. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  446. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  447. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  448. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  449. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  450. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  451. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  452. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  453. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  454. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  455. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  456. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  457. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  458. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  459. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  460. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  461. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  462. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  463. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  464. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  465. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  466. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  467. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  468. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  469. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  470. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  471. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  472. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  473. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  474. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  475. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  476. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  477. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  478. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  479. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  480. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  481. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  482. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  483. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  484. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  485. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  486. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  487. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  488. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  489. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  490. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  491. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  492. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  493. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  494. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  495. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  496. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  497. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  498. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  499. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  500. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  501. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  502. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  503. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  504. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  505. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  506. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  507. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  508. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  509. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  510. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  511. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  512. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  513. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  514. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  515. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  516. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  517. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  518. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  519. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  520. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  521. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  522. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  523. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  524. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  525. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  526. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  527. ksadk/studio/static/index.html +2 -2
  528. ksadk/studio/validator.py +1 -1
  529. ksadk/studio/workspace.py +1 -0
  530. ksadk/version.py +1 -1
  531. ksadk_runtime_common/workspace_files/path_utils.py +41 -0
  532. agentengine_sdk_python-0.8.2.dist-info/RECORD +0 -778
  533. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
  534. ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
  535. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
  536. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
  537. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
  538. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
  539. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
  540. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
  541. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
  542. ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
  543. ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
  544. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
  545. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
  546. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
  547. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
  548. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
  549. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
  550. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
  551. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
  552. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
  553. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
  554. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
  555. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
  556. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
  557. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  558. ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
  559. ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
  560. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  561. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  562. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  563. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
ksadk/plugins/host.py ADDED
@@ -0,0 +1,787 @@
1
+ """Transactional, side-effect-owning PluginHost foundation (P2-03A).
2
+
3
+ The host has no knowledge of AgentControl, SessionEvent sequencing, or cloud
4
+ deployment. It only stages a fully resolved profile, atomically swaps it once
5
+ healthy, and disposes owned effects in reverse dependency order.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import asyncio
11
+ from collections.abc import Coroutine, Mapping
12
+ from dataclasses import dataclass
13
+ from typing import Any, Protocol, runtime_checkable
14
+ from uuid import uuid4
15
+
16
+ from ksadk.plugins.bundle import ResolvedPluginBundle
17
+ from ksadk.plugins.contracts import (
18
+ CompositionProfile,
19
+ PluginInventory,
20
+ PluginInventoryItem,
21
+ PluginLockEntry,
22
+ PluginManifest,
23
+ )
24
+ from ksadk.plugins.resolver import (
25
+ PluginRegistry,
26
+ PluginResolutionError,
27
+ ResolvedComposition,
28
+ )
29
+
30
+
31
+ class PluginHostError(RuntimeError):
32
+ """Stable reject/failure from PluginHost profile transactions."""
33
+
34
+ def __init__(self, code: str, message: str) -> None:
35
+ super().__init__(message)
36
+ self.code = code
37
+
38
+
39
+ @runtime_checkable
40
+ class ManagedPlugin(Protocol):
41
+ """Effects owned by one staged plugin instance."""
42
+
43
+ async def start(self) -> None: ...
44
+
45
+ async def health(self) -> bool: ...
46
+
47
+ async def drain(self) -> None: ...
48
+
49
+ async def dispose(self) -> None: ...
50
+
51
+
52
+ @runtime_checkable
53
+ class PluginFactory(Protocol):
54
+ """Factory seam; `stage` must not expose partially started effects."""
55
+
56
+ async def stage(
57
+ self,
58
+ manifest: PluginManifest,
59
+ *,
60
+ profile: CompositionProfile,
61
+ services: Mapping[str, Any],
62
+ ) -> ManagedPlugin: ...
63
+
64
+
65
+ @dataclass(frozen=True)
66
+ class PluginCapabilityBinding:
67
+ """One locked capability and the active runtime that owns it."""
68
+
69
+ plugin_id: str
70
+ plugin_version: str
71
+ definition: str
72
+ slot: str
73
+ runtime: ManagedPlugin
74
+
75
+
76
+ @dataclass(frozen=True)
77
+ class PluginExecutionContext:
78
+ """Read-only capability view passed to the active AgentProvider."""
79
+
80
+ profile_digest: str
81
+ plugin_lock_digest: str
82
+ bindings: tuple[PluginCapabilityBinding, ...]
83
+ # The host owns this key. Capability plugins may use it to bind ephemeral
84
+ # leases to the same provider activation without learning request payloads.
85
+ activation_key: str = ""
86
+
87
+ def all(
88
+ self,
89
+ definition: str,
90
+ *,
91
+ slot: str | None = None,
92
+ ) -> tuple[PluginCapabilityBinding, ...]:
93
+ return tuple(
94
+ binding
95
+ for binding in self.bindings
96
+ if binding.definition == definition and (slot is None or binding.slot == slot)
97
+ )
98
+
99
+ def require(
100
+ self,
101
+ definition: str,
102
+ *,
103
+ slot: str | None = None,
104
+ ) -> PluginCapabilityBinding:
105
+ matches = self.all(definition, slot=slot)
106
+ if not matches:
107
+ suffix = f" in slot {slot!r}" if slot is not None else ""
108
+ raise PluginHostError(
109
+ "plugin_capability_unavailable",
110
+ f"active profile does not provide {definition!r}{suffix}",
111
+ )
112
+ if len(matches) != 1:
113
+ raise PluginHostError(
114
+ "plugin_capability_ambiguous",
115
+ f"active profile provides more than one {definition!r}; select a slot",
116
+ )
117
+ return matches[0]
118
+
119
+
120
+ @runtime_checkable
121
+ class PreparedAgent(ManagedPlugin, Protocol):
122
+ """One provider-owned activation prepared from an immutable Bundle."""
123
+
124
+ async def execute(self, request: Any) -> Any: ...
125
+
126
+
127
+ @runtime_checkable
128
+ class ExecutableAgentProvider(ManagedPlugin, Protocol):
129
+ """AgentProvider execution seam used by the first PluginHost vertical.
130
+
131
+ ``prepare`` must either return an unstarted activation or clean up all of
132
+ its own partial effects before raising. PluginHost owns start, health,
133
+ drain, and dispose for every returned activation.
134
+ """
135
+
136
+ async def prepare(
137
+ self,
138
+ bundle: ResolvedPluginBundle,
139
+ *,
140
+ capabilities: PluginExecutionContext,
141
+ ) -> PreparedAgent: ...
142
+
143
+
144
+ @dataclass(frozen=True)
145
+ class _ActivePlugin:
146
+ entry: PluginLockEntry
147
+ runtime: ManagedPlugin
148
+
149
+
150
+ @dataclass(frozen=True)
151
+ class _ActiveGraph:
152
+ resolved: ResolvedComposition
153
+ plugins: tuple[_ActivePlugin, ...]
154
+
155
+
156
+ @dataclass
157
+ class _ActiveActivation:
158
+ key: str
159
+ graph: _ActiveGraph
160
+ bundle_digest: str
161
+ runtime: PreparedAgent
162
+ operation_lock: asyncio.Lock
163
+ operation_task: asyncio.Task[Any] | None = None
164
+ closed: bool = False
165
+
166
+
167
+ class PluginActivationSession:
168
+ """Provider-owned activation retained across turns for one session.
169
+
170
+ The handle is deliberately small: PluginHost still owns lifecycle and
171
+ profile fencing, while the provider owns any native thread/checkpoint state
172
+ inside ``PreparedAgent``. Calls are serialized per activation because a
173
+ conversational session is an ordered command stream.
174
+ """
175
+
176
+ def __init__(self, host: "PluginHost", active: _ActiveActivation) -> None:
177
+ self._host = host
178
+ self._active = active
179
+
180
+ @property
181
+ def key(self) -> str:
182
+ return self._active.key
183
+
184
+ @property
185
+ def bundle_digest(self) -> str:
186
+ return self._active.bundle_digest
187
+
188
+ @property
189
+ def closed(self) -> bool:
190
+ return self._active.closed
191
+
192
+ async def execute(self, request: Any) -> Any:
193
+ return await self._host._execute_activation(self._active, request)
194
+
195
+ async def runtime_adapter(self) -> Any:
196
+ """Return an optional provider-owned RuntimeAdapter for AgentKernel.
197
+
198
+ ``execute`` remains the minimum cross-provider ABI. Providers that
199
+ need durable AgentControl/SessionEvent ownership (for example local
200
+ Scheduler Lite) may expose this additive seam. PluginHost retains the
201
+ activation/profile fence; unsupported providers fail explicitly.
202
+ """
203
+
204
+ return await self._host._runtime_adapter_activation(self._active)
205
+
206
+ async def close(self) -> None:
207
+ await self._host.close_activation(self._active.key, expected=self._active)
208
+
209
+
210
+ class PluginHost:
211
+ """Apply resolved profiles without tearing down a healthy old graph first."""
212
+
213
+ def __init__(
214
+ self,
215
+ registry: PluginRegistry,
216
+ factories: Mapping[str, PluginFactory],
217
+ *,
218
+ allowed_permissions: frozenset[str] = frozenset(),
219
+ services: Mapping[str, Any] | None = None,
220
+ ) -> None:
221
+ self._registry = registry
222
+ self._factories = dict(factories)
223
+ self._allowed_permissions = frozenset(allowed_permissions)
224
+ self._services = dict(services or {})
225
+ self._transaction_lock = asyncio.Lock()
226
+ self._active: _ActiveGraph | None = None
227
+ # A profile switch moves default admission atomically, while already
228
+ # prepared conversations may hold provider-native thread/checkpoint
229
+ # state. Retired graphs are reclaimed only after their last session
230
+ # activation closes.
231
+ self._retired: list[_ActiveGraph] = []
232
+ self._activations: dict[str, _ActiveActivation] = {}
233
+ self._last_failure: PluginHostError | None = None
234
+
235
+ async def apply(self, profile: CompositionProfile) -> PluginInventory:
236
+ """Resolve, admit, stage, health-check, then atomically switch profile.
237
+
238
+ Any resolve/admission/stage/health error leaves the current graph
239
+ untouched. Staged effects from the failed candidate are drained and
240
+ disposed before the error is returned.
241
+ """
242
+
243
+ async with self._transaction_lock:
244
+ resolved = self.preflight(profile)
245
+ if self._active and (
246
+ self._active.resolved.profile_digest == resolved.profile_digest
247
+ and self._active.resolved.plugin_lock_digest == resolved.plugin_lock_digest
248
+ ):
249
+ return self._inventory_for(self._active)
250
+
251
+ ordered_entries = _dependency_order(resolved.plugin_lock.plugins)
252
+ staged: list[_ActivePlugin] = []
253
+ try:
254
+ for entry in ordered_entries:
255
+ manifest = self._registry.manifest_for(entry.id, entry.version)
256
+ factory = self._factories[entry.id]
257
+ runtime = await factory.stage(
258
+ manifest,
259
+ profile=resolved.profile,
260
+ services=self._services,
261
+ )
262
+ staged.append(_ActivePlugin(entry=entry, runtime=runtime))
263
+ for plugin in staged:
264
+ await plugin.runtime.start()
265
+ if not await plugin.runtime.health():
266
+ raise PluginHostError(
267
+ "plugin_health_failed",
268
+ f"plugin {plugin.entry.id}@{plugin.entry.version} failed health check",
269
+ )
270
+ except asyncio.CancelledError:
271
+ await self._finish_cleanup(self._dispose_staged(staged))
272
+ raise
273
+ except PluginHostError as error:
274
+ await self._finish_cleanup(self._dispose_staged(staged))
275
+ self._last_failure = error
276
+ raise
277
+ except Exception as error: # noqa: BLE001 - boundary adapts plugins
278
+ await self._finish_cleanup(self._dispose_staged(staged))
279
+ failure = PluginHostError("plugin_stage_failed", str(error))
280
+ self._last_failure = failure
281
+ raise failure from error
282
+
283
+ candidate = _ActiveGraph(resolved=resolved, plugins=tuple(staged))
284
+ previous = self._active
285
+ # This single assignment is the profile switch. It only happens
286
+ # after every staged effect has passed health, preserving the old
287
+ # graph on all earlier failures.
288
+ self._active = candidate
289
+ self._last_failure = None
290
+ if previous is not None:
291
+ self._retired.append(previous)
292
+ await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
293
+ return self._inventory_for(candidate)
294
+
295
+ def preflight(self, profile: CompositionProfile) -> ResolvedComposition:
296
+ """Resolve and admit a profile without importing or starting a plugin."""
297
+
298
+ try:
299
+ resolved = self._registry.resolve(profile)
300
+ except PluginResolutionError as error:
301
+ failure = PluginHostError(error.code, str(error))
302
+ self._last_failure = failure
303
+ raise failure from error
304
+ entries = _dependency_order(resolved.plugin_lock.plugins)
305
+ self._admit(entries)
306
+ for entry in entries:
307
+ if entry.id not in self._factories:
308
+ failure = PluginHostError(
309
+ "plugin_factory_unavailable",
310
+ f"no factory is registered for {entry.id}@{entry.version}",
311
+ )
312
+ self._last_failure = failure
313
+ raise failure
314
+ return resolved
315
+
316
+ def inventory(self) -> PluginInventory | None:
317
+ """Return only the currently active profile inventory, if any."""
318
+
319
+ if self._active is None:
320
+ return None
321
+ return self._inventory_for(self._active)
322
+
323
+ @property
324
+ def activation_count(self) -> int:
325
+ """Number of live provider-owned activations (diagnostic only)."""
326
+
327
+ return sum(not active.closed for active in self._activations.values())
328
+
329
+ async def execute(self, bundle: ResolvedPluginBundle, request: Any) -> Any:
330
+ """Execute one disposable activation (compatibility convenience API)."""
331
+
332
+ session = await self.open_activation(
333
+ bundle,
334
+ activation_key=f"one-shot:{uuid4().hex}",
335
+ )
336
+ try:
337
+ return await session.execute(request)
338
+ finally:
339
+ await session.close()
340
+
341
+ async def open_activation(
342
+ self,
343
+ bundle: ResolvedPluginBundle,
344
+ *,
345
+ activation_key: str,
346
+ ) -> PluginActivationSession:
347
+ """Open or reuse one profile-fenced, provider-owned activation.
348
+
349
+ Reuse is permitted for the exact graph and immutable Bundle digest. A
350
+ profile switch retires its old graph for new sessions, but an existing
351
+ session key remains pinned to that graph until it closes.
352
+ """
353
+
354
+ key = str(activation_key).strip()
355
+ if not key or len(key) > 512:
356
+ raise PluginHostError(
357
+ "agent_activation_key_invalid",
358
+ "activation_key must be a non-empty value of at most 512 characters",
359
+ )
360
+ async with self._transaction_lock:
361
+ existing = self._activations.get(key)
362
+ if existing is not None:
363
+ if (
364
+ not existing.closed
365
+ and existing.bundle_digest == bundle.bundle_digest
366
+ and self._bundle_matches_graph(bundle, existing.graph)
367
+ ):
368
+ # This activation may belong to a retired graph: it was
369
+ # pinned before a newer profile became active.
370
+ return PluginActivationSession(self, existing)
371
+ await self._close_activation_record(existing)
372
+ if self._activations.get(key) is existing:
373
+ self._activations.pop(key, None)
374
+ await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
375
+
376
+ graph = self._require_bundle_graph(bundle)
377
+ runtime = await self._prepare_activation(
378
+ graph,
379
+ bundle,
380
+ activation_key=key,
381
+ )
382
+ active = _ActiveActivation(
383
+ key=key,
384
+ graph=graph,
385
+ bundle_digest=bundle.bundle_digest,
386
+ runtime=runtime,
387
+ operation_lock=asyncio.Lock(),
388
+ )
389
+ self._activations[key] = active
390
+ return PluginActivationSession(self, active)
391
+
392
+ async def close_activation(
393
+ self,
394
+ activation_key: str,
395
+ *,
396
+ expected: _ActiveActivation | None = None,
397
+ ) -> None:
398
+ """Drain and dispose a retained activation if it is still current."""
399
+
400
+ async with self._transaction_lock:
401
+ active = self._activations.get(activation_key)
402
+ if active is None or (expected is not None and active is not expected):
403
+ return
404
+ await self._close_activation_record(active)
405
+ if self._activations.get(activation_key) is active:
406
+ self._activations.pop(activation_key, None)
407
+ await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
408
+
409
+ @property
410
+ def last_failure(self) -> PluginHostError | None:
411
+ return self._last_failure
412
+
413
+ async def dispose(self) -> None:
414
+ """Drain and dispose active plus retired graphs; there is no implicit restart."""
415
+
416
+ async with self._transaction_lock:
417
+ graphs = [graph for graph in [self._active, *self._retired] if graph is not None]
418
+ self._active = None
419
+ self._retired = []
420
+ if graphs:
421
+ await self._finish_cleanup(self._dispose_all_graphs(graphs))
422
+
423
+ @staticmethod
424
+ async def _finish_cleanup(cleanup: Coroutine[Any, Any, None]) -> None:
425
+ """Defer caller cancellation until an owned-effect cleanup finishes."""
426
+
427
+ cleanup_task = asyncio.create_task(cleanup)
428
+ interrupted = False
429
+ while not cleanup_task.done():
430
+ try:
431
+ await asyncio.shield(cleanup_task)
432
+ except asyncio.CancelledError:
433
+ interrupted = True
434
+ cleanup_task.result()
435
+ if interrupted:
436
+ raise asyncio.CancelledError
437
+
438
+ async def _dispose_graph(self, graph: _ActiveGraph) -> None:
439
+ await self._close_graph_activations(graph)
440
+ await self._dispose_staged(list(graph.plugins))
441
+
442
+ async def _dispose_all_graphs(self, graphs: list[_ActiveGraph]) -> None:
443
+ await self._close_all_activations()
444
+ for graph in graphs:
445
+ await self._dispose_staged(list(graph.plugins))
446
+
447
+ async def _dispose_unpinned_retired_graphs(self) -> None:
448
+ for graph in tuple(self._retired):
449
+ if any(
450
+ not activation.closed and activation.graph is graph
451
+ for activation in self._activations.values()
452
+ ):
453
+ continue
454
+ await self._dispose_staged(list(graph.plugins))
455
+ self._retired.remove(graph)
456
+
457
+ def _admit(self, entries: list[PluginLockEntry]) -> None:
458
+ for entry in entries:
459
+ manifest = self._registry.manifest_for(entry.id, entry.version)
460
+ missing = sorted(set(manifest.spec.permissions) - self._allowed_permissions)
461
+ if missing:
462
+ raise PluginHostError(
463
+ "plugin_permission_denied",
464
+ f"plugin {entry.id}@{entry.version} requests unapproved permissions: "
465
+ + ", ".join(missing),
466
+ )
467
+
468
+ @staticmethod
469
+ async def _dispose_staged(staged: list[_ActivePlugin]) -> None:
470
+ """Best-effort cleanup preserves the primary failure while draining all effects."""
471
+
472
+ for plugin in reversed(staged):
473
+ try:
474
+ await plugin.runtime.drain()
475
+ except Exception: # noqa: BLE001 - disposal must continue
476
+ pass
477
+ try:
478
+ await plugin.runtime.dispose()
479
+ except Exception: # noqa: BLE001 - disposal must continue
480
+ pass
481
+
482
+ @staticmethod
483
+ async def _dispose_activation(activation: PreparedAgent) -> None:
484
+ """Best-effort cleanup for a prepared one-shot activation."""
485
+
486
+ try:
487
+ await activation.drain()
488
+ except Exception: # noqa: BLE001 - disposal must continue
489
+ pass
490
+ try:
491
+ await activation.dispose()
492
+ except Exception: # noqa: BLE001 - disposal must continue
493
+ pass
494
+
495
+ def _require_bundle_graph(self, bundle: ResolvedPluginBundle) -> _ActiveGraph:
496
+ graph = self._active
497
+ if graph is None:
498
+ raise PluginHostError("plugin_profile_inactive", "no plugin profile is active")
499
+ if not self._bundle_matches_graph(bundle, graph):
500
+ raise PluginHostError(
501
+ "plugin_bundle_profile_mismatch",
502
+ "Bundle composition does not match the active plugin graph",
503
+ )
504
+ return graph
505
+
506
+ @staticmethod
507
+ def _bundle_matches_graph(bundle: ResolvedPluginBundle, graph: _ActiveGraph) -> bool:
508
+ return (
509
+ bundle.composition.profile_digest == graph.resolved.profile_digest
510
+ and bundle.composition.plugin_lock_digest == graph.resolved.plugin_lock_digest
511
+ )
512
+
513
+ async def _prepare_activation(
514
+ self,
515
+ graph: _ActiveGraph,
516
+ bundle: ResolvedPluginBundle,
517
+ *,
518
+ activation_key: str,
519
+ ) -> PreparedAgent:
520
+ capabilities = self._execution_context(graph, activation_key=activation_key)
521
+ provider_binding = capabilities.require("agent.provider/v1", slot="agent.execution")
522
+ provider = provider_binding.runtime
523
+ if not isinstance(provider, ExecutableAgentProvider):
524
+ raise PluginHostError(
525
+ "agent_provider_not_executable",
526
+ f"plugin {provider_binding.plugin_id}@"
527
+ f"{provider_binding.plugin_version} does not implement prepare",
528
+ )
529
+
530
+ activation: PreparedAgent | None = None
531
+ try:
532
+ try:
533
+ activation = await provider.prepare(bundle, capabilities=capabilities)
534
+ except PluginHostError:
535
+ raise
536
+ except Exception as error: # noqa: BLE001 - provider boundary
537
+ raise PluginHostError("agent_prepare_failed", str(error)) from error
538
+ if not isinstance(activation, PreparedAgent):
539
+ raise PluginHostError(
540
+ "agent_activation_invalid",
541
+ "AgentProvider.prepare returned an invalid activation",
542
+ )
543
+ try:
544
+ await activation.start()
545
+ except Exception as error: # noqa: BLE001 - activation boundary
546
+ raise PluginHostError("agent_activation_start_failed", str(error)) from error
547
+ try:
548
+ healthy = await activation.health()
549
+ except Exception as error: # noqa: BLE001 - activation boundary
550
+ raise PluginHostError("agent_activation_health_failed", str(error)) from error
551
+ if not healthy:
552
+ raise PluginHostError(
553
+ "agent_activation_health_failed",
554
+ "prepared Agent activation failed health check",
555
+ )
556
+ return activation
557
+ except asyncio.CancelledError:
558
+ if activation is not None:
559
+ await self._dispose_activation(activation)
560
+ raise
561
+ except PluginHostError as error:
562
+ self._last_failure = error
563
+ if activation is not None:
564
+ await self._dispose_activation(activation)
565
+ raise
566
+
567
+ async def _execute_activation(
568
+ self,
569
+ active: _ActiveActivation,
570
+ request: Any,
571
+ ) -> Any:
572
+ async with active.operation_lock:
573
+ task = asyncio.current_task()
574
+ active.operation_task = task
575
+ try:
576
+ if active.closed:
577
+ raise PluginHostError(
578
+ "agent_activation_closed",
579
+ f"Agent activation {active.key!r} is closed",
580
+ )
581
+ result = await active.runtime.execute(request)
582
+ except asyncio.CancelledError:
583
+ if not active.closed:
584
+ await self._dispose_activation(active.runtime)
585
+ active.closed = True
586
+ raise
587
+ except PluginHostError as error:
588
+ self._last_failure = error
589
+ await self._dispose_activation(active.runtime)
590
+ active.closed = True
591
+ raise
592
+ except Exception as error: # noqa: BLE001 - provider boundary
593
+ failure = PluginHostError("agent_execution_failed", str(error))
594
+ self._last_failure = failure
595
+ await self._dispose_activation(active.runtime)
596
+ active.closed = True
597
+ raise failure from error
598
+ finally:
599
+ if active.operation_task is task:
600
+ active.operation_task = None
601
+ self._last_failure = None
602
+ return result
603
+
604
+ async def _runtime_adapter_activation(self, active: _ActiveActivation) -> Any:
605
+ async with active.operation_lock:
606
+ if active.closed:
607
+ raise PluginHostError(
608
+ "agent_activation_closed",
609
+ f"Agent activation {active.key!r} is closed",
610
+ )
611
+ provide = getattr(active.runtime, "runtime_adapter", None)
612
+ if not callable(provide):
613
+ raise PluginHostError(
614
+ "agent_provider_runtime_adapter_unavailable",
615
+ "AgentProvider does not expose a Kernel RuntimeAdapter",
616
+ )
617
+ try:
618
+ adapter = provide()
619
+ if asyncio.iscoroutine(adapter):
620
+ adapter = await adapter
621
+ except PluginHostError:
622
+ raise
623
+ except Exception as error: # noqa: BLE001 - provider boundary
624
+ raise PluginHostError(
625
+ "agent_provider_runtime_adapter_failed", str(error)
626
+ ) from error
627
+ return adapter
628
+
629
+ async def _close_activation_record(self, active: _ActiveActivation) -> None:
630
+ await self._finish_cleanup(self._close_activation_record_owned(active))
631
+
632
+ async def _close_activation_record_owned(self, active: _ActiveActivation) -> None:
633
+ """Finish the entire terminal close before propagating caller cancellation."""
634
+
635
+ if active.closed and active.operation_task is None:
636
+ return
637
+ active.closed = True
638
+ operation = active.operation_task
639
+ await self._abort_activation(active.runtime)
640
+ if operation is not None and operation is not asyncio.current_task():
641
+ operation.cancel()
642
+ try:
643
+ await asyncio.wait_for(active.operation_lock.acquire(), timeout=2.0)
644
+ except TimeoutError:
645
+ await self._bounded_dispose_activation(active.runtime)
646
+ return
647
+ try:
648
+ await self._bounded_dispose_activation(active.runtime)
649
+ finally:
650
+ active.operation_lock.release()
651
+
652
+ @staticmethod
653
+ async def _abort_activation(activation: PreparedAgent) -> None:
654
+ """Finish provider revocation before a close can report success.
655
+
656
+ ``abort`` is currently implemented only by the Harness activation and
657
+ revokes activation-scoped MCP credentials. A host-side timeout would
658
+ let close return while those credentials still authorize requests.
659
+ The underlying DSH lifecycle operation owns its network timeout and
660
+ kills the whole generation when revocation cannot be proven.
661
+ """
662
+
663
+ abort = getattr(activation, "abort", None)
664
+ if not callable(abort):
665
+ return
666
+ try:
667
+ result = abort()
668
+ if asyncio.iscoroutine(result):
669
+ await result
670
+ except BaseException: # abort is best-effort; disposal still follows
671
+ pass
672
+
673
+ @classmethod
674
+ async def _bounded_dispose_activation(cls, activation: PreparedAgent) -> None:
675
+ try:
676
+ await asyncio.wait_for(cls._dispose_activation(activation), timeout=2.0)
677
+ except BaseException: # terminal close cannot wait forever on provider code
678
+ pass
679
+
680
+ async def _close_graph_activations(self, graph: _ActiveGraph) -> None:
681
+ selected = [
682
+ (key, active)
683
+ for key, active in tuple(self._activations.items())
684
+ if active.graph is graph
685
+ ]
686
+ if selected:
687
+ await asyncio.gather(
688
+ *(self._close_activation_record(active) for _key, active in selected)
689
+ )
690
+ for key, active in selected:
691
+ if self._activations.get(key) is active:
692
+ self._activations.pop(key, None)
693
+
694
+ async def _close_all_activations(self) -> None:
695
+ selected = tuple(self._activations.items())
696
+ if selected:
697
+ await asyncio.gather(
698
+ *(self._close_activation_record(active) for _key, active in selected)
699
+ )
700
+ for key, active in selected:
701
+ if self._activations.get(key) is active:
702
+ self._activations.pop(key, None)
703
+
704
+ @staticmethod
705
+ def _execution_context(
706
+ graph: _ActiveGraph,
707
+ *,
708
+ activation_key: str = "",
709
+ ) -> PluginExecutionContext:
710
+ bindings = tuple(
711
+ PluginCapabilityBinding(
712
+ plugin_id=plugin.entry.id,
713
+ plugin_version=plugin.entry.version,
714
+ definition=capability.definition,
715
+ slot=capability.slot,
716
+ runtime=plugin.runtime,
717
+ )
718
+ for plugin in graph.plugins
719
+ for capability in plugin.entry.provides
720
+ )
721
+ return PluginExecutionContext(
722
+ profile_digest=graph.resolved.profile_digest,
723
+ plugin_lock_digest=graph.resolved.plugin_lock_digest,
724
+ bindings=bindings,
725
+ activation_key=activation_key,
726
+ )
727
+
728
+ @staticmethod
729
+ def _inventory_for(graph: _ActiveGraph) -> PluginInventory:
730
+ return PluginInventory(
731
+ profile_digest=graph.resolved.profile_digest,
732
+ plugin_lock_digest=graph.resolved.plugin_lock_digest,
733
+ plugins=[
734
+ PluginInventoryItem(
735
+ id=plugin.entry.id,
736
+ version=plugin.entry.version,
737
+ digest=plugin.entry.digest,
738
+ state="ready",
739
+ health="healthy",
740
+ )
741
+ for plugin in graph.plugins
742
+ ],
743
+ )
744
+
745
+
746
+ def _dependency_order(entries: list[PluginLockEntry]) -> list[PluginLockEntry]:
747
+ """Dependency-first deterministic topological order from the locked graph."""
748
+
749
+ by_id = {entry.id: entry for entry in entries}
750
+ visiting: set[str] = set()
751
+ visited: set[str] = set()
752
+ ordered: list[PluginLockEntry] = []
753
+
754
+ def visit(plugin_id: str) -> None:
755
+ if plugin_id in visiting:
756
+ raise PluginHostError("plugin_dependency_cycle", "plugin lock dependency cycle")
757
+ if plugin_id in visited:
758
+ return
759
+ entry = by_id.get(plugin_id)
760
+ if entry is None:
761
+ raise PluginHostError(
762
+ "plugin_dependency_unresolved",
763
+ f"plugin dependency {plugin_id!r} is missing from the lock",
764
+ )
765
+ visiting.add(plugin_id)
766
+ for dependency in sorted(entry.dependencies, key=lambda item: item.id):
767
+ visit(dependency.id)
768
+ visiting.remove(plugin_id)
769
+ visited.add(plugin_id)
770
+ ordered.append(entry)
771
+
772
+ for entry in sorted(entries, key=lambda item: item.id):
773
+ visit(entry.id)
774
+ return ordered
775
+
776
+
777
+ __all__ = [
778
+ "ExecutableAgentProvider",
779
+ "ManagedPlugin",
780
+ "PluginCapabilityBinding",
781
+ "PluginActivationSession",
782
+ "PluginExecutionContext",
783
+ "PluginFactory",
784
+ "PluginHost",
785
+ "PluginHostError",
786
+ "PreparedAgent",
787
+ ]