agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
  2. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
  3. ksadk/_build_provenance.json +1 -1
  4. ksadk/api/client.py +105 -91
  5. ksadk/builders/code_builder.py +36 -9
  6. ksadk/builders/framework_requirements.py +2 -1
  7. ksadk/builders/ks3_uploader.py +36 -7
  8. ksadk/builders/managed_runtime_builder.py +1 -0
  9. ksadk/cli/__init__.py +32 -3
  10. ksadk/cli/cmd_managed_runtime.py +13 -1
  11. ksadk/cli/cmd_plugin.py +6 -1
  12. ksadk/cli/cmd_web.py +2 -5
  13. ksadk/cli/runtime_bootstrap.py +23 -1
  14. ksadk/codex/client.py +424 -96
  15. ksadk/codex/projection.py +24 -0
  16. ksadk/codex/runtime.py +56 -298
  17. ksadk/common/auth.py +16 -10
  18. ksadk/configs/env_registry.py +29 -1
  19. ksadk/conversations/message_projection.py +135 -14
  20. ksadk/conversations/projector.py +4 -6
  21. ksadk/conversations/runtime_invocation.py +5 -0
  22. ksadk/conversations/runtime_payloads.py +1 -0
  23. ksadk/conversations/runtime_preparation.py +30 -27
  24. ksadk/conversations/runtime_resume.py +50 -2
  25. ksadk/conversations/runtime_stream_events.py +5 -0
  26. ksadk/conversations/runtime_streaming.py +25 -7
  27. ksadk/deployment/env_forward.py +2 -2
  28. ksadk/deployment/providers/serverless.py +1 -1
  29. ksadk/events/adapters/_codex_validators.py +18 -7
  30. ksadk/events/adapters/langgraph.py +15 -1
  31. ksadk/events/canonical_store.py +3 -1
  32. ksadk/events/projections.py +1 -1
  33. ksadk/harness/config.py +2 -2
  34. ksadk/harness/runtime.py +27 -27
  35. ksadk/harness/tools.py +38 -13
  36. ksadk/interaction/provider.py +1 -0
  37. ksadk/interaction/providers/langgraph.py +1 -0
  38. ksadk/kernel/bootstrap.py +28 -4
  39. ksadk/kernel/ingress.py +15 -2
  40. ksadk/kernel/sqlite_store.py +27 -0
  41. ksadk/kernel/store.py +3 -0
  42. ksadk/kernel/worker.py +65 -10
  43. ksadk/knowledge_base/client.py +57 -27
  44. ksadk/mcp_runtime/__init__.py +12 -4
  45. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  46. ksadk/memory/adk/resilient_session_service.py +25 -17
  47. ksadk/memory/adk/short_term_memory.py +26 -9
  48. ksadk/memory/models.py +7 -4
  49. ksadk/memory/provider_resolver.py +3 -0
  50. ksadk/model_proxy/server.py +10 -5
  51. ksadk/plugins/__init__.py +4 -0
  52. ksadk/plugins/artifacts.py +275 -0
  53. ksadk/plugins/bridges/__init__.py +4 -2
  54. ksadk/plugins/bridges/codex.py +120 -13
  55. ksadk/plugins/bridges/dsh.py +340 -156
  56. ksadk/plugins/builtins.py +35 -36
  57. ksadk/plugins/bundle_security.py +28 -4
  58. ksadk/plugins/codex_manifest.py +983 -0
  59. ksadk/plugins/composition.py +8 -0
  60. ksadk/plugins/contracts.py +118 -0
  61. ksadk/plugins/delivery.py +153 -0
  62. ksadk/plugins/dsh_installation_digest.py +71 -0
  63. ksadk/plugins/dsh_toolchain.py +110 -21
  64. ksadk/plugins/ecosystem_probe.py +6 -6
  65. ksadk/plugins/host.py +102 -39
  66. ksadk/plugins/kernel_adapter.py +205 -0
  67. ksadk/plugins/providers/__init__.py +23 -0
  68. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  69. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  70. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  71. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  72. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  73. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  74. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  75. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  76. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  77. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  78. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  79. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  80. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  81. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  82. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  83. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  84. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  85. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  86. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  87. ksadk/plugins/providers/codex.py +335 -69
  88. ksadk/plugins/providers/codex_native.py +368 -0
  89. ksadk/plugins/providers/codex_turn.py +301 -0
  90. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  91. ksadk/plugins/providers/dsh_mcp.py +467 -0
  92. ksadk/plugins/providers/harness.py +118 -113
  93. ksadk/plugins/providers/mcp_projection.py +150 -0
  94. ksadk/plugins/providers/platform_resources.py +657 -0
  95. ksadk/plugins/resolver.py +8 -1
  96. ksadk/resource_runtime/__init__.py +4 -0
  97. ksadk/resource_runtime/broker.py +616 -0
  98. ksadk/resource_runtime/build_artifacts.py +165 -0
  99. ksadk/resource_runtime/contracts.py +138 -0
  100. ksadk/resource_runtime/discovery_receipts.py +100 -0
  101. ksadk/resource_runtime/discovery_skills.py +172 -0
  102. ksadk/resource_runtime/errors.py +6 -0
  103. ksadk/resource_runtime/ipc.py +142 -0
  104. ksadk/resource_runtime/kernel_approval.py +165 -0
  105. ksadk/resource_runtime/knowledge.py +114 -0
  106. ksadk/resource_runtime/langgraph.py +94 -0
  107. ksadk/resource_runtime/leases.py +191 -0
  108. ksadk/resource_runtime/managed_projection.py +186 -0
  109. ksadk/resource_runtime/mcp_server.py +138 -0
  110. ksadk/resource_runtime/memory_provider.py +318 -0
  111. ksadk/resource_runtime/memory_receipts.py +34 -0
  112. ksadk/resource_runtime/operation_ledger.py +211 -0
  113. ksadk/resource_runtime/plugin_config.py +48 -0
  114. ksadk/resource_runtime/policy_authorization.py +54 -0
  115. ksadk/resource_runtime/process.py +110 -0
  116. ksadk/resource_runtime/skill_artifacts.py +153 -0
  117. ksadk/resource_runtime/skill_runtime.py +42 -0
  118. ksadk/resource_runtime/skill_workspace.py +118 -0
  119. ksadk/resource_runtime/skills.py +215 -0
  120. ksadk/resource_runtime/snapshots.py +180 -0
  121. ksadk/resource_runtime/socket_server.py +103 -0
  122. ksadk/resource_runtime/supervisor.py +380 -0
  123. ksadk/resource_runtime/worker.py +504 -0
  124. ksadk/runners/_langgraph_runner_streams.py +74 -6
  125. ksadk/runners/adk_runner.py +149 -11
  126. ksadk/runners/base_runner.py +29 -1
  127. ksadk/runners/langgraph_runner.py +475 -145
  128. ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
  129. ksadk/runtime/adapter.py +2 -0
  130. ksadk/runtime/conversation_execution.py +92 -16
  131. ksadk/runtime/executor.py +78 -2
  132. ksadk/runtime/factory.py +29 -273
  133. ksadk/runtime/framework_adapters.py +23 -0
  134. ksadk/runtime/preprocessing.py +10 -2
  135. ksadk/runtime/runner_adapter.py +73 -14
  136. ksadk/runtime_context.py +40 -2
  137. ksadk/sandbox/backends/e2b.py +52 -11
  138. ksadk/sandbox/backends/local_process.py +9 -0
  139. ksadk/sandbox/base.py +2 -0
  140. ksadk/sandbox/e2b_connection.py +66 -0
  141. ksadk/scheduler/sqlite_store.py +18 -0
  142. ksadk/server/composition.py +2 -0
  143. ksadk/server/factory.py +5 -0
  144. ksadk/server/persistence_capability.py +516 -0
  145. ksadk/server/routes/control.py +210 -46
  146. ksadk/server/routes/dependencies.py +15 -0
  147. ksadk/server/routes/models.py +47 -4
  148. ksadk/server/routes/projection.py +252 -12
  149. ksadk/server/routes/sessions.py +284 -107
  150. ksadk/server/routes/streaming.py +43 -9
  151. ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  152. ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
  153. ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  154. ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  155. ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  156. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  157. ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
  158. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  159. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  160. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  161. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  162. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  163. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  164. ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  165. ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  166. ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  167. ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  168. ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  169. ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  170. ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  171. ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  172. ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  173. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  174. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  175. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  176. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  177. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  178. ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  179. ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
  180. ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  181. ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  182. ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  183. ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  184. ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  185. ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
  186. ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
  187. ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
  188. ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
  189. ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
  190. ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
  191. ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
  192. ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
  193. ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
  194. ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
  195. ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
  196. ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
  197. ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
  198. ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
  199. ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
  200. ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
  201. ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
  202. ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
  203. ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
  204. ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
  205. ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
  206. ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
  207. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  208. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  209. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  210. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  211. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  212. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  213. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  214. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  215. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  216. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  217. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  218. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  219. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  220. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  221. ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
  222. ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
  223. ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  224. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  225. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  226. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  227. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  228. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  229. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  230. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  231. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  232. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  233. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  234. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  235. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  236. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  237. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  238. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  239. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  240. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  241. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  242. ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  243. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  244. ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  245. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  246. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  247. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  248. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  249. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  250. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  251. ksadk/server/static/index.html +2 -2
  252. ksadk/session_context.py +66 -0
  253. ksadk/sessions/__init__.py +11 -21
  254. ksadk/sessions/_local_service_sync.py +263 -1
  255. ksadk/sessions/base.py +176 -0
  256. ksadk/sessions/errors.py +4 -0
  257. ksadk/sessions/in_memory.py +309 -19
  258. ksadk/sessions/local_service.py +83 -1
  259. ksadk/sessions/persistence.py +275 -0
  260. ksadk/sessions/postgres_service.py +358 -0
  261. ksadk/sessions/resilience.py +8 -0
  262. ksadk/sessions/resilient.py +362 -4
  263. ksadk/sessions/topology.py +135 -0
  264. ksadk/skills/models.py +26 -4
  265. ksadk/skills/package_store.py +186 -38
  266. ksadk/skills/runtime/agent.py +31 -6
  267. ksadk/skills/runtime/artifact_delivery.py +139 -0
  268. ksadk/skills/runtime/backends/e2b.py +98 -6
  269. ksadk/skills/runtime/backends/local.py +73 -8
  270. ksadk/skills/runtime/base.py +3 -0
  271. ksadk/skills/runtime/executor.py +2 -0
  272. ksadk/skills/runtime/loader.py +10 -2
  273. ksadk/skills/runtime/pinned.py +114 -0
  274. ksadk/skills/runtime/request.py +31 -0
  275. ksadk/skills/service_client.py +167 -28
  276. ksadk/studio/api.py +224 -42
  277. ksadk/studio/api_catalog_routes.py +18 -0
  278. ksadk/studio/api_plugin_routes.py +526 -95
  279. ksadk/studio/api_resource_connections.py +183 -0
  280. ksadk/studio/authoring_coordinator.py +19 -14
  281. ksadk/studio/builder.py +76 -0
  282. ksadk/studio/cloud.py +342 -104
  283. ksadk/studio/cloud_shared_web.py +565 -0
  284. ksadk/studio/codex_agent_service.py +128 -26
  285. ksadk/studio/codex_builder.py +241 -2
  286. ksadk/studio/codex_credentials.py +90 -0
  287. ksadk/studio/codex_manifest.py +31 -4
  288. ksadk/studio/codex_plugin_store.py +746 -0
  289. ksadk/studio/codex_provider_build.py +231 -0
  290. ksadk/studio/codex_run.py +184 -25
  291. ksadk/studio/compatibility_report.py +12 -1
  292. ksadk/studio/compiler.py +78 -14
  293. ksadk/studio/contracts.py +132 -6
  294. ksadk/studio/dsh_application.py +137 -0
  295. ksadk/studio/dsh_capability_service.py +1107 -0
  296. ksadk/studio/dsh_models.py +59 -0
  297. ksadk/studio/dsh_provider_registration.py +320 -13
  298. ksadk/studio/hosted_kernel.py +88 -13
  299. ksadk/studio/mcp_runtime.py +11 -3
  300. ksadk/studio/model_client.py +2 -2
  301. ksadk/studio/plugin_composition.py +190 -23
  302. ksadk/studio/plugin_kernel_adapter.py +12 -112
  303. ksadk/studio/plugin_runtime.py +224 -45
  304. ksadk/studio/resource_authority.py +637 -0
  305. ksadk/studio/resource_binding_validation.py +77 -0
  306. ksadk/studio/resource_build_admission.py +196 -0
  307. ksadk/studio/resource_build_materializer.py +149 -0
  308. ksadk/studio/resource_catalog.py +143 -2
  309. ksadk/studio/resource_connections.py +220 -0
  310. ksadk/studio/run_service.py +462 -52
  311. ksadk/studio/runtime_source.py +15 -7
  312. ksadk/studio/scheduler_assistant.py +317 -0
  313. ksadk/studio/scheduler_runtime.py +9 -0
  314. ksadk/studio/scheduler_service.py +3 -0
  315. ksadk/studio/service.py +490 -44
  316. ksadk/studio/shared_web.py +446 -62
  317. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  318. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  319. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  320. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  321. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  322. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  323. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  324. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  325. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  326. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  327. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  328. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  329. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  330. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  331. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  332. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  333. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  334. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  335. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  336. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  337. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  338. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  339. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  340. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  341. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  342. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  343. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  344. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  345. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  346. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  347. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  348. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  349. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  350. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  351. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  352. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  353. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  354. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  355. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  356. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  357. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  358. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  359. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  360. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  361. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  362. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  363. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  364. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  365. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  366. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  367. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  368. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  369. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  372. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  373. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  377. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  378. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  379. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  380. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  381. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  382. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  383. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  384. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  385. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  386. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  387. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  388. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  389. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  390. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  391. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  392. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  393. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  394. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  395. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  396. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  397. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  398. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  399. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  400. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  401. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  402. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  403. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  404. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  405. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  406. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  407. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  408. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  409. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  410. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  411. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  412. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  413. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  414. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  415. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  416. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  417. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  418. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  419. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  420. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  421. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  422. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  423. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  424. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  425. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  426. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  427. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  428. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  429. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  430. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  431. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  432. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  433. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  434. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  435. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  436. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  437. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  438. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  439. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  440. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  441. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  442. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  443. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  444. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  445. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  446. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  447. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  448. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  449. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  450. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  451. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  452. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  453. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  454. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  455. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  456. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  457. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  458. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  459. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  460. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  461. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  462. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  463. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  464. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  465. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  466. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  467. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  468. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  469. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  470. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  471. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  472. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  473. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  474. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  475. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  476. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  477. ksadk/studio/static/index.html +2 -2
  478. ksadk/version.py +1 -1
  479. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
  480. ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
  481. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
  482. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
  483. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
  484. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
  485. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
  486. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
  487. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
  488. ksadk/server/static/assets/index-B2k_urY8.js +0 -241
  489. ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
  490. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
  491. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
  492. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
  493. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
  494. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
  495. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
  496. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
  497. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
  498. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
  499. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
  500. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
  501. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
  502. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
  503. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  504. ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
  505. ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
  506. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  507. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  508. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  509. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
