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,616 @@
1
+ """Resource dispatch admission; transport and subprocess ownership stay separate."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import hashlib
7
+ import json
8
+ import time
9
+ from collections.abc import Callable
10
+ from dataclasses import dataclass, field
11
+ from pathlib import Path
12
+ from typing import Protocol
13
+
14
+ from pydantic import ValidationError
15
+
16
+ from ksadk.resource_runtime.discovery_receipts import (
17
+ DiscoverySelectionReceipts,
18
+ DiscoverySkillReceipt,
19
+ )
20
+ from ksadk.resource_runtime.ipc import FrameError, ResourceRequest, encode_frame
21
+ from ksadk.resource_runtime.knowledge import KnowledgeQuery
22
+ from ksadk.resource_runtime.leases import LeaseRejected, ResourceLeaseRegistry, ResourceScope
23
+ from ksadk.resource_runtime.memory_provider import (
24
+ MemoryQuery,
25
+ MemoryRecordSelector,
26
+ MemoryStatusQuery,
27
+ MemoryUpdate,
28
+ MemoryWrite,
29
+ )
30
+ from ksadk.resource_runtime.memory_receipts import MemoryMutationReceipt
31
+ from ksadk.resource_runtime.operation_ledger import OperationConflict, OperationLedger
32
+ from ksadk.resource_runtime.skill_artifacts import SkillArtifactQuery, SkillArtifactReceipts
33
+ from ksadk.resource_runtime.skills import SkillExecutionQuery
34
+
35
+
36
+ class ResourceWorkerPort(Protocol):
37
+ async def invoke(self, request: ResourceRequest, scope: ResourceScope) -> dict: ...
38
+
39
+
40
+ class ResourceWriteAuthorizer(Protocol):
41
+ async def authorize(self, request: ResourceRequest, scope: ResourceScope) -> str | None:
42
+ """Resolve a host approval bound to exact arguments and return its stable event ID.
43
+
44
+ The implementation must validate the request schema and host minimum policy,
45
+ and look up approval in trusted state. IPC arguments are never approval.
46
+ Return None to deny. The event ID must survive activation/checkpoint recovery.
47
+ """
48
+ ...
49
+
50
+
51
+ @dataclass
52
+ class _Activation:
53
+ worker: ResourceWorkerPort
54
+ scopes: dict[str, ResourceScope]
55
+ tasks: set[asyncio.Task] = field(default_factory=set)
56
+ closed: bool = False
57
+ execution_lock: asyncio.Lock = field(default_factory=asyncio.Lock)
58
+ artifact_roots: dict[str, Path] = field(default_factory=dict)
59
+ discovery_keys: dict[str, str] = field(default_factory=dict)
60
+
61
+
62
+ _WRITES = frozenset({"save_memory", "update_memory", "delete_memory", "execute_skills"})
63
+
64
+
65
+ class ResourceBroker:
66
+ """One event-loop-owned dispatcher for a Core generation.
67
+
68
+ Registration is host-only. The worker receives identity resolved by the
69
+ registry; IPC callers cannot register workers, set identity or mint handles.
70
+ Write dispatch remains closed until the Kernel approval/receipt adapter is
71
+ installed; a scope alone is never approval for side effects.
72
+ """
73
+
74
+ def __init__(
75
+ self,
76
+ registry: ResourceLeaseRegistry,
77
+ generation_id: str,
78
+ *,
79
+ clock: Callable[[], float] = time.time,
80
+ max_inflight: int = 8,
81
+ write_authorizer: ResourceWriteAuthorizer | None = None,
82
+ operation_ledger: OperationLedger | None = None,
83
+ ):
84
+ if type(max_inflight) is not int or not 1 <= max_inflight <= 8:
85
+ raise ValueError("Resource concurrency must be 1..8")
86
+ self._registry = registry
87
+ self._generation_id = generation_id
88
+ self._clock = clock
89
+ self._max_inflight = max_inflight
90
+ if (write_authorizer is None) != (operation_ledger is None):
91
+ raise ValueError("Write authorization and durable ledger must be configured together")
92
+ self._write_authorizer = write_authorizer
93
+ self._operation_ledger = operation_ledger
94
+ self._discovery_receipts = (
95
+ DiscoverySelectionReceipts(operation_ledger) if operation_ledger is not None else None
96
+ )
97
+ self._skill_artifacts = (
98
+ SkillArtifactReceipts(operation_ledger) if operation_ledger is not None else None
99
+ )
100
+ self._activations: dict[str, _Activation] = {}
101
+
102
+ def register(
103
+ self,
104
+ scope: ResourceScope,
105
+ worker: ResourceWorkerPort,
106
+ *,
107
+ artifact_root: Path | None = None,
108
+ discovery_key: str | None = None,
109
+ ) -> None:
110
+ if discovery_key is not None:
111
+ if self._discovery_receipts is None:
112
+ raise ValueError("RESOURCE_DISCOVERY_RECEIPTS_REQUIRED")
113
+ DiscoverySelectionReceipts._key(discovery_key)
114
+ if artifact_root is not None:
115
+ if not artifact_root.is_absolute():
116
+ raise ValueError("Artifact publication requires an absolute host root")
117
+ artifact_root = artifact_root.resolve()
118
+ if scope.generation_id != self._generation_id:
119
+ raise ValueError("Worker generation does not match broker")
120
+ existing = self._activations.get(scope.activation_id)
121
+ if existing is None:
122
+ if any(item.worker is worker for item in self._activations.values()):
123
+ raise ValueError("A resource worker cannot serve multiple activations")
124
+ self._activations[scope.activation_id] = _Activation(worker, {scope.binding_id: scope})
125
+ if artifact_root is not None:
126
+ self._activations[scope.activation_id].artifact_roots[scope.binding_id] = (
127
+ artifact_root
128
+ )
129
+ if discovery_key is not None:
130
+ self._activations[scope.activation_id].discovery_keys[scope.binding_id] = (
131
+ discovery_key
132
+ )
133
+ return
134
+ first = next(iter(existing.scopes.values()))
135
+ if (
136
+ existing.closed
137
+ or existing.worker is not worker
138
+ or first.identity != scope.identity
139
+ or first.build_digest != scope.build_digest
140
+ or first.profile_digest != scope.profile_digest
141
+ or first.binding_snapshot_digest != scope.binding_snapshot_digest
142
+ ):
143
+ raise ValueError("Worker activation identity and Build are immutable")
144
+ if scope.binding_id in existing.scopes and existing.scopes[scope.binding_id] != scope:
145
+ raise ValueError("Worker binding registration is immutable")
146
+ if scope.binding_id in existing.scopes and existing.discovery_keys.get(
147
+ scope.binding_id
148
+ ) != discovery_key:
149
+ raise ValueError("Worker discovery run is immutable")
150
+ if (
151
+ scope.binding_id in existing.scopes
152
+ and existing.artifact_roots.get(scope.binding_id) != artifact_root
153
+ ):
154
+ raise ValueError("Worker artifact publication root is immutable")
155
+ existing.scopes[scope.binding_id] = scope
156
+ if artifact_root is not None:
157
+ existing.artifact_roots[scope.binding_id] = artifact_root
158
+ if discovery_key is not None:
159
+ existing.discovery_keys[scope.binding_id] = discovery_key
160
+
161
+ async def dispatch(self, payload: dict) -> dict:
162
+ try:
163
+ frame = encode_frame(payload)
164
+ request = ResourceRequest.model_validate_json(frame[4:])
165
+ except (ValidationError, FrameError):
166
+ return self._error("RESOURCE_REQUEST_INVALID")
167
+ try:
168
+ scope = self._registry.resolve(
169
+ request.handle, operation=request.operation, generation_id=self._generation_id
170
+ )
171
+ except LeaseRejected:
172
+ return self._error("RESOURCE_SCOPE_INVALID", request.request_id)
173
+ activation = self._activations.get(scope.activation_id)
174
+ if (
175
+ activation is None
176
+ or activation.closed
177
+ or activation.scopes.get(scope.binding_id) != scope
178
+ ):
179
+ return self._error("RESOURCE_ACTIVATION_UNAVAILABLE", request.request_id)
180
+ remaining = request.deadline / 1000 - self._clock()
181
+ if remaining <= 0:
182
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
183
+ if request.check_only:
184
+ if request.arguments:
185
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
186
+ if getattr(activation.worker, "is_running", True) is False:
187
+ return self._error("RESOURCE_ACTIVATION_UNAVAILABLE", request.request_id)
188
+ # Inventory checks prove local lease admission only. They neither
189
+ # call upstream nor claim a write, authorize approval, or renew leases.
190
+ return {"v": 1, "requestId": request.request_id, "result": {"available": True}}
191
+ if request.operation in _WRITES and self._write_authorizer is None:
192
+ return self._error("RESOURCE_APPROVAL_REQUIRED", request.request_id)
193
+ if request.operation == "search_knowledge_base":
194
+ try:
195
+ KnowledgeQuery.model_validate(request.arguments)
196
+ except ValidationError:
197
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
198
+ if request.operation == "load_memory":
199
+ try:
200
+ MemoryQuery.model_validate(request.arguments)
201
+ except ValidationError:
202
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
203
+ if request.operation == "save_memory":
204
+ try:
205
+ parsed = MemoryWrite.model_validate(request.arguments)
206
+ if not parsed.content.strip():
207
+ raise ValueError("Empty memory content")
208
+ except ValueError:
209
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
210
+ if request.operation == "memory_status":
211
+ try:
212
+ MemoryStatusQuery.model_validate(request.arguments)
213
+ except ValueError:
214
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
215
+ if request.operation in {"update_memory", "delete_memory"}:
216
+ try:
217
+ if request.operation == "update_memory":
218
+ if not MemoryUpdate.model_validate(request.arguments).content.strip():
219
+ raise ValueError("Empty memory content")
220
+ else:
221
+ MemoryRecordSelector.model_validate(request.arguments)
222
+ except ValueError:
223
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
224
+ if request.operation == "execute_skills":
225
+ try:
226
+ query = SkillExecutionQuery.model_validate(request.arguments)
227
+ if not query.workflow_prompt.strip():
228
+ raise ValueError("Empty workflow")
229
+ except ValueError:
230
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
231
+ if scope.binding_id not in activation.artifact_roots:
232
+ return self._error("RESOURCE_ARTIFACT_DELIVERY_REQUIRED", request.request_id)
233
+ if request.operation == "read_skill_artifact":
234
+ try:
235
+ SkillArtifactQuery.model_validate(request.arguments)
236
+ except ValueError:
237
+ return self._error("RESOURCE_ARGUMENTS_INVALID", request.request_id)
238
+ if self._skill_artifacts is None:
239
+ return self._error("RESOURCE_OPERATION_NOT_FOUND", request.request_id)
240
+ # The ingress cannot extend worker execution indefinitely with a distant
241
+ # deadline. Bound both the wait and the deadline sent into the subprocess.
242
+ remaining = min(remaining, 900.0 if request.operation == "execute_skills" else 60.0)
243
+ request = request.model_copy(
244
+ update={"deadline": min(request.deadline, int((self._clock() + remaining) * 1000))}
245
+ )
246
+ if len(activation.tasks) >= self._max_inflight:
247
+ return self._error("RESOURCE_BUSY", request.request_id)
248
+ # No await between admission and recording the task. Recheck immediately
249
+ # before the worker call so a queued task cannot bypass revocation.
250
+ task = asyncio.create_task(self._invoke(activation, request, scope))
251
+ activation.tasks.add(task)
252
+ task.add_done_callback(activation.tasks.discard)
253
+ # A timeout or disconnected caller must not cancel a possibly sent write.
254
+ # Only the lifecycle owner cancels these tasks after revocation and Worker
255
+ # shutdown. wait() distinguishes that child cancellation from cancellation
256
+ # of this caller, which must still propagate to the transport/engine.
257
+ done, _ = await asyncio.wait((task,), timeout=remaining)
258
+ if not done:
259
+ if request.operation in _WRITES:
260
+ return self._error("RESOURCE_WRITE_UNKNOWN", request.request_id)
261
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
262
+ if task.cancelled():
263
+ if not activation.closed:
264
+ raise asyncio.CancelledError
265
+ code = (
266
+ "RESOURCE_WRITE_UNKNOWN" if request.operation in _WRITES
267
+ else "RESOURCE_ACTIVATION_UNAVAILABLE"
268
+ )
269
+ return self._error(code, request.request_id)
270
+ return task.result()
271
+
272
+ async def _invoke(
273
+ self, activation: _Activation, request: ResourceRequest, scope: ResourceScope
274
+ ) -> dict:
275
+ # Keep the serial SDK queue here so admission is checked after waiting,
276
+ # immediately before handing the request to the worker transport.
277
+ async with activation.execution_lock:
278
+ return await self._invoke_admitted(activation, request, scope)
279
+
280
+ async def _invoke_admitted(
281
+ self, activation: _Activation, request: ResourceRequest, scope: ResourceScope
282
+ ) -> dict:
283
+ try:
284
+ self._registry.authorize(
285
+ request.handle,
286
+ operation=request.operation,
287
+ generation_id=self._generation_id,
288
+ activation_id=scope.activation_id,
289
+ )
290
+ if activation.closed or request.deadline / 1000 <= self._clock():
291
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
292
+ if request.operation == "read_skill_artifact":
293
+ try:
294
+ result = await asyncio.to_thread(
295
+ self._skill_artifacts.read,
296
+ request.arguments,
297
+ authority_digest=self._authority(scope),
298
+ )
299
+ except Exception:
300
+ return self._error("RESOURCE_ARTIFACT_NOT_FOUND", request.request_id)
301
+ self._registry.authorize(
302
+ request.handle,
303
+ operation=request.operation,
304
+ generation_id=self._generation_id,
305
+ activation_id=scope.activation_id,
306
+ )
307
+ if request.deadline / 1000 <= self._clock():
308
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
309
+ return {"v": 1, "requestId": request.request_id, "result": result}
310
+ receipt = None
311
+ status_receipt = None
312
+ execution_selections = None
313
+ if (
314
+ request.operation == "execute_skills"
315
+ and scope.binding_id in activation.discovery_keys
316
+ ):
317
+ selections = await asyncio.to_thread(
318
+ self._discovery_receipts.read, activation.discovery_keys[scope.binding_id]
319
+ )
320
+ self._registry.authorize(
321
+ request.handle, operation=request.operation,
322
+ generation_id=self._generation_id, activation_id=scope.activation_id,
323
+ )
324
+ selected = {item.skill_id: item for item in selections}
325
+ query = SkillExecutionQuery.model_validate(request.arguments)
326
+ if any(skill_id not in selected for skill_id in query.skill_ids):
327
+ return self._error("RESOURCE_SKILL_SELECTION_REQUIRED", request.request_id)
328
+ execution_selections = [
329
+ selected[skill_id].model_dump(by_alias=True, mode="json")
330
+ for skill_id in query.skill_ids
331
+ ]
332
+ if request.operation == "memory_status":
333
+ if self._operation_ledger is None:
334
+ return self._error("RESOURCE_OPERATION_NOT_FOUND", request.request_id)
335
+ query = MemoryStatusQuery.model_validate(request.arguments)
336
+ status_receipt = await asyncio.to_thread(
337
+ self._operation_ledger.lookup,
338
+ query.operation_id,
339
+ authority_digest=self._authority(scope),
340
+ operation="save_memory",
341
+ )
342
+ if status_receipt is None:
343
+ return self._error("RESOURCE_OPERATION_NOT_FOUND", request.request_id)
344
+ self._registry.authorize(
345
+ request.handle,
346
+ operation=request.operation,
347
+ generation_id=self._generation_id,
348
+ activation_id=scope.activation_id,
349
+ )
350
+ if activation.closed or request.deadline / 1000 <= self._clock():
351
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
352
+ if request.operation in _WRITES:
353
+ assert self._write_authorizer is not None and self._operation_ledger is not None
354
+ event_id = await self._write_authorizer.authorize(request, scope)
355
+ if not event_id:
356
+ return self._error("RESOURCE_APPROVAL_REQUIRED", request.request_id)
357
+ authority = self._authority(scope)
358
+ receipt = await asyncio.to_thread(
359
+ self._operation_ledger.claim,
360
+ authority_digest=authority,
361
+ event_id=event_id,
362
+ operation=request.operation,
363
+ arguments=(
364
+ {**request.arguments, "_hostSelections": execution_selections}
365
+ if execution_selections is not None else request.arguments
366
+ ),
367
+ )
368
+ # Authorization may have changed while awaiting approval or disk.
369
+ self._registry.authorize(
370
+ request.handle,
371
+ operation=request.operation,
372
+ generation_id=self._generation_id,
373
+ activation_id=scope.activation_id,
374
+ )
375
+ if activation.closed or request.deadline / 1000 <= self._clock():
376
+ return self._error("RESOURCE_WRITE_UNKNOWN", request.request_id)
377
+ if not receipt.claimed:
378
+ previous = None
379
+ if request.operation == "execute_skills" and self._skill_artifacts is not None:
380
+ previous = await asyncio.to_thread(
381
+ self._skill_artifacts.result,
382
+ receipt.operation_id,
383
+ authority_digest=authority,
384
+ )
385
+ self._registry.authorize(
386
+ request.handle,
387
+ operation=request.operation,
388
+ generation_id=self._generation_id,
389
+ activation_id=scope.activation_id,
390
+ )
391
+ elif request.operation in {"update_memory", "delete_memory"}:
392
+ previous = await asyncio.to_thread(
393
+ self._operation_ledger.memory_mutation_result,
394
+ receipt.operation_id,
395
+ authority_digest=authority,
396
+ operation=request.operation,
397
+ )
398
+ self._registry.authorize(
399
+ request.handle,
400
+ operation=request.operation,
401
+ generation_id=self._generation_id,
402
+ activation_id=scope.activation_id,
403
+ )
404
+ if activation.closed or request.deadline / 1000 <= self._clock():
405
+ return self._error("RESOURCE_DEADLINE_EXCEEDED", request.request_id)
406
+ if previous is not None:
407
+ return {
408
+ "v": 1,
409
+ "requestId": request.request_id,
410
+ "result": {**previous, "replayed": False},
411
+ }
412
+ return {
413
+ "v": 1,
414
+ "requestId": request.request_id,
415
+ "result": {
416
+ "status": receipt.state,
417
+ "operationId": receipt.operation_id,
418
+ "replayed": False,
419
+ },
420
+ }
421
+ worker_request = (
422
+ request
423
+ if receipt is None
424
+ else request.model_copy(update={"request_id": receipt.operation_id})
425
+ )
426
+ if execution_selections is not None:
427
+ worker_request = worker_request.model_copy(update={"arguments": {
428
+ **request.arguments, "_hostSelections": execution_selections,
429
+ }})
430
+ result = await activation.worker.invoke(worker_request, scope)
431
+ selection = result.pop("_discoverySelection", None)
432
+ if selection is not None:
433
+ key = activation.discovery_keys.get(scope.binding_id)
434
+ if (
435
+ key is None or self._discovery_receipts is None
436
+ or request.operation not in {"load_skill", "read_skill_resource"}
437
+ or result.get("status") != "ok"
438
+ ):
439
+ raise ValueError("Unexpected discovery selection")
440
+ selected = DiscoverySkillReceipt.model_validate(selection)
441
+ if (
442
+ selected.skill_id != result.get("skillId")
443
+ or selected.version_id != result.get("versionId")
444
+ or selected.content_hash != result.get("contentHash")
445
+ or selected.skill_id != request.arguments.get(
446
+ "skillId", request.arguments.get("skill_id")
447
+ )
448
+ ):
449
+ raise ValueError("Discovery selection does not match request/result")
450
+ self._registry.authorize(
451
+ request.handle, operation=request.operation,
452
+ generation_id=self._generation_id, activation_id=scope.activation_id,
453
+ )
454
+ await asyncio.to_thread(self._discovery_receipts.record, key, selected)
455
+ elif (
456
+ scope.binding_id in activation.discovery_keys
457
+ and request.operation in {"load_skill", "read_skill_resource"}
458
+ and result.get("status") == "ok"
459
+ ):
460
+ raise ValueError("Discovery selection receipt is missing")
461
+ if (
462
+ result.get("status") in {"failed", "unauthorized"}
463
+ and result.get("errorCode", result.get("error_code")) == "RESOURCE_FORBIDDEN"
464
+ ):
465
+ self._registry.revoke_binding(scope.activation_id, scope.binding_id)
466
+ denied = self._error("RESOURCE_FORBIDDEN", request.request_id)
467
+ if receipt is not None:
468
+ # Authentication failure is not a confirmed business write
469
+ # receipt. Preserve the claimed operation for reconciliation.
470
+ denied["operationReceipt"] = {
471
+ "operationId": receipt.operation_id, "state": receipt.state,
472
+ }
473
+ return denied
474
+ if receipt is not None and request.operation in {"update_memory", "delete_memory"}:
475
+ mutation = MemoryMutationReceipt.model_validate(result)
476
+ if (
477
+ mutation.operation_id != receipt.operation_id
478
+ or mutation.memory_id
479
+ != request.arguments.get("memoryId", request.arguments.get("memory_id"))
480
+ ):
481
+ raise ValueError("Invalid memory mutation receipt")
482
+ result = mutation.model_dump(by_alias=True, mode="json")
483
+ if mutation.status in {"succeeded", "failed"}:
484
+ receipt = await asyncio.to_thread(
485
+ self._operation_ledger.record_memory_mutation,
486
+ mutation,
487
+ authority_digest=self._authority(scope),
488
+ operation=request.operation,
489
+ )
490
+ if receipt is not None and request.operation == "execute_skills":
491
+ # Never forward the private Worker result, including on malformed
492
+ # receipts. Only host-published metadata can reach the tool caller.
493
+ if (
494
+ set(result) != {"operationId", "status", "outputFiles"}
495
+ or result["operationId"] != receipt.operation_id
496
+ or result["status"] not in {"succeeded", "failed", "unknown"}
497
+ or not isinstance(result["outputFiles"], list)
498
+ or any(not isinstance(path, str) for path in result["outputFiles"])
499
+ ):
500
+ raise ValueError("Invalid Skill execution receipt")
501
+ if result["status"] in {"succeeded", "failed"}:
502
+ assert self._skill_artifacts is not None
503
+ result = await asyncio.to_thread(
504
+ self._skill_artifacts.publish,
505
+ receipt.operation_id,
506
+ authority_digest=self._authority(scope),
507
+ root=activation.artifact_roots[scope.binding_id],
508
+ paths=result["outputFiles"],
509
+ status=result["status"],
510
+ )
511
+ receipt = await asyncio.to_thread(
512
+ self._operation_ledger.lookup,
513
+ receipt.operation_id,
514
+ authority_digest=self._authority(scope),
515
+ operation="execute_skills",
516
+ )
517
+ else:
518
+ result = {
519
+ "status": "unknown",
520
+ "operationId": receipt.operation_id,
521
+ "artifacts": [],
522
+ }
523
+ if status_receipt is not None:
524
+ if result == {
525
+ "operationId": status_receipt.operation_id,
526
+ "extractionStatus": "failed",
527
+ "searchable": False,
528
+ "errorCode": None,
529
+ } and status_receipt.state in {"unknown", "accepted_pending", "failed"}:
530
+ status_receipt = await asyncio.to_thread(
531
+ self._operation_ledger.record, status_receipt.operation_id, "failed"
532
+ )
533
+ result = {**result, "status": status_receipt.state}
534
+ if (
535
+ receipt is not None
536
+ and request.operation == "save_memory"
537
+ and result
538
+ == {
539
+ "status": "accepted_pending",
540
+ "operationId": receipt.operation_id,
541
+ "searchable": False,
542
+ "errorCode": None,
543
+ }
544
+ ):
545
+ # Fixed memory submission receipt from our initialized Worker;
546
+ # acceptance is not a searchable/succeeded terminal state.
547
+ receipt = await asyncio.to_thread(
548
+ self._operation_ledger.record, receipt.operation_id, "accepted_pending"
549
+ )
550
+ self._registry.authorize(
551
+ request.handle,
552
+ operation=request.operation,
553
+ generation_id=self._generation_id,
554
+ activation_id=scope.activation_id,
555
+ )
556
+ reply = {"v": 1, "requestId": request.request_id, "result": result}
557
+ if receipt is not None:
558
+ # The trusted business adapter must reconcile authoritative status;
559
+ # arbitrary Worker text cannot mark a durable operation successful.
560
+ reply["operationReceipt"] = {
561
+ "operationId": receipt.operation_id,
562
+ "state": receipt.state,
563
+ }
564
+ encode_frame(reply)
565
+ return reply
566
+ except LeaseRejected:
567
+ return self._error("RESOURCE_SCOPE_INVALID", request.request_id)
568
+ except OperationConflict:
569
+ return self._error("RESOURCE_OPERATION_CONFLICT", request.request_id)
570
+ except Exception:
571
+ if request.operation in _WRITES:
572
+ return self._error("RESOURCE_WRITE_UNKNOWN", request.request_id)
573
+ return self._error("RESOURCE_WORKER_FAILED", request.request_id)
574
+
575
+ @staticmethod
576
+ def _authority(scope: ResourceScope) -> str:
577
+ identity = scope.identity.model_dump(mode="json", exclude={"session_ref"})
578
+ return hashlib.sha256(
579
+ json.dumps(
580
+ [identity, scope.binding_id, scope.binding_snapshot_digest],
581
+ sort_keys=True,
582
+ separators=(",", ":"),
583
+ ).encode()
584
+ ).hexdigest()
585
+
586
+ def revoke_activation(self, activation_id: str) -> None:
587
+ self._registry.revoke_activation(activation_id)
588
+ activation = self._activations.get(activation_id)
589
+ if activation is not None:
590
+ activation.closed = True
591
+
592
+ def revoke_generation(self) -> None:
593
+ self._registry.revoke_generation(self._generation_id)
594
+ for activation in self._activations.values():
595
+ activation.closed = True
596
+
597
+ async def retire_activation(self, activation_id: str) -> None:
598
+ """Owner closes the worker first, then drains and removes broker state."""
599
+ self.revoke_activation(activation_id)
600
+ activation = self._activations.get(activation_id)
601
+ if activation is None:
602
+ return
603
+ tasks = tuple(activation.tasks)
604
+ if tasks:
605
+ # The owner has closed the Worker. Approval waiters and queued calls
606
+ # must not retain the supervisor lock until a UI response or deadline.
607
+ # Existing ledger claims remain unknown; cancellation is not rollback.
608
+ for task in tasks:
609
+ task.cancel()
610
+ await asyncio.gather(*tasks, return_exceptions=True)
611
+ if self._activations.get(activation_id) is activation:
612
+ del self._activations[activation_id]
613
+
614
+ @staticmethod
615
+ def _error(code: str, request_id: str = "") -> dict:
616
+ return {"v": 1, "requestId": request_id, "error": {"code": code}}