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
@@ -0,0 +1,180 @@
1
+ """Credential-free resource snapshots consumed by Build activation and workers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ from typing import Literal
8
+ from urllib.parse import urlsplit, urlunsplit
9
+
10
+ from pydantic import Field, field_validator, model_validator
11
+
12
+ from ksadk.plugins.bridges.dsh import DshProfileBuildSnapshot
13
+ from ksadk.plugins.contracts import PluginContractModel
14
+ from ksadk.resource_runtime.contracts import (
15
+ Digest,
16
+ Identifier,
17
+ ResourceConfig,
18
+ validate_resource_bindings,
19
+ )
20
+
21
+
22
+ class ConnectionTarget(PluginContractModel):
23
+ connection_ref: Identifier
24
+ tenant_ref: Identifier
25
+ principal_ref: Identifier
26
+ endpoint: str
27
+ auth_mode: Literal["signed", "sts", "token"]
28
+
29
+ @field_validator("endpoint")
30
+ @classmethod
31
+ def canonical_endpoint(cls, value: str) -> str:
32
+ if any(char.isspace() for char in value) or "\\" in value:
33
+ raise ValueError("Invalid resource endpoint")
34
+ url = urlsplit(value)
35
+ if (
36
+ url.scheme not in {"http", "https"}
37
+ or not url.hostname
38
+ or url.username is not None
39
+ or url.password is not None
40
+ or url.query
41
+ or url.fragment
42
+ or "%" in url.hostname
43
+ ):
44
+ raise ValueError("Resource endpoint must be an explicit HTTP service URL")
45
+ port = url.port # validates port range and syntax
46
+ host = url.hostname.encode("idna").decode("ascii").lower()
47
+ if ":" in host:
48
+ host = f"[{host}]"
49
+ if port is not None and (url.scheme, port) not in {("http", 80), ("https", 443)}:
50
+ host += f":{port}"
51
+ return urlunsplit((url.scheme, host, url.path.rstrip("/"), "", ""))
52
+
53
+
54
+ class SkillExecutionTarget(PluginContractModel):
55
+ backend: Literal["e2b"] = "e2b"
56
+ connection: ConnectionTarget
57
+ domain: str = Field(strict=True, pattern=r"^[a-zA-Z0-9]+(?:[.-][a-zA-Z0-9-]+)*$")
58
+ template_id: Identifier
59
+ timeout: int = Field(default=900, strict=True, ge=1, le=900)
60
+ allow_internet_access: bool = Field(default=False, strict=True)
61
+
62
+ @model_validator(mode="after")
63
+ def explicit_target(self):
64
+ url = urlsplit(self.connection.endpoint)
65
+ if self.connection.auth_mode != "token" or url.scheme != "https" or url.path:
66
+ raise ValueError("Skill execution requires an explicit HTTPS token connection")
67
+ return self
68
+
69
+
70
+ class MemoryRecallPolicy(PluginContractModel):
71
+ """Frozen projection of Agent memory recall limits, never a second draft config."""
72
+
73
+ top_k: int = Field(default=8, strict=True, ge=1, le=64)
74
+ max_tokens: int = Field(default=1600, strict=True, ge=0, le=100000)
75
+ min_score: float = Field(default=0, strict=True, ge=0, le=1)
76
+
77
+ @model_validator(mode="after")
78
+ def supported_score(self):
79
+ if self.min_score != 0:
80
+ raise ValueError(
81
+ "MEMORY_SEARCH_POLICY_UNSUPPORTED: AICP score threshold is unavailable"
82
+ )
83
+ return self
84
+
85
+
86
+ class FrozenResourceBinding(PluginContractModel):
87
+ config: ResourceConfig
88
+ connection: ConnectionTarget
89
+ # The connection target deliberately contains no credential references.
90
+ # Freeze the repository revision separately so rotating those references
91
+ # cannot make an old Build silently consume a different credential set.
92
+ connection_revision: int = Field(default=1, strict=True, ge=1)
93
+ skill_execution: SkillExecutionTarget | None = None
94
+ memory_recall: MemoryRecallPolicy | None = None
95
+
96
+ @model_validator(mode="after")
97
+ def matching_connection(self) -> FrozenResourceBinding:
98
+ if self.config.binding.connection_ref != self.connection.connection_ref:
99
+ raise ValueError("Resource binding and connection reference do not match")
100
+ if (
101
+ self.memory_recall is not None
102
+ and self.config.binding.resource.kind != "memory-instance"
103
+ ):
104
+ raise ValueError("Memory recall policy requires a memory binding")
105
+ if self.skill_execution is not None and (
106
+ self.config.binding.resource.kind != "skill-space"
107
+ or self.config.execution_mode != "isolated"
108
+ or self.skill_execution.connection.tenant_ref != self.connection.tenant_ref
109
+ ):
110
+ raise ValueError("Skill execution target requires an isolated Skill in the same tenant")
111
+ return self
112
+
113
+
114
+ class ResourceSnapshot(PluginContractModel):
115
+ schema_version: Literal[1] = 1
116
+ plugin_lock_digest: Digest
117
+ bindings: tuple[FrozenResourceBinding, ...]
118
+ # Older standalone Worker fixtures may omit this. Studio Build/activation
119
+ # requires the actual host snapshot, bound into the resource digest below.
120
+ dsh_profile: DshProfileBuildSnapshot | None = None
121
+
122
+ @field_validator("schema_version", mode="before")
123
+ @classmethod
124
+ def strict_version(cls, value: object) -> object:
125
+ if type(value) is not int:
126
+ raise ValueError("Resource snapshot version must be an integer")
127
+ return value
128
+
129
+ @model_validator(mode="after")
130
+ def unique_bindings(self) -> ResourceSnapshot:
131
+ validate_resource_bindings(tuple(binding.config for binding in self.bindings))
132
+ return self
133
+
134
+ @property
135
+ def digest(self) -> str:
136
+ payload = {
137
+ "schemaVersion": self.schema_version,
138
+ "pluginLockDigest": self.plugin_lock_digest,
139
+ **({"dshProfileDigest": self.dsh_profile.digest} if self.dsh_profile else {}),
140
+ "bindings": [
141
+ {
142
+ "config": json.loads(binding.config.canonical_bytes()),
143
+ "connection": binding.connection.model_dump(by_alias=True, mode="json"),
144
+ "connectionRevision": binding.connection_revision,
145
+ **(
146
+ {
147
+ "memoryRecall": binding.memory_recall.model_dump(
148
+ by_alias=True, mode="json"
149
+ )
150
+ }
151
+ if binding.memory_recall is not None
152
+ else {}
153
+ ),
154
+ **(
155
+ {
156
+ "skillExecution": binding.skill_execution.model_dump(
157
+ by_alias=True, mode="json"
158
+ )
159
+ }
160
+ if binding.skill_execution is not None
161
+ else {}
162
+ ),
163
+ }
164
+ for binding in sorted(self.bindings, key=lambda item: item.config.binding.id)
165
+ ],
166
+ }
167
+ raw = json.dumps(
168
+ payload, ensure_ascii=False, sort_keys=True, separators=(",", ":"), allow_nan=False
169
+ ).encode("utf-8")
170
+ return "sha256:" + hashlib.sha256(raw).hexdigest()
171
+
172
+ def binding(self, binding_id: str) -> FrozenResourceBinding:
173
+ for binding in self.bindings:
174
+ if binding.config.binding.id == binding_id:
175
+ return binding
176
+ raise ValueError("RESOURCE_BINDING_NOT_IN_BUILD")
177
+
178
+ def verify_connection(self, binding_id: str, current: ConnectionTarget) -> None:
179
+ if self.binding(binding_id).connection != current:
180
+ raise ValueError("RESOURCE_CONNECTION_CHANGED")
@@ -0,0 +1,103 @@
1
+ """Private Unix socket ingress for the existing host's resource broker."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import os
7
+ import struct
8
+ import tempfile
9
+ from pathlib import Path
10
+
11
+ from ksadk.resource_runtime.broker import ResourceBroker
12
+ from ksadk.resource_runtime.ipc import MAX_FRAME_BYTES, FrameError, decode_body, encode_frame
13
+
14
+
15
+ class ResourceSocketServer:
16
+ def __init__(self, broker: ResourceBroker, *, max_connections: int = 64):
17
+ if type(max_connections) is not int or not 1 <= max_connections <= 1024:
18
+ raise ValueError("Socket connection limit must be 1..1024")
19
+ self._broker = broker
20
+ self._max_connections = max_connections
21
+ self._directory: tempfile.TemporaryDirectory | None = None
22
+ self._server: asyncio.AbstractServer | None = None
23
+ self._clients: set[asyncio.Task] = set()
24
+ self._closing = False
25
+ self.path: Path | None = None
26
+
27
+ async def start(self) -> Path:
28
+ if os.name != "posix":
29
+ raise RuntimeError("RESOURCE_IPC_UNSUPPORTED")
30
+ if self._directory is not None or self._closing:
31
+ raise RuntimeError("Resource socket server cannot be restarted")
32
+ directory = tempfile.TemporaryDirectory(prefix="ksr-")
33
+ self._directory = directory
34
+ self.path = Path(directory.name) / "broker.sock"
35
+ try:
36
+ os.chmod(directory.name, 0o700)
37
+ # Private parent directory prevents access during the bind/chmod gap.
38
+ self._server = await asyncio.start_unix_server(self._accept, path=str(self.path))
39
+ os.chmod(self.path, 0o600)
40
+ return self.path
41
+ except BaseException:
42
+ await self.aclose()
43
+ raise
44
+
45
+ async def _accept(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None:
46
+ task = asyncio.current_task()
47
+ assert task is not None
48
+ if self._closing or len(self._clients) >= self._max_connections:
49
+ writer.close()
50
+ await writer.wait_closed()
51
+ return
52
+ self._clients.add(task)
53
+ try:
54
+ while not self._closing:
55
+ payload = await asyncio.wait_for(self._read(reader), 15)
56
+ if payload is None:
57
+ return
58
+ response = await self._broker.dispatch(payload)
59
+ writer.write(encode_frame(response))
60
+ await asyncio.wait_for(writer.drain(), 5)
61
+ except (
62
+ FrameError,
63
+ asyncio.TimeoutError,
64
+ asyncio.IncompleteReadError,
65
+ ConnectionError,
66
+ OSError,
67
+ ):
68
+ # Closing rejects malformed/slow ingress; never echo raw input.
69
+ pass
70
+ finally:
71
+ self._clients.discard(task)
72
+ writer.close()
73
+ try:
74
+ await writer.wait_closed()
75
+ except (ConnectionError, OSError):
76
+ pass
77
+
78
+ @staticmethod
79
+ async def _read(reader: asyncio.StreamReader) -> dict | None:
80
+ try:
81
+ prefix = await reader.readexactly(4)
82
+ except asyncio.IncompleteReadError as exc:
83
+ if not exc.partial:
84
+ return None
85
+ raise
86
+ (size,) = struct.unpack("!I", prefix)
87
+ if not 0 < size <= MAX_FRAME_BYTES:
88
+ raise FrameError("Invalid IPC frame length")
89
+ return decode_body(await reader.readexactly(size))
90
+
91
+ async def aclose(self) -> None:
92
+ self._closing = True
93
+ if self._server is not None:
94
+ self._server.close()
95
+ await self._server.wait_closed()
96
+ self._broker.revoke_generation()
97
+ clients = tuple(self._clients)
98
+ for task in clients:
99
+ task.cancel()
100
+ if clients:
101
+ await asyncio.gather(*clients, return_exceptions=True)
102
+ if self._directory is not None:
103
+ self._directory.cleanup()
@@ -0,0 +1,380 @@
1
+ """Generation-owned resource lifecycle for trusted Studio/runtime adapters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from collections.abc import Awaitable, Callable
7
+ from dataclasses import dataclass, field
8
+ from datetime import datetime, timezone
9
+ from pathlib import Path
10
+
11
+ from ksadk.resource_runtime.broker import ResourceBroker, ResourceWriteAuthorizer
12
+ from ksadk.resource_runtime.discovery_receipts import (
13
+ DiscoverySelectionReceipts,
14
+ discovery_scope_key,
15
+ )
16
+ from ksadk.resource_runtime.ipc import ResourceRequest
17
+ from ksadk.resource_runtime.leases import (
18
+ LeaseRejected,
19
+ ResourceLease,
20
+ ResourceLeaseRegistry,
21
+ ResourceScope,
22
+ )
23
+ from ksadk.resource_runtime.operation_ledger import OperationLedger
24
+ from ksadk.resource_runtime.process import ResourceWorkerProcess
25
+ from ksadk.resource_runtime.socket_server import ResourceSocketServer
26
+ from ksadk.resource_runtime.worker import DiscoverySkillWorkerBinding, WorkerInitialization
27
+
28
+ ResourceRevalidator = Callable[[tuple[ResourceScope, ...]], Awaitable[bool]]
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class ActiveResources:
33
+ activation_id: str
34
+ socket_path: Path
35
+ leases: tuple[ResourceLease, ...] = field(repr=False)
36
+ worker_pid: int
37
+
38
+
39
+ @dataclass
40
+ class _Running:
41
+ worker: ResourceWorkerProcess
42
+ resources: ActiveResources
43
+ lease_changed: asyncio.Event = field(default_factory=asyncio.Event)
44
+
45
+
46
+ class _ActivationApprovals:
47
+ """Dispatch only to the approval owner admitted for this exact activation."""
48
+
49
+ def __init__(self):
50
+ self.owners: dict[str, tuple[tuple[ResourceScope, ...], ResourceWriteAuthorizer]] = {}
51
+
52
+ def register(self, scopes: tuple[ResourceScope, ...], owner: ResourceWriteAuthorizer) -> None:
53
+ activation_id = scopes[0].activation_id
54
+ if activation_id in self.owners:
55
+ raise ValueError("RESOURCE_APPROVAL_OWNER_IMMUTABLE")
56
+ self.owners[activation_id] = (scopes, owner)
57
+
58
+ def revoke(self, activation_id: str) -> None:
59
+ self.owners.pop(activation_id, None)
60
+
61
+ async def authorize(self, request: ResourceRequest, scope: ResourceScope) -> str | None:
62
+ admitted = self.owners.get(scope.activation_id)
63
+ if admitted is None or scope not in admitted[0]:
64
+ return None
65
+ event_id = await admitted[1].authorize(request, scope)
66
+ # An approval may finish after the run was stopped. Do not revive it.
67
+ return event_id if self.owners.get(scope.activation_id) is admitted else None
68
+
69
+
70
+ class ResourceSupervisor:
71
+ """One owner per Core generation, with one worker per activation.
72
+
73
+ Admission and real credential/principal verification precede activate().
74
+ This class never derives user identity from tool arguments, reads credential
75
+ environment variables, restarts failed activations or replays requests.
76
+ """
77
+
78
+ def __init__(
79
+ self,
80
+ generation_id: str,
81
+ *,
82
+ max_workers: int = 32,
83
+ write_authorizer: ResourceWriteAuthorizer | None = None,
84
+ operation_ledger: OperationLedger | None = None,
85
+ ):
86
+ if type(max_workers) is not int or not 1 <= max_workers <= 128:
87
+ raise ValueError("Resource worker limit must be 1..128")
88
+ self.generation_id = generation_id
89
+ self._max_workers = max_workers
90
+ if write_authorizer is not None and operation_ledger is None:
91
+ raise ValueError("Write approval requires a durable operation ledger")
92
+ self._default_write_authorizer = write_authorizer
93
+ self._has_operation_ledger = operation_ledger is not None
94
+ self._discovery_receipts = (
95
+ DiscoverySelectionReceipts(operation_ledger) if operation_ledger is not None else None
96
+ )
97
+ self._approvals = _ActivationApprovals()
98
+ self._registry = ResourceLeaseRegistry()
99
+ self._broker = ResourceBroker(
100
+ self._registry,
101
+ generation_id,
102
+ write_authorizer=self._approvals if operation_ledger is not None else None,
103
+ operation_ledger=operation_ledger,
104
+ )
105
+ self._socket = ResourceSocketServer(self._broker)
106
+ self._lock = asyncio.Lock()
107
+ self._running: dict[str, _Running] = {}
108
+ self._used: set[str] = set()
109
+ self._monitors: set[asyncio.Task] = set()
110
+ self._closed = False
111
+
112
+ async def start_broker(self) -> Path:
113
+ """Prepare private ingress before Core startup, without workers or grants."""
114
+ async with self._lock:
115
+ return await self._start_broker_locked()
116
+
117
+ async def _start_broker_locked(self) -> Path:
118
+ if self._closed:
119
+ raise RuntimeError("RESOURCE_SUPERVISOR_CLOSED")
120
+ if self._socket.path is None:
121
+ try:
122
+ await self._socket.start()
123
+ except BaseException:
124
+ self._closed = True
125
+ raise
126
+ assert self._socket.path is not None
127
+ return self._socket.path
128
+
129
+ async def activate(
130
+ self,
131
+ initialization: WorkerInitialization,
132
+ *,
133
+ write_authorizer: ResourceWriteAuthorizer | None = None,
134
+ ) -> ActiveResources:
135
+ # Revalidate even models assembled via unchecked model_copy/model_construct.
136
+ initialization = WorkerInitialization.model_validate(initialization.pipe_payload())
137
+ discovery_keys = {}
138
+ restored_bindings = list(initialization.bindings)
139
+ for index, binding in enumerate(initialization.bindings):
140
+ if isinstance(binding, DiscoverySkillWorkerBinding):
141
+ if self._discovery_receipts is None:
142
+ raise ValueError("RESOURCE_DISCOVERY_RECEIPTS_REQUIRED")
143
+ binding_scope = next(
144
+ item for item in initialization.scopes
145
+ if item.binding_id == binding.config.binding.id
146
+ )
147
+ key = discovery_scope_key(binding_scope, binding.selection_run_ref)
148
+ discovery_keys[binding_scope.binding_id] = key
149
+ restored = await asyncio.to_thread(self._discovery_receipts.read, key)
150
+ # Only host ledger contents may restore selections. Ignore caller
151
+ # supplied preloads at this public lifecycle entry.
152
+ restored_bindings[index] = binding.model_copy(
153
+ update={"restored_selections": restored}
154
+ )
155
+ initialization = initialization.model_copy(update={"bindings": tuple(restored_bindings)})
156
+ scope = initialization.scopes[0]
157
+ owner = write_authorizer if write_authorizer is not None else self._default_write_authorizer
158
+ if owner is not None and not self._has_operation_ledger:
159
+ raise ValueError("Write approval requires a durable operation ledger")
160
+ if scope.generation_id != self.generation_id:
161
+ raise ValueError("Resource activation belongs to another generation")
162
+ async with self._lock:
163
+ if self._closed:
164
+ raise RuntimeError("RESOURCE_SUPERVISOR_CLOSED")
165
+ if scope.activation_id in self._used:
166
+ raise ValueError("RESOURCE_ACTIVATION_ALREADY_USED")
167
+ if len(self._used) >= 4096:
168
+ raise RuntimeError("RESOURCE_GENERATION_CAPACITY")
169
+ if len(self._running) >= self._max_workers:
170
+ raise RuntimeError("RESOURCE_WORKER_CAPACITY")
171
+ await self._start_broker_locked()
172
+ self._used.add(scope.activation_id)
173
+ worker = None
174
+ try:
175
+ if owner is not None:
176
+ self._approvals.register(initialization.scopes, owner)
177
+ worker = await ResourceWorkerProcess.start(initialization)
178
+ leases = []
179
+ for binding_scope in initialization.scopes:
180
+ binding = next(
181
+ item
182
+ for item in initialization.bindings
183
+ if item.config.binding.id == binding_scope.binding_id
184
+ )
185
+ self._broker.register(
186
+ binding_scope,
187
+ worker,
188
+ artifact_root=getattr(binding, "artifact_directory", None),
189
+ discovery_key=discovery_keys.get(binding_scope.binding_id),
190
+ )
191
+ leases.append(self._registry.issue(binding_scope))
192
+ assert self._socket.path is not None
193
+ resources = ActiveResources(
194
+ scope.activation_id, self._socket.path, tuple(leases), worker.pid
195
+ )
196
+ self._running[scope.activation_id] = _Running(worker, resources)
197
+ monitor = asyncio.create_task(self._monitor(scope.activation_id, worker))
198
+ self._monitors.add(monitor)
199
+ monitor.add_done_callback(self._monitors.discard)
200
+ return resources
201
+ except BaseException:
202
+ self._approvals.revoke(scope.activation_id)
203
+ self._broker.revoke_activation(scope.activation_id)
204
+ if worker is not None:
205
+ await worker.aclose()
206
+ await self._broker.retire_activation(scope.activation_id)
207
+ raise
208
+
209
+ async def deactivate(self, activation_id: str) -> None:
210
+ async with self._lock:
211
+ await self._deactivate_locked(activation_id)
212
+
213
+ async def owns(self, current: ActiveResources) -> bool:
214
+ """Confirm an opaque activation handle still names this live generation."""
215
+
216
+ async with self._lock:
217
+ running = self._running.get(current.activation_id)
218
+ return (
219
+ not self._closed
220
+ and running is not None
221
+ and running.resources is current
222
+ and running.worker.is_running
223
+ )
224
+
225
+ async def renew(
226
+ self,
227
+ current: ActiveResources,
228
+ *,
229
+ revalidate: ResourceRevalidator,
230
+ lifetime: int = 600,
231
+ ) -> ActiveResources:
232
+ """Host-only renewal after fresh upstream permission checks.
233
+
234
+ The caller replaces its connector with the returned handles at a safe
235
+ turn boundary. No model operation, automatic timer, or default grant is
236
+ installed here. The verifier must check every supplied binding scope.
237
+ """
238
+ if type(lifetime) is not int or not 1 <= lifetime <= 600:
239
+ raise ValueError("Resource lease lifetime must be 1..600 seconds")
240
+ async with self._lock:
241
+ running = self._running.get(current.activation_id)
242
+ if (
243
+ self._closed
244
+ or running is None
245
+ or running.resources is not current
246
+ or not running.worker.is_running
247
+ ):
248
+ raise ValueError("RESOURCE_RENEWAL_STALE")
249
+ scopes = tuple(
250
+ ResourceScope.model_validate(lease.scope.model_dump()) for lease in current.leases
251
+ )
252
+ # Do not block immediate deactivation while checking the platform.
253
+ try:
254
+ if await asyncio.wait_for(revalidate(scopes), timeout=15) is not True:
255
+ raise PermissionError("RESOURCE_RENEWAL_DENIED")
256
+ except BaseException:
257
+ async with self._lock:
258
+ latest = self._running.get(current.activation_id)
259
+ if latest is running and latest.resources is current:
260
+ await self._deactivate_locked(current.activation_id)
261
+ raise
262
+ async with self._lock:
263
+ if (
264
+ self._closed
265
+ or self._running.get(current.activation_id) is not running
266
+ or running.resources is not current
267
+ or not running.worker.is_running
268
+ ):
269
+ raise ValueError("RESOURCE_RENEWAL_STALE")
270
+ try:
271
+ leases = self._registry.renew_many(
272
+ tuple(lease.handle for lease in current.leases),
273
+ lifetime=lifetime,
274
+ )
275
+ except BaseException:
276
+ await self._deactivate_locked(current.activation_id)
277
+ raise
278
+ renewed = ActiveResources(
279
+ current.activation_id, current.socket_path, leases, current.worker_pid
280
+ )
281
+ running.resources = renewed
282
+ running.lease_changed.set()
283
+ return renewed
284
+
285
+ async def runtime_status(self, *, agent_id: str, activation_id: str) -> dict | None:
286
+ """Observe this live activation without issuing leases or probing upstream.
287
+
288
+ Unknown and differently owned activations are indistinguishable. This is
289
+ transport availability, not proof that current upstream grants are valid.
290
+ """
291
+ async with self._lock:
292
+ running = self._running.get(activation_id)
293
+ if running is None:
294
+ return None
295
+ scopes = [lease.scope for lease in running.resources.leases]
296
+ if any(scope.identity.agent_id != agent_id for scope in scopes):
297
+ return None
298
+ items = []
299
+ for lease in running.resources.leases:
300
+ available = running.worker.is_running and not self._closed
301
+ try:
302
+ self._registry.authorize(
303
+ lease.handle,
304
+ operation=lease.scope.allowed_operations[0],
305
+ generation_id=self.generation_id,
306
+ activation_id=activation_id,
307
+ )
308
+ except LeaseRejected:
309
+ available = False
310
+ items.append(
311
+ {
312
+ "bindingId": lease.scope.binding_id,
313
+ "runtimeState": "available" if available else "unavailable",
314
+ "allowedOperations": list(lease.scope.allowed_operations)
315
+ if available
316
+ else [],
317
+ }
318
+ )
319
+ first = scopes[0]
320
+ return {
321
+ "agentId": agent_id,
322
+ "activationId": activation_id,
323
+ "generationId": self.generation_id,
324
+ "buildDigest": first.build_digest,
325
+ "bindingSnapshotDigest": first.binding_snapshot_digest,
326
+ "observedAt": datetime.now(timezone.utc).isoformat(),
327
+ "upstreamVerification": "not-observed",
328
+ "items": items,
329
+ }
330
+
331
+ async def _deactivate_locked(self, activation_id: str) -> None:
332
+ self._approvals.revoke(activation_id)
333
+ self._broker.revoke_activation(activation_id)
334
+ running = self._running.pop(activation_id, None)
335
+ if running is not None:
336
+ await running.worker.aclose()
337
+ await self._broker.retire_activation(activation_id)
338
+
339
+ async def _monitor(self, activation_id: str, worker: ResourceWorkerProcess) -> None:
340
+ stopped = asyncio.create_task(worker.wait_stopped())
341
+ try:
342
+ while True:
343
+ async with self._lock:
344
+ running = self._running.get(activation_id)
345
+ if running is None or running.worker is not worker:
346
+ return
347
+ remaining = self._registry.remaining_lifetime(
348
+ tuple(lease.handle for lease in running.resources.leases)
349
+ )
350
+ if stopped.done() or remaining <= 0:
351
+ await self._deactivate_locked(activation_id)
352
+ return
353
+ # Read current leases and clear under the same lock as renew.
354
+ # An old expiry wakeup never revokes a successfully renewed run.
355
+ running.lease_changed.clear()
356
+ changed = asyncio.create_task(running.lease_changed.wait())
357
+ try:
358
+ # Also notice complete binding revocation without another model
359
+ # request. This timer cannot refresh credentials or issue leases.
360
+ await asyncio.wait(
361
+ (stopped, changed), timeout=min(remaining, 30.0),
362
+ return_when=asyncio.FIRST_COMPLETED,
363
+ )
364
+ finally:
365
+ changed.cancel()
366
+ await asyncio.gather(changed, return_exceptions=True)
367
+ finally:
368
+ if not stopped.done():
369
+ stopped.cancel()
370
+ await asyncio.gather(stopped, return_exceptions=True)
371
+
372
+ async def aclose(self) -> None:
373
+ async with self._lock:
374
+ self._closed = True
375
+ await self._socket.aclose()
376
+ for activation_id in tuple(self._running):
377
+ await self._deactivate_locked(activation_id)
378
+ # Monitors may be waiting on the supervisor lock, so join after releasing it.
379
+ if self._monitors:
380
+ await asyncio.gather(*tuple(self._monitors), return_exceptions=True)