@@ -3,11 +3,12 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
- import hashlib
6
+ import base64
7
7
  import os
8
+ import re
8
9
  from pathlib import Path
9
10
  from typing import Any, Callable
10
- from urllib.parse import urlencode, urlparse
11
+ from urllib.parse import urlparse
11
12
  from uuid import uuid4
12
13
 
13
14
  from fastapi import FastAPI, Query, Response
@@ -29,8 +30,21 @@ from ksadk.plugins.bridges.dsh import (
29
30
  DshPluginMutationError,
30
31
  DshPluginNotFoundError,
31
32
  DshProfilePluginBridge,
33
+ DshProfileRecoveryError,
34
+ validate_dsh_registry_request,
35
+ )
36
+ from ksadk.plugins.codex_manifest import (
37
+ CodexInstalledPluginSnapshot,
38
+ CodexPluginSourceCoordinate,
39
+ snapshot_installed_codex_plugin,
32
40
  )
33
41
  from ksadk.plugins.dsh_toolchain import DshToolchainError, DshToolchainManager
42
+ from ksadk.plugins.host import PluginHostError
43
+ from ksadk.studio.codex_plugin_store import (
44
+ CodexWorkspacePluginSnapshot,
45
+ component_selector,
46
+ find_installed_codex_plugin_root,
47
+ )
34
48
  from ksadk.studio.errors import StudioError
