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,911 @@
1
+ """Studio lifecycle API for DSH plugins and the Codex compatibility bridge."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import base64
7
+ import os
8
+ import re
9
+ from pathlib import Path
10
+ from typing import Any, Callable
11
+ from urllib.parse import urlparse
12
+ from uuid import uuid4
13
+
14
+ from fastapi import FastAPI, Query, Response
15
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
16
+
17
+ from ksadk.plugins.bridges.codex import (
18
+ CodexAppServerPluginBridge,
19
+ CodexBridgeHost,
20
+ CodexPluginApprovalRequired,
21
+ CodexPluginDetail,
22
+ CodexPluginInventory,
23
+ CodexPluginNotFoundError,
24
+ )
25
+ from ksadk.plugins.bridges.dsh import (
26
+ DshBridgeHost,
27
+ DshHostUnavailableError,
28
+ DshPluginApprovalRequired,
29
+ DshPluginInventory,
30
+ DshPluginMutationError,
31
+ DshPluginNotFoundError,
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,
40
+ )
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
+ )
48
+ from ksadk.studio.errors import StudioError
49
+ from ksadk.studio.service import StudioService
50
+
51
+
52
+ class CodexPluginInstallRequest(BaseModel):
53
+ model_config = ConfigDict(extra="forbid", populate_by_name=True)
54
+ marketplace_name: str | None = Field(
55
+ default=None, alias="marketplaceName", min_length=1, max_length=256
56
+ )
57
+ accept_undeclared_permissions: bool = Field(default=False, alias="acceptUndeclaredPermissions")
58
+
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
+
67
+ class DshPluginInstallRequest(BaseModel):
68
+ model_config = ConfigDict(extra="forbid", populate_by_name=True)
69
+ source: str = Field(min_length=1, max_length=2048)
70
+ accept_host_permissions: bool = Field(default=False, alias="acceptHostPermissions")
71
+
72
+ @field_validator("source")
73
+ @classmethod
74
+ def validate_source(cls, value: str) -> str:
75
+ normalized = value.strip()
76
+ if not normalized or any(character in value for character in ("\x00", "\r", "\n")):
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)
87
+
88
+
89
+ class DshPluginUpdateRequest(BaseModel):
90
+ model_config = ConfigDict(extra="forbid", populate_by_name=True)
91
+ accept_host_permissions: bool = Field(default=False, alias="acceptHostPermissions")
92
+
93
+
94
+ def _studio_codex_home(studio: StudioService) -> tuple[Path, str]:
95
+ configured = os.environ.get("KSADK_CODEX_HOME", "").strip()
96
+ if configured:
97
+ return Path(configured).expanduser(), "explicit"
98
+ return studio.workspace.root / ".agentkit" / "codex-home", "workspace-isolated"
99
+
100
+
101
+ def _studio_dsh_options(studio: StudioService) -> tuple[Path, str, tuple[str, ...] | None, str]:
102
+ configured_home = os.environ.get("KSADK_DSH_HOME", "").strip()
103
+ home = (
104
+ Path(configured_home).expanduser()
105
+ if configured_home
106
+ else studio.workspace.root / ".agentkit" / "dsh-home"
107
+ )
108
+ configured_bin = os.environ.get("KSADK_DSH_BIN", "").strip()
109
+ if configured_bin:
110
+ command = (str(Path(configured_bin).expanduser()),)
111
+ else:
112
+ try:
113
+ command = DshToolchainManager().require_command()
114
+ except (DshToolchainError, OSError, ValueError):
115
+ # Keep the bridge's established PATH lookup when the optional
116
+ # pinned toolchain has not been installed or is unusable.
117
+ command = None
118
+ profile = os.environ.get("KSADK_DSH_PROFILE", "").strip() or "web"
119
+ return home, profile, command, "explicit" if configured_home else "workspace-isolated"
120
+
121
+
122
+ def _public_host(kind: str, host: Any | None, *, home_mode: str) -> dict[str, Any]:
123
+ codex = kind == "codex"
124
+ return {
125
+ "hostId": "codex-app-server" if codex else "deepseek-harness",
126
+ "available": host is not None,
127
+ "status": "available" if host is not None else "unavailable",
128
+ "version": host.version if host is not None else None,
129
+ "protocol": host.protocol
130
+ if host is not None
131
+ else ("codex.app-server/v1" if codex else "dsh.profile/v1"),
132
+ "homeMode": home_mode,
133
+ }
134
+
135
+
136
+ def _public_codex_source(source: BaseModel) -> dict[str, Any]:
137
+ raw = source.model_dump(by_alias=True, mode="json")
138
+ source_type = str(raw.get("type") or "remote")
139
+ payload: dict[str, Any] = {"type": source_type}
140
+ if source_type == "local":
141
+ payload["name"] = Path(str(raw.get("path") or "plugin")).name or "plugin"
142
+ elif source_type == "git":
143
+ payload["name"] = Path(urlparse(str(raw.get("url") or "")).path.rstrip("/")).name
144
+ for key in ("refName", "sha"):
145
+ if raw.get(key):
146
+ payload[key] = raw[key]
147
+ elif source_type == "npm":
148
+ payload.update(package=raw.get("package"), version=raw.get("version"))
149
+ return payload
150
+
151
+
152
+ def _public_codex_inventory(
153
+ inventory: CodexPluginInventory, *, host: CodexBridgeHost, home_mode: str
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
160
+ return {
161
+ "ecosystem": "codex",
162
+ "integrationMode": "bridged",
163
+ "pluginId": inventory.plugin_id,
164
+ "resolvedVersion": inventory.version,
165
+ "distributionName": inventory.name,
166
+ "displayName": inventory.interface.get("displayName") or inventory.name,
167
+ "description": inventory.interface.get("shortDescription"),
168
+ "interface": presentation,
169
+ "marketplaceName": inventory.marketplace_name,
170
+ "source": _public_codex_source(inventory.source),
171
+ "installed": inventory.installed,
172
+ "state": "enabled" if inventory.enabled else "disabled",
173
+ "enabled": inventory.enabled,
174
+ "availability": inventory.availability,
175
+ "permissions": [],
176
+ "permissionsDeclared": False,
177
+ "riskDisclosures": list(inventory.risk_disclosures),
178
+ "isolation": "host-managed",
179
+ "runtimeState": None,
180
+ "host": _public_host("codex", host, home_mode=home_mode),
181
+ }
182
+
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
+
251
+ def _public_codex_detail(
252
+ detail: CodexPluginDetail,
253
+ *,
254
+ host: CodexBridgeHost,
255
+ home_mode: str,
256
+ snapshot: CodexWorkspacePluginSnapshot | None = None,
257
+ ) -> dict[str, Any]:
258
+ payload = {
259
+ "item": _public_codex_inventory(detail.inventory, host=host, home_mode=home_mode),
260
+ "description": detail.description,
261
+ "capabilities": {
262
+ "skills": list(detail.skills),
263
+ "mcpServers": list(detail.mcp_servers),
264
+ "hooks": list(detail.hooks),
265
+ "apps": list(detail.apps),
266
+ "scheduledTasks": list(detail.scheduled_tasks),
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
+ ],
451
+ }
452
+
453
+
454
+ def _public_dsh_inventory(
455
+ inventory: DshPluginInventory,
456
+ *,
457
+ host: DshBridgeHost,
458
+ home_mode: str,
459
+ runtime_state: dict[str, Any] | None = None,
460
+ ) -> dict[str, Any]:
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
+ }
475
+ return {
476
+ "ecosystem": "dsh",
477
+ "integrationMode": "bridged",
478
+ "pluginId": inventory.name,
479
+ "resolvedVersion": inventory.version,
480
+ "distributionName": inventory.name,
481
+ "displayName": inventory.display_name,
482
+ "description": inventory.description,
483
+ "clientExtension": inventory.client_extension,
484
+ "settingsIntegration": inventory.settings_integration,
485
+ "profile": inventory.profile,
486
+ "source": source,
487
+ "installed": True,
488
+ "state": "enabled" if inventory.enabled else "disabled",
489
+ "enabled": inventory.enabled,
490
+ "permissions": [],
491
+ "permissionsDeclared": False,
492
+ "riskDisclosures": list(inventory.risk_disclosures),
493
+ "isolation": "host-managed",
494
+ "runtimeState": runtime_state,
495
+ "host": _public_host("dsh", host, home_mode=home_mode),
496
+ }
497
+
498
+
499
+ def _codex_error(error: Exception) -> StudioError:
500
+ if isinstance(error, StudioError):
501
+ return error
502
+ if isinstance(error, CodexPluginNotFoundError):
503
+ return StudioError(
504
+ "CODEX_PLUGIN_NOT_FOUND", "Codex 插件不存在或来源不唯一", status_code=404
505
+ )
506
+ if isinstance(error, CodexPluginApprovalRequired):
507
+ return StudioError(
508
+ "CODEX_PLUGIN_RISK_CONFIRMATION_REQUIRED",
509
+ "安装 Codex 插件前必须确认宿主权限风险",
510
+ status_code=422,
511
+ )
512
+ return StudioError("CODEX_PLUGIN_HOST_UNAVAILABLE", "Codex 插件宿主当前不可用", status_code=503)
513
+
514
+
515
+ def _dsh_error(error: Exception) -> StudioError:
516
+ if isinstance(error, DshPluginNotFoundError):
517
+ return StudioError("DSH_PLUGIN_NOT_FOUND", "DSH 插件未安装", status_code=404)
518
+ if isinstance(error, DshPluginApprovalRequired):
519
+ return StudioError(
520
+ "DSH_PLUGIN_RISK_CONFIRMATION_REQUIRED",
521
+ "安装或升级 DSH 插件前必须确认宿主权限风险",
522
+ status_code=422,
523
+ )
524
+ if isinstance(error, DshProfileRecoveryError):
525
+ return StudioError(
526
+ "DSH_PROFILE_RECOVERY_REQUIRED",
527
+ "Profile 迁移恢复失败,已保留恢复备份并暂停运行准入",
528
+ status_code=503,
529
+ )
530
+ if isinstance(error, DshPluginMutationError):
531
+ return StudioError(
532
+ "DSH_PLUGIN_MUTATION_FAILED", "DSH 插件操作失败,原 Profile 已保留", status_code=409
533
+ )
534
+ if isinstance(error, (DshHostUnavailableError, OSError)):
535
+ return StudioError("DSH_PLUGIN_HOST_UNAVAILABLE", "DSH 插件宿主当前不可用", status_code=503)
536
+ return StudioError("DSH_PLUGIN_OPERATION_FAILED", "DSH 插件操作失败", status_code=422)
537
+
538
+
539
+ def register_plugin_routes(app: FastAPI, studio: StudioService) -> None:
540
+ """Register only DSH Profile and Codex App Server lifecycle routes."""
541
+
542
+ codex_home, codex_mode = _studio_codex_home(studio)
543
+ dsh_home, dsh_profile, dsh_command, dsh_mode = _studio_dsh_options(studio)
544
+
545
+ def public_dsh(item: DshPluginInventory, host: DshBridgeHost) -> dict[str, Any]:
546
+ return _public_dsh_inventory(
547
+ item,
548
+ host=host,
549
+ home_mode=dsh_mode,
550
+ runtime_state=studio.dsh_provider_runtime_state(item.name),
551
+ )
552
+
553
+ def call_dsh(operation: Callable[[DshProfilePluginBridge], Any]) -> Any:
554
+ try:
555
+ with DshProfilePluginBridge(
556
+ dsh_home=dsh_home, profile=dsh_profile, dsh_command=dsh_command
557
+ ) as bridge:
558
+ return bridge.host, operation(bridge)
559
+ except Exception as error:
560
+ raise _dsh_error(error) from None
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
+
590
+ @app.get("/api/v1/plugin-ecosystems/codex/plugins")
591
+ async def list_codex_plugins(
592
+ installed_only: bool = Query(default=False), force_refetch: bool = Query(default=False)
593
+ ):
594
+ try:
595
+ async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
596
+ items = await bridge.list_plugins(force_refetch=force_refetch)
597
+ visible = [item for item in items if item.installed or not installed_only]
598
+ return {
599
+ "ecosystem": "codex",
600
+ "integrationMode": "bridged",
601
+ "host": _public_host("codex", bridge.host, home_mode=codex_mode),
602
+ "items": [
603
+ _public_codex_inventory(item, host=bridge.host, home_mode=codex_mode)
604
+ for item in visible
605
+ ],
606
+ }
607
+ except Exception:
608
+ return {
609
+ "ecosystem": "codex",
610
+ "integrationMode": "bridged",
611
+ "host": _public_host("codex", None, home_mode=codex_mode),
612
+ "items": [],
613
+ "error": {
614
+ "code": "CODEX_PLUGIN_HOST_UNAVAILABLE",
615
+ "message": "Codex 插件宿主当前不可用",
616
+ },
617
+ }
618
+
619
+ @app.get("/api/v1/plugin-ecosystems/codex/plugins/{plugin_id}")
620
+ async def get_codex_plugin(
621
+ plugin_id: str, marketplace_name: str | None = Query(default=None, max_length=256)
622
+ ):
623
+ try:
624
+ async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
625
+ detail = await bridge.read_plugin(plugin_id, marketplace_name=marketplace_name)
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}
659
+ except Exception as error:
660
+ raise _codex_error(error) from None
661
+
662
+ @app.post("/api/v1/plugin-ecosystems/codex/plugins/{plugin_id}:install")
663
+ async def install_codex_plugin(plugin_id: str, payload: CodexPluginInstallRequest):
664
+ if not payload.accept_undeclared_permissions:
665
+ raise _codex_error(CodexPluginApprovalRequired("approval required"))
666
+ try:
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
+ )
672
+ result = await bridge.install_plugin(
673
+ plugin_id,
674
+ marketplace_name=payload.marketplace_name,
675
+ accept_undeclared_permissions=True,
676
+ install_attempt_id=f"studio-{uuid4().hex}",
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
+ )
736
+ return {
737
+ "item": item,
738
+ "snapshot": snapshot_projection,
739
+ "snapshotRequired": False,
740
+ "authPolicy": result.auth_policy,
741
+ "appsNeedingAuth": list(result.apps_needing_auth),
742
+ }
743
+ except Exception as error:
744
+ raise _codex_error(error) from None
745
+
746
+ @app.delete("/api/v1/plugin-ecosystems/codex/plugins/{plugin_id}", status_code=204)
747
+ async def uninstall_codex_plugin(plugin_id: str):
748
+ try:
749
+ async with CodexAppServerPluginBridge(codex_home=codex_home) as bridge:
750
+ await bridge.uninstall_plugin(plugin_id)
751
+ return Response(status_code=204)
752
+ except Exception as error:
753
+ raise _codex_error(error) from None
754
+
755
+ @app.get("/api/v1/plugin-ecosystems/dsh/plugins")
756
+ async def list_dsh_plugins():
757
+ try:
758
+ host, items = await asyncio.to_thread(call_dsh, lambda bridge: bridge.list_plugins())
759
+ return {
760
+ "ecosystem": "dsh",
761
+ "integrationMode": "bridged",
762
+ "profile": dsh_profile,
763
+ "host": _public_host("dsh", host, home_mode=dsh_mode),
764
+ "items": [public_dsh(item, host) for item in items],
765
+ }
766
+ except StudioError as error:
767
+ return {
768
+ "ecosystem": "dsh",
769
+ "integrationMode": "bridged",
770
+ "profile": dsh_profile,
771
+ "host": _public_host("dsh", None, home_mode=dsh_mode),
772
+ "items": [],
773
+ "error": {"code": error.code, "message": error.message},
774
+ }
775
+
776
+ @app.get("/api/v1/plugin-ecosystems/dsh/profile")
777
+ async def get_dsh_profile_projection():
778
+ host, projection = await asyncio.to_thread(
779
+ call_dsh, lambda bridge: bridge.project_profile()
780
+ )
781
+ return {
782
+ "host": _public_host("dsh", host, home_mode=dsh_mode),
783
+ "profile": projection.model_dump(mode="json", by_alias=True),
784
+ }
785
+
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
+ }
837
+
838
+ @app.post("/api/v1/plugin-ecosystems/dsh/plugins:install", status_code=201)
839
+ async def install_dsh_plugin(payload: DshPluginInstallRequest):
840
+ if not payload.accept_host_permissions:
841
+ raise _dsh_error(DshPluginApprovalRequired("approval required"))
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)
850
+ return {"item": public_dsh(item, host)}
851
+
852
+ async def mutate_dsh(plugin_name: str, operation: str):
853
+ def action(bridge: DshProfilePluginBridge):
854
+ if operation == "enable":
855
+ return bridge.set_enabled(plugin_name, enabled=True)
856
+ if operation == "disable":
857
+ return bridge.set_enabled(plugin_name, enabled=False)
858
+ if operation == "uninstall":
859
+ return bridge.uninstall_plugin(plugin_name)
860
+ return bridge.get_plugin(plugin_name)
861
+
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)
869
+
870
+ @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:enable")
871
+ async def enable_dsh_plugin(plugin_name: str):
872
+ host, item = await mutate_dsh(plugin_name, "enable")
873
+ return {"item": public_dsh(item, host)}
874
+
875
+ @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:disable")
876
+ async def disable_dsh_plugin(plugin_name: str):
877
+ host, item = await mutate_dsh(plugin_name, "disable")
878
+ return {"item": public_dsh(item, host)}
879
+
880
+ @app.post("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}:update")
881
+ async def update_dsh_plugin(plugin_name: str, payload: DshPluginUpdateRequest):
882
+ if not payload.accept_host_permissions:
883
+ raise _dsh_error(DshPluginApprovalRequired("approval required"))
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)
892
+ return {"item": public_dsh(item, host)}
893
+
894
+ @app.get("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}")
895
+ async def get_dsh_plugin(plugin_name: str):
896
+ host, item = await mutate_dsh(plugin_name, "get")
897
+ return {"item": public_dsh(item, host)}
898
+
899
+ @app.delete("/api/v1/plugin-ecosystems/dsh/plugins/{plugin_name:path}", status_code=204)
900
+ async def uninstall_dsh_plugin(plugin_name: str):
901
+ await mutate_dsh(plugin_name, "uninstall")
902
+ return Response(status_code=204)
903
+
904
+
905
+ __all__ = [
906
+ "CodexPluginInstallRequest",
907
+ "CodexPluginSnapshotRequest",
908
+ "DshPluginInstallRequest",
909
+ "DshPluginUpdateRequest",
910
+ "register_plugin_routes",
911
+ ]