35
49
  from ksadk.studio.service import StudioService
36
50
 
@@ -43,6 +57,13 @@ class CodexPluginInstallRequest(BaseModel):
43
57
  accept_undeclared_permissions: bool = Field(default=False, alias="acceptUndeclaredPermissions")
44
58
 
45
59
 
60
+ class CodexPluginSnapshotRequest(BaseModel):
61
+ model_config = ConfigDict(extra="forbid", populate_by_name=True)
62
+ marketplace_name: str | None = Field(
63
+ default=None, alias="marketplaceName", min_length=1, max_length=256
64
+ )
65
+
66
+
46
67
  class DshPluginInstallRequest(BaseModel):
47
68
  model_config = ConfigDict(extra="forbid", populate_by_name=True)
48
69
  source: str = Field(min_length=1, max_length=2048)
@@ -53,8 +74,16 @@ class DshPluginInstallRequest(BaseModel):
53
74
  def validate_source(cls, value: str) -> str:
54
75
  normalized = value.strip()
55
76
  if not normalized or any(character in value for character in ("\x00", "\r", "\n")):
56
- raise ValueError("source must be one package, Git URL, or absolute local path")
57
- return normalized
77
+ raise ValueError("source must be one exact registry package")
78
+ # The authenticated Studio API is a production-facing package install
79
+ # boundary. Local paths remain available to the CLI/developer bridge,
80
+ # where they are packed into the immutable store; exposing arbitrary
81
+ # host paths to a browser request would turn the API into a file reader.
82
+ if Path(normalized).expanduser().is_absolute():
83
+ raise ValueError(
84
+ "Studio only accepts registry packages; use the local CLI for development"
85
+ )
86
+ return validate_dsh_registry_request(normalized)
58
87
 
59
88
 
60
89
  class DshPluginUpdateRequest(BaseModel):
@@ -86,7 +115,7 @@ def _studio_dsh_options(studio: StudioService) -> tuple[Path, str, tuple[str, ..
86
115
  # Keep the bridge's established PATH lookup when the optional
87
116
  # pinned toolchain has not been installed or is unusable.
88
117
  command = None
89
- profile = os.environ.get("KSADK_DSH_PROFILE", "").strip() or "studio"
118
+ profile = os.environ.get("KSADK_DSH_PROFILE", "").strip() or "web"
90
119
  return home, profile, command, "explicit" if configured_home else "workspace-isolated"
91
120
 
92
121
 
@@ -123,13 +152,20 @@ def _public_codex_source(source: BaseModel) -> dict[str, Any]:
123
152
  def _public_codex_inventory(
124
153
  inventory: CodexPluginInventory, *, host: CodexBridgeHost, home_mode: str
125
154
  ) -> dict[str, Any]:
155
+ presentation = _public_plugin_interface(inventory.interface)
156
+ if not presentation.get("logoUrl"):
157
+ artwork = _local_plugin_artwork(inventory)
158
+ if artwork:
159
+ presentation["logoUrl"] = artwork
126
160
  return {
127
161
  "ecosystem": "codex",
128
162
  "integrationMode": "bridged",
129
163
  "pluginId": inventory.plugin_id,
130
164
  "resolvedVersion": inventory.version,
131
165
  "distributionName": inventory.name,
132
- "displayName": inventory.name,
166
+ "displayName": inventory.interface.get("displayName") or inventory.name,
167
+ "description": inventory.interface.get("shortDescription"),
168
+ "interface": presentation,
133
169
  "marketplaceName": inventory.marketplace_name,
134
170
  "source": _public_codex_source(inventory.source),
135
171
  "installed": inventory.installed,
@@ -145,10 +181,81 @@ def _public_codex_inventory(
145
181
  }
146
182
 
147
183
 
184
+ def _local_plugin_artwork(inventory: CodexPluginInventory) -> str | None:
185
+ """Read only bounded image assets inside the host-reported local plugin.
186
+
187
+ Never expose host paths, accept browser-supplied filenames, or fetch URLs.
188
+ SVGs remain image data (not executable same-origin HTML documents).
189
+ """
190
+ if inventory.source.type != "local":
191
+ return None
192
+ root = Path(inventory.source.path)
193
+ if not root.is_absolute():
194
+ if not inventory.marketplace_path:
195
+ return None
196
+ root = Path(inventory.marketplace_path) / root
197
+ root = root.resolve()
198
+ if not (root / ".codex-plugin" / "plugin.json").is_file():
199
+ return None
200
+ for key in ("logo", "composerIcon"):
201
+ raw = inventory.interface.get(key)
202
+ if not isinstance(raw, str):
203
+ continue
204
+ path = Path(raw)
205
+ path = (path if path.is_absolute() else root / path).resolve()
206
+ if not path.is_relative_to(root):
207
+ continue
208
+ try:
209
+ with path.open("rb") as stream:
210
+ data = stream.read(256 * 1024 + 1)
211
+ except OSError:
212
+ continue
213
+ if len(data) > 256 * 1024:
214
+ continue
215
+ mime = None
216
+ if data.startswith(b"\x89PNG\r\n\x1a\n"):
217
+ mime = "image/png"
218
+ elif data.startswith(b"\xff\xd8\xff"):
219
+ mime = "image/jpeg"
220
+ elif data.startswith((b"GIF87a", b"GIF89a")):
221
+ mime = "image/gif"
222
+ elif data.startswith(b"RIFF") and data[8:12] == b"WEBP":
223
+ mime = "image/webp"
224
+ elif path.suffix.lower() == ".svg" and b"<svg" in data[:1024]:
225
+ mime = "image/svg+xml"
226
+ if mime:
227
+ return f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}"
228
+ return None
229
+
230
+
231
+ def _public_plugin_interface(value: dict[str, Any]) -> dict[str, Any]:
232
+ """Project marketplace display data, never filesystem paths or host state."""
233
+ result = {
234
+ key: value[key] for key in (
235
+ "displayName", "shortDescription", "longDescription", "developerName", "category",
236
+ ) if isinstance(value.get(key), str)
237
+ }
238
+ for key in ("defaultPrompt", "capabilities"):
239
+ if isinstance(value.get(key), list):
240
+ result[key] = [item for item in value[key] if isinstance(item, str)]
241
+ for key in (
242
+ "logoUrl", "logoUrlDark", "composerIconUrl", "websiteUrl",
243
+ "privacyPolicyUrl", "termsOfServiceUrl",
244
+ ):
245
+ raw = value.get(key)
246
+ if isinstance(raw, str) and urlparse(raw).scheme == "https" and not urlparse(raw).username:
247
+ result[key] = raw
248
+ return result
249
+
250
+
148
251
  def _public_codex_detail(
149
- detail: CodexPluginDetail, *, host: CodexBridgeHost, home_mode: str
252
+ detail: CodexPluginDetail,
253
+ *,
254
+ host: CodexBridgeHost,
255
+ home_mode: str,
256
+ snapshot: CodexWorkspacePluginSnapshot | None = None,
150
257
  ) -> dict[str, Any]:
151
- return {
258
+ payload = {
152
259
  "item": _public_codex_inventory(detail.inventory, host=host, home_mode=home_mode),
153
260
  "description": detail.description,
154
261
  "capabilities": {
@@ -158,6 +265,189 @@ def _public_codex_detail(
158
265
  "apps": list(detail.apps),
159
266
  "scheduledTasks": list(detail.scheduled_tasks),
160
267
  },
268
+ "snapshot": None,
269
+ "snapshotRequired": detail.inventory.installed,
270
+ }
271
+ if snapshot is not None:
272
+ projection = _public_codex_snapshot(snapshot)
273
+ payload["snapshot"] = projection
274
+ payload["snapshotRequired"] = False
275
+ payload["item"].update(
276
+ snapshotDigest=projection["snapshotDigest"],
277
+ pluginRef=projection["pluginRef"],
278
+ components=projection["components"],
279
+ )
280
+ return payload
281
+
282
+
283
+ _EXACT_SEMVER = re.compile(
284
+ r"^(0|[1-9]\d*)\."
285
+ r"(0|[1-9]\d*)\."
286
+ r"(0|[1-9]\d*)"
287
+ r"(?:-(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\."
288
+ r"(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*)?"
289
+ r"(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$"
290
+ )
291
+ _FULL_GIT_COMMIT = re.compile(r"^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$")
292
+
293
+
294
+ def _require_exact_codex_version(inventory: CodexPluginInventory) -> str:
295
+ version = str(inventory.version or "")
296
+ if _EXACT_SEMVER.fullmatch(version) is None:
297
+ raise StudioError(
298
+ "CODEX_PLUGIN_SOURCE_NOT_IMMUTABLE",
299
+ "Codex 插件缺少可锁定的精确语义版本",
300
+ status_code=422,
301
+ details={
302
+ "pluginId": inventory.plugin_id,
303
+ "sourceType": inventory.source.type,
304
+ "version": inventory.version,
305
+ },
306
+ )
307
+ return version
308
+
309
+
310
+ def _codex_source_coordinate(inventory: CodexPluginInventory) -> CodexPluginSourceCoordinate:
311
+ raw = inventory.source.model_dump(by_alias=True, exclude_none=True, mode="json")
312
+ source_type = str(raw.get("type") or "remote")
313
+ marketplace = inventory.marketplace_name
314
+ version = _require_exact_codex_version(inventory)
315
+ integrity: str | None = None
316
+ if source_type == "local":
317
+ requested = str(raw.get("path") or inventory.name)
318
+ resolved = f"codex-marketplace://{marketplace}/{inventory.name}@{version}"
319
+ elif source_type == "git":
320
+ requested = str(raw.get("url") or inventory.name)
321
+ revision = str(raw.get("sha") or "")
322
+ if _FULL_GIT_COMMIT.fullmatch(revision) is None:
323
+ raise StudioError(
324
+ "CODEX_PLUGIN_SOURCE_NOT_IMMUTABLE",
325
+ "Git Codex 插件必须由宿主解析为完整 commit SHA 后才能提交快照",
326
+ status_code=422,
327
+ details={
328
+ "pluginId": inventory.plugin_id,
329
+ "refName": raw.get("refName"),
330
+ "sha": raw.get("sha"),
331
+ },
332
+ )
333
+ resolved = f"{requested.rstrip('/')}@{revision.lower()}"
334
+ elif source_type == "npm":
335
+ package = str(raw.get("package") or inventory.name)
336
+ source_version = str(raw.get("version") or "")
337
+ if _EXACT_SEMVER.fullmatch(source_version) is None or source_version != version:
338
+ raise StudioError(
339
+ "CODEX_PLUGIN_SOURCE_NOT_IMMUTABLE",
340
+ "npm Codex 插件必须由宿主解析为一致的精确版本后才能提交快照",
341
+ status_code=422,
342
+ details={
343
+ "pluginId": inventory.plugin_id,
344
+ "requestedVersion": raw.get("version"),
345
+ "resolvedVersion": inventory.version,
346
+ },
347
+ )
348
+ requested = f"{package}@{source_version}"
349
+ resolved = requested
350
+ raw_integrity = raw.get("integrity")
351
+ integrity = str(raw_integrity) if raw_integrity else None
352
+ else:
353
+ requested = inventory.plugin_id
354
+ resolved = f"codex-marketplace://{marketplace}/{inventory.name}@{version}"
355
+ return CodexPluginSourceCoordinate(
356
+ type=source_type,
357
+ requested=requested,
358
+ resolved=resolved,
359
+ marketplace_name=marketplace,
360
+ registry=raw.get("registry"),
361
+ integrity=integrity,
362
+ )
363
+
364
+
365
+ def _observe_codex_snapshot(
366
+ codex_home: Path,
367
+ inventory: CodexPluginInventory,
368
+ ) -> CodexInstalledPluginSnapshot:
369
+ if not inventory.installed:
370
+ raise StudioError(
371
+ "CODEX_PLUGIN_NOT_INSTALLED",
372
+ "Codex 插件尚未安装,无法提交不可变快照",
373
+ status_code=409,
374
+ details={"pluginId": inventory.plugin_id},
375
+ )
376
+ installed_root = find_installed_codex_plugin_root(
377
+ codex_home,
378
+ marketplace_name=inventory.marketplace_name,
379
+ plugin_name=inventory.name,
380
+ version=inventory.version,
381
+ )
382
+ observed = snapshot_installed_codex_plugin(
383
+ installed_root,
384
+ source=_codex_source_coordinate(inventory),
385
+ )
386
+ if observed.manifest.version != inventory.version:
387
+ raise StudioError(
388
+ "CODEX_PLUGIN_VERSION_MISMATCH",
389
+ "Codex 宿主清单版本与已安装插件清单不一致",
390
+ status_code=409,
391
+ details={
392
+ "pluginId": inventory.plugin_id,
393
+ "hostVersion": inventory.version,
394
+ "manifestVersion": observed.manifest.version,
395
+ },
396
+ )
397
+ return observed
398
+
399
+
400
+ def _lookup_codex_snapshot(
401
+ studio: StudioService,
402
+ codex_home: Path,
403
+ inventory: CodexPluginInventory,
404
+ ) -> CodexWorkspacePluginSnapshot | None:
405
+ if not inventory.installed:
406
+ return None
407
+ try:
408
+ observed = _observe_codex_snapshot(codex_home, inventory)
409
+ except (StudioError, OSError, ValueError):
410
+ # GET is an inventory operation. Invalid/unpinned host bytes remain
411
+ # visible but require the explicit admission POST, which reports the
412
+ # actionable validation failure.
413
+ return None
414
+ return studio.codex_plugin_snapshots.lookup(observed)
415
+
416
+
417
+ def _commit_codex_snapshot(
418
+ studio: StudioService,
419
+ codex_home: Path,
420
+ inventory: CodexPluginInventory,
421
+ ) -> CodexWorkspacePluginSnapshot:
422
+ return studio.codex_plugin_snapshots.commit(_observe_codex_snapshot(codex_home, inventory))
423
+
424
+
425
+ def _snapshot_failure_details(error: Exception) -> dict[str, Any]:
426
+ if isinstance(error, StudioError):
427
+ return {
428
+ "code": error.code,
429
+ "message": error.message,
430
+ "details": error.details,
431
+ }
432
+ return {"code": type(error).__name__, "message": str(error)}
433
+
434
+
435
+ def _public_codex_snapshot(snapshot: CodexWorkspacePluginSnapshot) -> dict[str, Any]:
436
+ return {
437
+ "snapshotDigest": snapshot.snapshot_digest,
438
+ "pluginRef": snapshot.plugin_ref,
439
+ "artifactDigest": snapshot.artifact_digest,
440
+ "manifestDigest": snapshot.manifest_digest,
441
+ "components": [
442
+ {
443
+ "id": component_selector(component),
444
+ "kind": component.kind,
445
+ "name": component.name,
446
+ "path": component.path,
447
+ "digest": component.content_digest,
448
+ }
449
+ for component in snapshot.components
450
+ ],
161
451
  }
162
452
 
163
453
 
@@ -168,7 +458,20 @@ def _public_dsh_inventory(
168
458
  home_mode: str,
169
459
  runtime_state: dict[str, Any] | None = None,
170
460
  ) -> dict[str, Any]:
171
- client = inventory.client_bundle
461
+ if inventory.source_digest is not None:
462
+ source = {
463
+ "type": "local-immutable",
464
+ "name": inventory.name,
465
+ "kind": inventory.source_kind,
466
+ "integrity": inventory.source_digest,
467
+ }
468
+ else:
469
+ source = {
470
+ "type": "registry",
471
+ "package": inventory.name,
472
+ "requested": inventory.requested_spec,
473
+ "resolvedVersion": inventory.version,
474
+ }
172
475
  return {
173
476
  "ecosystem": "dsh",
174
477
  "integrationMode": "bridged",
@@ -177,8 +480,10 @@ def _public_dsh_inventory(
177
480
  "distributionName": inventory.name,
178
481
  "displayName": inventory.display_name,
179
482
  "description": inventory.description,
483
+ "clientExtension": inventory.client_extension,
484
+ "settingsIntegration": inventory.settings_integration,
180
485
  "profile": inventory.profile,
181
- "source": {"type": "host-profile", "name": inventory.name},
486
+ "source": source,
182
487
  "installed": True,
183
488
  "state": "enabled" if inventory.enabled else "disabled",
184
489
  "enabled": inventory.enabled,
@@ -187,42 +492,13 @@ def _public_dsh_inventory(
187
492
  "riskDisclosures": list(inventory.risk_disclosures),
188
493
  "isolation": "host-managed",
189
494
  "runtimeState": runtime_state,
190
- "clientBundle": (
191
- {
192
- "platform": client.platform,
193
- "digest": client.digest,
194
- "contentBytes": client.content_bytes,
195
- "external": list(client.external),
196
- "inject": list(client.inject),
197
- "compatible": client.compatible,
198
- "incompatibilityReason": client.incompatibility_reason or None,
199
- }
200
- if client is not None
201
- else None
202
- ),
203
495
  "host": _public_host("dsh", host, home_mode=home_mode),
204
496
  }
205
497
 
206
498
 
207
- def _public_dsh_client_bundle(inventory: DshPluginInventory) -> dict[str, Any] | None:
208
- client = inventory.client_bundle
209
- if client is None:
210
- return None
211
- query = urlencode({"pluginName": inventory.name, "digest": client.digest})
212
- return {
213
- "pluginId": inventory.name,
214
- "enabled": inventory.enabled,
215
- "compatible": client.compatible,
216
- "digest": client.digest,
217
- "contentBytes": client.content_bytes,
218
- "external": list(client.external),
219
- "inject": list(client.inject),
220
- "incompatibilityReason": client.incompatibility_reason or None,
221
- "url": f"/api/v1/plugin-ecosystems/dsh/client-bundle?{query}",
222
- }
223
-
224
-
225
499
  def _codex_error(error: Exception) -> StudioError:
500
+ if isinstance(error, StudioError):
501
+ return error
226
502
  if isinstance(error, CodexPluginNotFoundError):
227
503
  return StudioError(
228
504
  "CODEX_PLUGIN_NOT_FOUND", "Codex 插件不存在或来源不唯一", status_code=404
@@ -245,6 +521,12 @@ def _dsh_error(error: Exception) -> StudioError:
245
521
  "安装或升级 DSH 插件前必须确认宿主权限风险",
246
522
  status_code=422,
247
523
  )
524
+ if isinstance(error, DshProfileRecoveryError):
525
+ return StudioError(
526
+ "DSH_PROFILE_RECOVERY_REQUIRED",
527
+ "Profile 迁移恢复失败,已保留恢复备份并暂停运行准入",
528
+ status_code=503,
529
+ )
248
530
  if isinstance(error, DshPluginMutationError):
249
531
  return StudioError(
250
532
  "DSH_PLUGIN_MUTATION_FAILED", "DSH 插件操作失败,原 Profile 已保留", status_code=409
@@ -277,6 +559,34 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
277
559
  except Exception as error:
278
560
  raise _dsh_error(error) from None
279
561
 
562
+ @app.post("/api/v1/plugin-ecosystems/dsh/core/session")
563
+ async def start_dsh_core_session(response: Response):
564
+ """Start the official full Core DSH Web profile on demand.
565
+
566
+ The token-bearing URL is returned only from this authenticated,
567
+ CSRF-protected local POST and must never be persisted in Studio state.
568
+ """
569
+
570
+ try:
571
+ lease = await studio.dsh_capabilities.connector_lease()
572
+ descriptor = await studio.dsh_capabilities.describe()
573
+ browser_url = lease.browser_url()
574
+ except PluginHostError as error:
575
+ raise StudioError(
576
+ "DSH_CORE_RUNTIME_UNAVAILABLE",
577
+ "完整 DSH Core 当前无法启动",
578
+ status_code=503,
579
+ details={"reason": error.code},
580
+ ) from error
581
+ response.headers["Cache-Control"] = "no-store"
582
+ return {
583
+ "protocolVersion": "ksadk.dsh-core-runtime/v1",
584
+ "version": descriptor.dsh_version,
585
+ "profile": descriptor.profile,
586
+ "endpoint": browser_url.split("?", 1)[0],
587
+ "browserUrl": browser_url,
588
+ }
589
+
280
590
  @app.get("/api/v1/plugin-ecosystems/codex/plugins")
281
591
  async def list_codex_plugins(
282
592
  installed_only: bool = Query(default=False), force_refetch: bool = Query(default=False)
@@ -313,7 +623,39 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
313
623
  try:
314
624
  async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
315
625
  detail = await bridge.read_plugin(plugin_id, marketplace_name=marketplace_name)
316
- return _public_codex_detail(detail, host=bridge.host, home_mode=codex_mode)
626
+ snapshot = _lookup_codex_snapshot(studio, codex_home, detail.inventory)
627
+ return _public_codex_detail(
628
+ detail,
629
+ host=bridge.host,
630
+ home_mode=codex_mode,
631
+ snapshot=snapshot,
632
+ )
633
+ except Exception as error:
634
+ raise _codex_error(error) from None
635
+
636
+ @app.post("/api/v1/plugin-ecosystems/codex/plugins/{plugin_id}:snapshot")
637
+ async def snapshot_codex_plugin(plugin_id: str, payload: CodexPluginSnapshotRequest):
638
+ """Explicitly admit already-installed host bytes into the workspace store."""
639
+
640
+ try:
641
+ async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
642
+ detail = await bridge.read_plugin(
643
+ plugin_id,
644
+ marketplace_name=payload.marketplace_name,
645
+ )
646
+ snapshot = _commit_codex_snapshot(studio, codex_home, detail.inventory)
647
+ projection = _public_codex_snapshot(snapshot)
648
+ item = _public_codex_inventory(
649
+ detail.inventory,
650
+ host=bridge.host,
651
+ home_mode=codex_mode,
652
+ )
653
+ item.update(
654
+ snapshotDigest=projection["snapshotDigest"],
655
+ pluginRef=projection["pluginRef"],
656
+ components=projection["components"],
657
+ )
658
+ return {"item": item, "snapshot": projection, "snapshotRequired": False}
317
659
  except Exception as error:
318
660
  raise _codex_error(error) from None
319
661
 
@@ -323,16 +665,78 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
323
665
  raise _codex_error(CodexPluginApprovalRequired("approval required"))
324
666
  try:
325
667
  async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
668
+ before = await bridge.read_plugin(
669
+ plugin_id,
670
+ marketplace_name=payload.marketplace_name,
671
+ )
326
672
  result = await bridge.install_plugin(
327
673
  plugin_id,
328
674
  marketplace_name=payload.marketplace_name,
329
675
  accept_undeclared_permissions=True,
330
676
  install_attempt_id=f"studio-{uuid4().hex}",
331
677
  )
678
+ try:
679
+ snapshot = _commit_codex_snapshot(studio, codex_home, result.inventory)
680
+ except Exception as snapshot_error:
681
+ failure = _snapshot_failure_details(snapshot_error)
682
+ inventory = _public_codex_inventory(
683
+ result.inventory,
684
+ host=bridge.host,
685
+ home_mode=codex_mode,
686
+ )
687
+ if before.inventory.installed:
688
+ raise StudioError(
689
+ "CODEX_PLUGIN_INSTALLED_BUT_UNADMITTED",
690
+ "Codex 插件仍由宿主安装,但未能提交 KsADK 不可变快照",
691
+ status_code=409,
692
+ details={
693
+ "inventory": inventory,
694
+ "snapshotFailure": failure,
695
+ "compensation": "not-attempted-preexisting-install",
696
+ },
697
+ ) from snapshot_error
698
+ try:
699
+ await bridge.uninstall_plugin(result.inventory.plugin_id)
700
+ except Exception as rollback_error:
701
+ raise StudioError(
702
+ "CODEX_PLUGIN_INSTALL_RECONCILIATION_REQUIRED",
703
+ "Codex 插件快照提交失败,且宿主卸载补偿未能确认",
704
+ status_code=409,
705
+ details={
706
+ "inventory": inventory,
707
+ "snapshotFailure": failure,
708
+ "compensation": "uninstall-unconfirmed",
709
+ "compensationFailure": {
710
+ "type": type(rollback_error).__name__,
711
+ "message": str(rollback_error),
712
+ },
713
+ },
714
+ ) from rollback_error
715
+ raise StudioError(
716
+ "CODEX_PLUGIN_SNAPSHOT_FAILED_ROLLED_BACK",
717
+ "Codex 插件快照提交失败;本次新安装已由宿主卸载补偿",
718
+ status_code=409,
719
+ details={
720
+ "pluginId": result.inventory.plugin_id,
721
+ "marketplaceName": result.inventory.marketplace_name,
722
+ "snapshotFailure": failure,
723
+ "compensation": "uninstalled",
724
+ },
725
+ ) from snapshot_error
726
+ snapshot_projection = _public_codex_snapshot(snapshot)
727
+ item = _public_codex_inventory(
728
+ result.inventory, host=bridge.host, home_mode=codex_mode
729
+ )
730
+ if snapshot_projection is not None:
731
+ item.update(
732
+ snapshotDigest=snapshot_projection["snapshotDigest"],
733
+ pluginRef=snapshot_projection["pluginRef"],
734
+ components=snapshot_projection["components"],
735
+ )
332
736
  return {
333
- "item": _public_codex_inventory(
334
- result.inventory, host=bridge.host, home_mode=codex_mode
335
- ),
737
+ "item": item,
738
+ "snapshot": snapshot_projection,
739
+ "snapshotRequired": False,
336
740
  "authPolicy": result.auth_policy,
337
741
  "appsNeedingAuth": list(result.apps_needing_auth),
338
742
  }
@@ -371,58 +775,78 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
371
775
 
372
776
  @app.get("/api/v1/plugin-ecosystems/dsh/profile")
373
777
  async def get_dsh_profile_projection():
374
- host, result = await asyncio.to_thread(
375
- call_dsh, lambda bridge: (bridge.project_profile(), bridge.list_plugins())
778
+ host, projection = await asyncio.to_thread(
779
+ call_dsh, lambda bridge: bridge.project_profile()
376
780
  )
377
- projection, items = result
378
- bundles = [
379
- projected
380
- for item in items
381
- if item.enabled
382
- for projected in [_public_dsh_client_bundle(item)]
383
- if projected is not None
384
- ]
385
- graph_hash = hashlib.sha256(projection.config_digest.encode("utf-8"))
386
- for bundle in bundles:
387
- for value in (str(bundle["pluginId"]), str(bundle["digest"])):
388
- encoded = value.encode("utf-8")
389
- graph_hash.update(f"{len(encoded)}:".encode("ascii"))
390
- graph_hash.update(encoded)
391
781
  return {
392
782
  "host": _public_host("dsh", host, home_mode=dsh_mode),
393
783
  "profile": projection.model_dump(mode="json", by_alias=True),
394
- "clientGraphDigest": f"sha256:{graph_hash.hexdigest()}",
395
- "clientBundles": bundles,
396
784
  }
397
785
 
398
- @app.get("/api/v1/plugin-ecosystems/dsh/client-bundle")
399
- async def get_dsh_client_bundle(
400
- plugin_name: str = Query(alias="pluginName", min_length=1, max_length=256),
401
- digest: str = Query(pattern=r"^sha256:[0-9a-f]{64}$"),
402
- ):
403
- _, content = await asyncio.to_thread(
404
- call_dsh,
405
- lambda bridge: bridge.read_client_bundle(plugin_name, expected_digest=digest),
406
- )
407
- return Response(
408
- content=content,
409
- media_type="application/javascript; charset=utf-8",
410
- headers={
411
- "Cache-Control": "private, max-age=31536000, immutable",
412
- "ETag": f'"{digest}"',
413
- "X-Content-Type-Options": "nosniff",
414
- },
415
- )
786
+ @app.get("/api/v1/plugin-ecosystems/dsh/capabilities")
787
+ async def get_dsh_capabilities():
788
+ snapshot, resource = await studio.dsh_capability_catalog_snapshot()
789
+ descriptor = snapshot.descriptor
790
+ tools = snapshot.tools
791
+ inventory = snapshot.inventory
792
+ return {
793
+ "ecosystem": "dsh",
794
+ "profile": descriptor.profile,
795
+ "profileDigest": descriptor.profile_digest,
796
+ "descriptorDigest": descriptor.descriptor_digest,
797
+ "inventoryDigest": descriptor.inventory_digest,
798
+ "state": inventory.model_dump(by_alias=True, mode="json"),
799
+ "tools": [tool.model_dump(by_alias=True, mode="json") for tool in tools],
800
+ "bindableResource": resource.model_dump(by_alias=True, exclude_none=True, mode="json"),
801
+ }
802
+
803
+ @app.post("/api/v1/plugin-ecosystems/dsh/profile:migrate-layout")
804
+ async def migrate_dsh_profile_layout(payload: DshPluginUpdateRequest):
805
+ if not payload.accept_host_permissions:
806
+ raise _dsh_error(DshPluginApprovalRequired("approval required"))
807
+
808
+ def migrate(bridge: DshProfilePluginBridge):
809
+ bridge.migrate_to_isolated_layout(accept_host_permissions=True)
810
+ return bridge.project_profile()
811
+
812
+ async def operation():
813
+ # Do not release Studio's admission fence while a cancelled HTTP
814
+ # request still has a filesystem migration running in its thread.
815
+ task = asyncio.create_task(asyncio.to_thread(call_dsh, migrate))
816
+ cancelled = False
817
+ while not task.done():
818
+ try:
819
+ await asyncio.shield(task)
820
+ except asyncio.CancelledError:
821
+ cancelled = True
822
+ if cancelled:
823
+ # Retrieve any exception; the reconfiguration owner will recover
824
+ # before allowing another run even when the requester has gone.
825
+ error = task.exception()
826
+ if error is not None:
827
+ raise error
828
+ raise asyncio.CancelledError
829
+ return task.result()
830
+
831
+ host, projection = await studio.reconfigure_dsh_profile(operation)
832
+ return {
833
+ "profile": projection.model_dump(mode="json", by_alias=True),
834
+ "nodeLinker": "isolated",
835
+ "host": {"id": host.host_id, "version": host.version, "available": True},
836
+ }
416
837
 
417
838
  @app.post("/api/v1/plugin-ecosystems/dsh/plugins:install", status_code=201)
418
839
  async def install_dsh_plugin(payload: DshPluginInstallRequest):
419
840
  if not payload.accept_host_permissions:
420
841
  raise _dsh_error(DshPluginApprovalRequired("approval required"))
421
- host, item = await asyncio.to_thread(
422
- call_dsh,
423
- lambda bridge: bridge.install_plugin(payload.source, accept_host_permissions=True),
424
- )
425
- await studio.refresh_dsh_provider_registrations()
842
+
843
+ async def install(): # type: ignore[no-untyped-def]
844
+ return await asyncio.to_thread(
845
+ call_dsh,
846
+ lambda bridge: bridge.install_plugin(payload.source, accept_host_permissions=True),
847
+ )
848
+
849
+ host, item = await studio.reconfigure_dsh_profile(install)
426
850
  return {"item": public_dsh(item, host)}
427
851
 
428
852
  async def mutate_dsh(plugin_name: str, operation: str):
@@ -435,29 +859,36 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
435
859
  return bridge.uninstall_plugin(plugin_name)
436
860
  return bridge.get_plugin(plugin_name)
437
861
 
438
- return await asyncio.to_thread(call_dsh, action)
862
+ if operation == "get":
863
+ return await asyncio.to_thread(call_dsh, action)
864
+
865
+ async def mutate(): # type: ignore[no-untyped-def]
866
+ return await asyncio.to_thread(call_dsh, action)
867
+
868
+ return await studio.reconfigure_dsh_profile(mutate)
439
869
 
440
870
  @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:enable")
441
871
  async def enable_dsh_plugin(plugin_name: str):
442
872
  host, item = await mutate_dsh(plugin_name, "enable")
443
- await studio.refresh_dsh_provider_registrations()
444
873
  return {"item": public_dsh(item, host)}
445
874
 
446
875
  @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:disable")
447
876
  async def disable_dsh_plugin(plugin_name: str):
448
877
  host, item = await mutate_dsh(plugin_name, "disable")
449
- await studio.refresh_dsh_provider_registrations()
450
878
  return {"item": public_dsh(item, host)}
451
879
 
452
880
  @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:update")
453
881
  async def update_dsh_plugin(plugin_name: str, payload: DshPluginUpdateRequest):
454
882
  if not payload.accept_host_permissions:
455
883
  raise _dsh_error(DshPluginApprovalRequired("approval required"))
456
- host, item = await asyncio.to_thread(
457
- call_dsh,
458
- lambda bridge: bridge.update_plugin(plugin_name, accept_host_permissions=True),
459
- )
460
- await studio.refresh_dsh_provider_registrations()
884
+
885
+ async def update(): # type: ignore[no-untyped-def]
886
+ return await asyncio.to_thread(
887
+ call_dsh,
888
+ lambda bridge: bridge.update_plugin(plugin_name, accept_host_permissions=True),
889
+ )
890
+
891
+ host, item = await studio.reconfigure_dsh_profile(update)
461
892
  return {"item": public_dsh(item, host)}
462
893
 
463
894
  @app.get("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}")
@@ -468,12 +899,12 @@ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
468
899
  @app.delete("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}", status_code=204)
469
900
  async def uninstall_dsh_plugin(plugin_name: str):
470
901
  await mutate_dsh(plugin_name, "uninstall")
471
- await studio.refresh_dsh_provider_registrations()
472
902
  return Response(status_code=204)
473
903
 
474
904
 
475
905
  __all__ = [
476
906
  "CodexPluginInstallRequest",
907
+ "CodexPluginSnapshotRequest",
477
908
  "DshPluginInstallRequest",
478
909
  "DshPluginUpdateRequest",
479
910
  "register_plugin_routes",