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,746 @@
1
+ """Immutable workspace snapshots and selective Codex plugin marketplaces.
2
+
3
+ Codex App Server owns plugin installation. Studio admits the installed bytes
4
+ into a content-addressed workspace store, then builds a small local
5
+ marketplace from those immutable bytes. Neither operation writes Codex's
6
+ host-managed cache directly.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import os
14
+ import re
15
+ import shutil
16
+ import stat
17
+ import tempfile
18
+ from pathlib import Path, PurePosixPath
19
+ from typing import Any, Iterable, Literal
20
+
21
+ from pydantic import Field, field_validator
22
+
23
+ from ksadk.plugins.codex_manifest import (
24
+ CodexInstalledPluginSnapshot,
25
+ CodexPluginComponentSnapshot,
26
+ CodexPluginManifest,
27
+ CodexPluginManifestError,
28
+ CodexPluginSourceCoordinate,
29
+ _load_installed_plugin,
30
+ snapshot_installed_codex_plugin,
31
+ )
32
+ from ksadk.studio.contracts import ContractModel
33
+ from ksadk.studio.errors import StudioError
34
+ from ksadk.studio.workspace import Workspace
35
+
36
+ _DIGEST = re.compile(r"^sha256:[0-9a-f]{64}$")
37
+ _PLUGIN_ID = re.compile(r"^[a-z0-9]+(?:[._-][a-z0-9]+)*$")
38
+ _SELECTOR = re.compile(r"^(skill|mcp|hook|app):(.+)$")
39
+ _CACHE_SEGMENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,255}$")
40
+
41
+
42
+ class CodexWorkspacePluginSnapshot(ContractModel):
43
+ """Receipt for bytes copied into the workspace content-addressed store."""
44
+
45
+ snapshot_format: Literal["codex.workspace-plugin-snapshot/v1"] = (
46
+ "codex.workspace-plugin-snapshot/v1"
47
+ )
48
+ snapshot_digest: str
49
+ plugin_ref: str = Field(min_length=12, max_length=256)
50
+ content_path: str = Field(min_length=1, max_length=4096)
51
+ source: CodexPluginSourceCoordinate
52
+ manifest: CodexPluginManifest
53
+ manifest_digest: str
54
+ artifact_digest: str
55
+ components: tuple[CodexPluginComponentSnapshot, ...] = ()
56
+
57
+ @field_validator("snapshot_digest", "manifest_digest", "artifact_digest")
58
+ @classmethod
59
+ def validate_digest(cls, value: str) -> str:
60
+ if _DIGEST.fullmatch(value) is None:
61
+ raise ValueError("Codex snapshot digests must be lowercase sha256 values")
62
+ return value
63
+
64
+ @field_validator("content_path")
65
+ @classmethod
66
+ def validate_content_path(cls, value: str) -> str:
67
+ if "\\" in value:
68
+ raise ValueError("Codex snapshot contentPath must use POSIX separators")
69
+ path = PurePosixPath(value)
70
+ if path.is_absolute() or any(part in {"", ".", ".."} for part in path.parts):
71
+ raise ValueError("Codex snapshot contentPath must be workspace-relative")
72
+ return value
73
+
74
+ def select_components(
75
+ self, selectors: Iterable[str]
76
+ ) -> tuple[CodexPluginComponentSnapshot, ...]:
77
+ requested = tuple(dict.fromkeys(str(item) for item in selectors))
78
+ by_selector = {component_selector(component): component for component in self.components}
79
+ missing = [selector for selector in requested if selector not in by_selector]
80
+ if missing:
81
+ raise StudioError(
82
+ "CODEX_PLUGIN_COMPONENT_NOT_FOUND",
83
+ "Codex 插件绑定引用了快照中不存在的组件",
84
+ status_code=422,
85
+ details={"pluginRef": self.plugin_ref, "components": missing},
86
+ )
87
+ return tuple(by_selector[selector] for selector in requested)
88
+
89
+
90
+ class CodexPinnedMarketplace(ContractModel):
91
+ marketplace_format: Literal["codex.pinned-marketplace/v1"] = "codex.pinned-marketplace/v1"
92
+ marketplace_name: str
93
+ marketplace_path: str
94
+ marketplace_digest: str
95
+ plugin_names: tuple[str, ...]
96
+ plugin_lock_digest: str
97
+
98
+ @field_validator("marketplace_digest", "plugin_lock_digest")
99
+ @classmethod
100
+ def validate_digest(cls, value: str) -> str:
101
+ if _DIGEST.fullmatch(value) is None:
102
+ raise ValueError("Codex marketplace digests must be lowercase sha256 values")
103
+ return value
104
+
105
+
106
+ def component_selector(component: CodexPluginComponentSnapshot) -> str:
107
+ return f"{component.kind}:{component.name}"
108
+
109
+
110
+ def codex_plugin_ref(manifest: CodexPluginManifest) -> str:
111
+ version = str(manifest.version or "")
112
+ if not version:
113
+ raise StudioError(
114
+ "CODEX_PLUGIN_VERSION_REQUIRED",
115
+ "Codex 插件必须声明精确版本后才能提交不可变快照",
116
+ status_code=422,
117
+ field="version",
118
+ )
119
+ candidate = str(manifest.id or "").strip().lower()
120
+ if not candidate or _PLUGIN_ID.fullmatch(candidate) is None:
121
+ candidate = f"codex.{manifest.name.lower()}"
122
+ if len(candidate) > 128 or _PLUGIN_ID.fullmatch(candidate) is None:
123
+ raise StudioError(
124
+ "CODEX_PLUGIN_ID_INVALID",
125
+ "Codex 插件无法映射为稳定的 plugin reference",
126
+ status_code=422,
127
+ details={"name": manifest.name, "id": manifest.id},
128
+ )
129
+ return f"plugin://{candidate}@{version}"
130
+
131
+
132
+ def _canonical_bytes(value: Any) -> bytes:
133
+ return json.dumps(
134
+ value,
135
+ ensure_ascii=False,
136
+ sort_keys=True,
137
+ separators=(",", ":"),
138
+ ).encode("utf-8")
139
+
140
+
141
+ def _sha256(raw: bytes) -> str:
142
+ return "sha256:" + hashlib.sha256(raw).hexdigest()
143
+
144
+
145
+ def _snapshot_identity(snapshot: CodexInstalledPluginSnapshot) -> dict[str, Any]:
146
+ return {
147
+ "source": snapshot.source.model_dump(by_alias=True, exclude_none=True, mode="json"),
148
+ "manifest": snapshot.manifest.model_dump(by_alias=True, exclude_none=True, mode="json"),
149
+ "manifestDigest": snapshot.manifest_digest,
150
+ "artifactDigest": snapshot.artifact_digest,
151
+ "components": [
152
+ item.model_dump(by_alias=True, exclude_none=True, mode="json")
153
+ for item in snapshot.components
154
+ ],
155
+ }
156
+
157
+
158
+ def _snapshot_digest(snapshot: CodexInstalledPluginSnapshot) -> str:
159
+ return _sha256(_canonical_bytes(_snapshot_identity(snapshot)))
160
+
161
+
162
+ def _same_snapshot(
163
+ expected: CodexInstalledPluginSnapshot,
164
+ actual: CodexInstalledPluginSnapshot,
165
+ ) -> bool:
166
+ return _snapshot_identity(expected) == _snapshot_identity(actual)
167
+
168
+
169
+ def _tree_digest(root: Path) -> str:
170
+ digest = hashlib.sha256()
171
+ for candidate in sorted(root.rglob("*"), key=lambda path: path.relative_to(root).as_posix()):
172
+ relative = candidate.relative_to(root).as_posix()
173
+ if candidate.is_symlink():
174
+ raise StudioError(
175
+ "CODEX_PLUGIN_MARKETPLACE_INVALID",
176
+ "固定 Codex marketplace 不能包含符号链接",
177
+ status_code=409,
178
+ details={"path": relative},
179
+ )
180
+ if candidate.is_dir():
181
+ continue
182
+ if not candidate.is_file():
183
+ raise StudioError(
184
+ "CODEX_PLUGIN_MARKETPLACE_INVALID",
185
+ "固定 Codex marketplace 只能包含常规文件",
186
+ status_code=409,
187
+ details={"path": relative},
188
+ )
189
+ raw = candidate.read_bytes()
190
+ digest.update(relative.encode("utf-8"))
191
+ digest.update(b"\0")
192
+ digest.update(f"{stat.S_IMODE(candidate.stat().st_mode) & 0o111:03o}".encode("ascii"))
193
+ digest.update(b"\0")
194
+ digest.update(str(len(raw)).encode("ascii"))
195
+ digest.update(b"\0")
196
+ digest.update(raw)
197
+ digest.update(b"\0")
198
+ return "sha256:" + digest.hexdigest()
199
+
200
+
201
+ class CodexPluginSnapshotStore:
202
+ """Content-addressed, copy-then-rehash store for installed Codex plugins."""
203
+
204
+ def __init__(self, workspace: Workspace) -> None:
205
+ self.workspace = workspace
206
+ self.root = workspace.resolve(".agentkit/codex-plugin-snapshots")
207
+
208
+ def lookup(self, snapshot: CodexInstalledPluginSnapshot) -> CodexWorkspacePluginSnapshot | None:
209
+ """Return an already-admitted snapshot without mutating the workspace.
210
+
211
+ The installed bytes still need to be hashed to derive their content
212
+ address. Unlike :meth:`commit`, lookup never creates directories or
213
+ copies host-owned plugin bytes.
214
+ """
215
+
216
+ digest = _snapshot_digest(snapshot)
217
+ receipt = self.root / digest.removeprefix("sha256:") / "snapshot.json"
218
+ if not receipt.is_file():
219
+ return None
220
+ return self.load(digest)
221
+
222
+ def commit(self, snapshot: CodexInstalledPluginSnapshot) -> CodexWorkspacePluginSnapshot:
223
+ source_root = Path(snapshot.installed_root)
224
+ try:
225
+ observed = snapshot_installed_codex_plugin(source_root, source=snapshot.source)
226
+ except CodexPluginManifestError as exc:
227
+ raise StudioError(
228
+ "CODEX_PLUGIN_SNAPSHOT_INVALID",
229
+ "Codex 插件安装目录无法提交快照",
230
+ status_code=422,
231
+ details={"reason": str(exc)},
232
+ ) from exc
233
+ if not _same_snapshot(snapshot, observed):
234
+ raise StudioError(
235
+ "CODEX_PLUGIN_SOURCE_DRIFT",
236
+ "Codex 插件在提交快照前已发生变化",
237
+ status_code=409,
238
+ details={
239
+ "expected": snapshot.artifact_digest,
240
+ "actual": observed.artifact_digest,
241
+ },
242
+ )
243
+
244
+ digest = _snapshot_digest(observed)
245
+ suffix = digest.removeprefix("sha256:")
246
+ destination = self.workspace.resolve(self.root / suffix)
247
+ if destination.exists():
248
+ return self.load(digest)
249
+
250
+ self.root.mkdir(parents=True, exist_ok=True)
251
+ staging = Path(tempfile.mkdtemp(prefix=".codex-plugin-", dir=self.root))
252
+ try:
253
+ content = staging / "content"
254
+ # Preserve a racing symlink as a symlink. The second parser/hash
255
+ # rejects it instead of following it outside the admitted root.
256
+ shutil.copytree(source_root, content, symlinks=True)
257
+ try:
258
+ copied = snapshot_installed_codex_plugin(content, source=observed.source)
259
+ except CodexPluginManifestError as exc:
260
+ raise StudioError(
261
+ "CODEX_PLUGIN_COPY_DRIFT",
262
+ "Codex 插件复制期间发生不安全或不一致的变化",
263
+ status_code=409,
264
+ details={"reason": str(exc)},
265
+ ) from exc
266
+ if not _same_snapshot(observed, copied):
267
+ raise StudioError(
268
+ "CODEX_PLUGIN_COPY_DRIFT",
269
+ "Codex 插件复制后的二次摘要不一致",
270
+ status_code=409,
271
+ details={
272
+ "expected": observed.artifact_digest,
273
+ "actual": copied.artifact_digest,
274
+ },
275
+ )
276
+
277
+ content_path = (destination / "content").relative_to(self.workspace.root).as_posix()
278
+ record = CodexWorkspacePluginSnapshot(
279
+ snapshot_digest=digest,
280
+ plugin_ref=codex_plugin_ref(copied.manifest),
281
+ content_path=content_path,
282
+ source=copied.source,
283
+ manifest=copied.manifest,
284
+ manifest_digest=copied.manifest_digest,
285
+ artifact_digest=copied.artifact_digest,
286
+ components=copied.components,
287
+ )
288
+ (staging / "snapshot.json").write_bytes(
289
+ json.dumps(
290
+ record.model_dump(by_alias=True, exclude_none=True, mode="json"),
291
+ ensure_ascii=False,
292
+ indent=2,
293
+ sort_keys=True,
294
+ ).encode("utf-8")
295
+ + b"\n"
296
+ )
297
+ try:
298
+ os.replace(staging, destination)
299
+ except FileExistsError:
300
+ # A concurrent identical commit won the content-addressed path.
301
+ pass
302
+ finally:
303
+ if staging.exists():
304
+ shutil.rmtree(staging)
305
+ return self.load(digest)
306
+
307
+ def load(self, digest: str) -> CodexWorkspacePluginSnapshot:
308
+ if _DIGEST.fullmatch(digest) is None:
309
+ raise StudioError(
310
+ "CODEX_PLUGIN_SNAPSHOT_DIGEST_INVALID",
311
+ "Codex 插件快照摘要格式无效",
312
+ status_code=422,
313
+ )
314
+ suffix = digest.removeprefix("sha256:")
315
+ directory = self.workspace.resolve(self.root / suffix)
316
+ receipt_path = self.workspace.resolve(directory / "snapshot.json")
317
+ if not receipt_path.is_file():
318
+ raise StudioError(
319
+ "CODEX_PLUGIN_SNAPSHOT_NOT_FOUND",
320
+ "Codex 插件快照不存在",
321
+ status_code=404,
322
+ details={"snapshotDigest": digest},
323
+ )
324
+ try:
325
+ record = CodexWorkspacePluginSnapshot.model_validate_json(
326
+ receipt_path.read_text(encoding="utf-8")
327
+ )
328
+ except (OSError, ValueError) as exc:
329
+ raise StudioError(
330
+ "CODEX_PLUGIN_SNAPSHOT_RECEIPT_INVALID",
331
+ "Codex 插件快照记录损坏",
332
+ status_code=409,
333
+ details={"snapshotDigest": digest},
334
+ ) from exc
335
+ expected_content = (directory / "content").relative_to(self.workspace.root).as_posix()
336
+ if record.snapshot_digest != digest or record.content_path != expected_content:
337
+ raise StudioError(
338
+ "CODEX_PLUGIN_SNAPSHOT_RECEIPT_INVALID",
339
+ "Codex 插件快照记录与内容地址不一致",
340
+ status_code=409,
341
+ details={"snapshotDigest": digest},
342
+ )
343
+ content = self.workspace.resolve(record.content_path)
344
+ try:
345
+ observed = snapshot_installed_codex_plugin(content, source=record.source)
346
+ except CodexPluginManifestError as exc:
347
+ raise StudioError(
348
+ "CODEX_PLUGIN_SNAPSHOT_DRIFT",
349
+ "Codex 插件不可变快照已损坏或漂移",
350
+ status_code=409,
351
+ details={"snapshotDigest": digest, "reason": str(exc)},
352
+ ) from exc
353
+ expected = CodexInstalledPluginSnapshot(
354
+ installed_root=str(content),
355
+ source=record.source,
356
+ manifest=record.manifest,
357
+ manifest_digest=record.manifest_digest,
358
+ artifact_digest=record.artifact_digest,
359
+ components=record.components,
360
+ )
361
+ if not _same_snapshot(expected, observed) or _snapshot_digest(observed) != digest:
362
+ raise StudioError(
363
+ "CODEX_PLUGIN_SNAPSHOT_DRIFT",
364
+ "Codex 插件不可变快照的内容摘要已漂移",
365
+ status_code=409,
366
+ details={
367
+ "snapshotDigest": digest,
368
+ "expectedArtifactDigest": record.artifact_digest,
369
+ "actualArtifactDigest": observed.artifact_digest,
370
+ },
371
+ )
372
+ return record
373
+
374
+ def content_root(self, snapshot: CodexWorkspacePluginSnapshot) -> Path:
375
+ return self.workspace.resolve(snapshot.content_path, must_exist=True)
376
+
377
+ def verify_marketplace(self, receipt: CodexPinnedMarketplace) -> Path:
378
+ root = self.workspace.resolve(receipt.marketplace_path, must_exist=True)
379
+ actual = _tree_digest(root)
380
+ if actual != receipt.marketplace_digest:
381
+ raise StudioError(
382
+ "CODEX_PLUGIN_MARKETPLACE_DRIFT",
383
+ "固定 Codex marketplace 已发生漂移",
384
+ status_code=409,
385
+ details={
386
+ "pluginLockDigest": receipt.plugin_lock_digest,
387
+ "expected": receipt.marketplace_digest,
388
+ "actual": actual,
389
+ },
390
+ )
391
+ return root
392
+
393
+ def materialize_marketplace(
394
+ self,
395
+ *,
396
+ plugin_lock_digest: str,
397
+ selections: Iterable[
398
+ tuple[CodexWorkspacePluginSnapshot, tuple[CodexPluginComponentSnapshot, ...]]
399
+ ],
400
+ ) -> CodexPinnedMarketplace:
401
+ """Build a deterministic local marketplace with selected declarations only."""
402
+
403
+ if _DIGEST.fullmatch(plugin_lock_digest) is None:
404
+ raise ValueError("plugin_lock_digest must be a lowercase sha256 digest")
405
+ selected_plugins = tuple(selections)
406
+ suffix = plugin_lock_digest.removeprefix("sha256:")
407
+ directory = self.workspace.resolve(Path(".agentkit/codex-plugin-marketplaces") / suffix)
408
+ receipt_path = directory / "receipt.json"
409
+ if receipt_path.is_file():
410
+ receipt = CodexPinnedMarketplace.model_validate_json(
411
+ receipt_path.read_text(encoding="utf-8")
412
+ )
413
+ root = self.workspace.resolve(receipt.marketplace_path, must_exist=True)
414
+ if (
415
+ receipt.plugin_lock_digest != plugin_lock_digest
416
+ or _tree_digest(root) != receipt.marketplace_digest
417
+ ):
418
+ raise StudioError(
419
+ "CODEX_PLUGIN_MARKETPLACE_DRIFT",
420
+ "固定 Codex marketplace 已发生漂移",
421
+ status_code=409,
422
+ details={"pluginLockDigest": plugin_lock_digest},
423
+ )
424
+ return receipt
425
+
426
+ directory.parent.mkdir(parents=True, exist_ok=True)
427
+ staging = Path(tempfile.mkdtemp(prefix=".codex-marketplace-", dir=directory.parent))
428
+ try:
429
+ root = staging / "marketplace"
430
+ plugins_root = root / "plugins"
431
+ plugins_root.mkdir(parents=True)
432
+ plugin_entries: list[dict[str, Any]] = []
433
+ plugin_names: list[str] = []
434
+ ordered_plugins = sorted(
435
+ selected_plugins,
436
+ key=lambda item: (item[0].manifest.name, item[0].plugin_ref),
437
+ )
438
+ names = [item[0].manifest.name for item in ordered_plugins]
439
+ if len(names) != len(set(names)):
440
+ raise StudioError(
441
+ "CODEX_PLUGIN_MARKETPLACE_NAME_CONFLICT",
442
+ "多个 Codex 插件快照映射到相同的原生插件名称",
443
+ status_code=422,
444
+ details={"pluginNames": names},
445
+ )
446
+ for snapshot, components in ordered_plugins:
447
+ # Revalidate the immutable source immediately before copying.
448
+ snapshot = self.load(snapshot.snapshot_digest)
449
+ name = snapshot.manifest.name
450
+ target = plugins_root / name
451
+ shutil.copytree(self.content_root(snapshot), target, symlinks=True)
452
+ self._retain_selected_components(target, components)
453
+ plugin_names.append(name)
454
+ plugin_entries.append(
455
+ {
456
+ "name": name,
457
+ "source": {"source": "local", "path": f"./plugins/{name}"},
458
+ "policy": {
459
+ "installation": "AVAILABLE",
460
+ "authentication": "ON_INSTALL",
461
+ },
462
+ "category": (
463
+ snapshot.manifest.interface.category
464
+ if snapshot.manifest.interface and snapshot.manifest.interface.category
465
+ else "Productivity"
466
+ ),
467
+ }
468
+ )
469
+ marketplace_name = f"ksadk-{suffix[:20]}"
470
+ marketplace = {
471
+ "name": marketplace_name,
472
+ "interface": {"displayName": "KsADK pinned plugins"},
473
+ "plugins": plugin_entries,
474
+ }
475
+ marketplace_path = root / ".agents" / "plugins" / "marketplace.json"
476
+ marketplace_path.parent.mkdir(parents=True)
477
+ marketplace_path.write_bytes(
478
+ json.dumps(marketplace, ensure_ascii=False, indent=2, sort_keys=True).encode(
479
+ "utf-8"
480
+ )
481
+ + b"\n"
482
+ )
483
+ digest = _tree_digest(root)
484
+ final_root = directory / "marketplace"
485
+ receipt = CodexPinnedMarketplace(
486
+ marketplace_name=marketplace_name,
487
+ marketplace_path=final_root.relative_to(self.workspace.root).as_posix(),
488
+ marketplace_digest=digest,
489
+ plugin_names=tuple(plugin_names),
490
+ plugin_lock_digest=plugin_lock_digest,
491
+ )
492
+ (staging / "receipt.json").write_bytes(
493
+ json.dumps(
494
+ receipt.model_dump(by_alias=True, mode="json"),
495
+ ensure_ascii=False,
496
+ indent=2,
497
+ sort_keys=True,
498
+ ).encode("utf-8")
499
+ + b"\n"
500
+ )
501
+ try:
502
+ os.replace(staging, directory)
503
+ except FileExistsError:
504
+ pass
505
+ finally:
506
+ if staging.exists():
507
+ shutil.rmtree(staging)
508
+ return self.materialize_marketplace(
509
+ plugin_lock_digest=plugin_lock_digest,
510
+ selections=selected_plugins,
511
+ )
512
+
513
+ @staticmethod
514
+ def _retain_selected_components(
515
+ root: Path,
516
+ selected: tuple[CodexPluginComponentSnapshot, ...],
517
+ ) -> None:
518
+ selected_keys = {(component.kind, component.name) for component in selected}
519
+ (
520
+ _validated_root,
521
+ manifest,
522
+ _raw,
523
+ skills,
524
+ mcp_servers,
525
+ hooks,
526
+ apps,
527
+ ) = _load_installed_plugin(root)
528
+
529
+ # The parser deliberately preserves additive upstream fields so the
530
+ # inventory/read path remains forward compatible. Selective
531
+ # materialization is an execution boundary, however: an unknown
532
+ # top-level field could name a new executable component that this
533
+ # implementation does not know how to remove. Fail closed until the
534
+ # field has explicit selection semantics.
535
+ if manifest.model_extra:
536
+ raise StudioError(
537
+ "CODEX_PLUGIN_MANIFEST_EXTENSION_UNSUPPORTED",
538
+ "Codex 插件包含尚未支持的可执行清单字段,无法安全裁剪组件",
539
+ status_code=422,
540
+ details={"fields": sorted(manifest.model_extra)},
541
+ )
542
+
543
+ # Copy selected skill trees aside, remove every discovered skill tree,
544
+ # then publish only the selected ones under the canonical skills root.
545
+ skill_staging = Path(tempfile.mkdtemp(prefix=".selected-skills-", dir=root))
546
+ try:
547
+ for name, source in skills:
548
+ if ("skill", name) in selected_keys:
549
+ shutil.copytree(source, skill_staging / name)
550
+ for _name, source in sorted(skills, key=lambda item: len(item[1].parts), reverse=True):
551
+ if source.exists():
552
+ shutil.rmtree(source)
553
+ canonical_skills = root / "skills"
554
+ if canonical_skills.exists():
555
+ shutil.rmtree(canonical_skills)
556
+ if any(kind == "skill" for kind, _name in selected_keys):
557
+ canonical_skills.mkdir(parents=True)
558
+ for source in sorted(skill_staging.iterdir(), key=lambda item: item.name):
559
+ shutil.copytree(source, canonical_skills / source.name)
560
+ finally:
561
+ shutil.rmtree(skill_staging, ignore_errors=True)
562
+
563
+ # Remove all source declaration files before writing canonical selected
564
+ # companions. Inline MCP declarations are replaced in plugin.json.
565
+ companion_paths = {
566
+ relative for _name, _config, relative in (*mcp_servers, *hooks, *apps) if relative
567
+ }
568
+ if isinstance(manifest.mcp_servers, str):
569
+ companion_paths.add(manifest.mcp_servers)
570
+ if manifest.apps:
571
+ companion_paths.add(manifest.apps)
572
+ if isinstance(manifest.hooks, str):
573
+ companion_paths.add(manifest.hooks)
574
+ elif isinstance(manifest.hooks, tuple):
575
+ companion_paths.update(item for item in manifest.hooks if isinstance(item, str))
576
+ elif manifest.hooks is None and (root / "hooks" / "hooks.json").is_file():
577
+ companion_paths.add("./hooks/hooks.json")
578
+ for relative in companion_paths:
579
+ candidate = root / PurePosixPath(relative)
580
+ if candidate.is_file():
581
+ candidate.unlink()
582
+ selected_mcp = {
583
+ name: config for name, config, _path in mcp_servers if ("mcp", name) in selected_keys
584
+ }
585
+ selected_hooks = {
586
+ name: config["hooks"]
587
+ for name, config, _path in hooks
588
+ if ("hook", name) in selected_keys
589
+ }
590
+ selected_apps = {
591
+ name: config for name, config, _path in apps if ("app", name) in selected_keys
592
+ }
593
+ if selected_mcp:
594
+ (root / ".mcp.json").write_bytes(_canonical_bytes({"mcpServers": selected_mcp}) + b"\n")
595
+ if selected_hooks:
596
+ (root / "hooks.json").write_bytes(_canonical_bytes({"hooks": selected_hooks}) + b"\n")
597
+ if selected_apps:
598
+ (root / ".app.json").write_bytes(_canonical_bytes({"apps": selected_apps}) + b"\n")
599
+
600
+ payload = manifest.model_dump(by_alias=True, exclude_none=True, mode="json")
601
+ for key in ("skills", "mcpServers", "mcp_servers", "hooks", "apps"):
602
+ payload.pop(key, None)
603
+ if any(kind == "skill" for kind, _name in selected_keys):
604
+ payload["skills"] = "./skills/"
605
+ if selected_mcp:
606
+ payload["mcpServers"] = "./.mcp.json"
607
+ if selected_hooks:
608
+ payload["hooks"] = "./hooks.json"
609
+ if selected_apps:
610
+ payload["apps"] = "./.app.json"
611
+ manifest_path = root / ".codex-plugin" / "plugin.json"
612
+ manifest_path.write_bytes(
613
+ json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True).encode("utf-8")
614
+ + b"\n"
615
+ )
616
+ # The same strict parser used at admission must accept generated bytes.
617
+ _load_installed_plugin(root)
618
+
619
+
620
+ def find_installed_codex_plugin_root(
621
+ codex_home: Path,
622
+ *,
623
+ marketplace_name: str,
624
+ plugin_name: str,
625
+ version: str | None,
626
+ ) -> Path:
627
+ """Locate the App Server-owned cache root without assuming it is writable."""
628
+
629
+ coordinates = {
630
+ "marketplaceName": marketplace_name,
631
+ "pluginName": plugin_name,
632
+ "version": version,
633
+ }
634
+ invalid = [
635
+ field
636
+ for field, value in coordinates.items()
637
+ if value is not None and _CACHE_SEGMENT.fullmatch(value) is None
638
+ ]
639
+ if invalid:
640
+ raise StudioError(
641
+ "CODEX_PLUGIN_CACHE_COORDINATE_INVALID",
642
+ "Codex 宿主返回的插件缓存坐标不是安全的单一路径段",
643
+ status_code=409,
644
+ details={"fields": invalid, **coordinates},
645
+ )
646
+
647
+ home = Path(codex_home).expanduser().resolve()
648
+ cache_path = home / "plugins" / "cache"
649
+ if any(path.is_symlink() for path in (home / "plugins", cache_path)):
650
+ raise StudioError(
651
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
652
+ "Codex 插件缓存路径不能经过符号链接",
653
+ status_code=409,
654
+ details={"cache": str(cache_path)},
655
+ )
656
+ try:
657
+ cache = cache_path.resolve(strict=True) if cache_path.exists() else cache_path.resolve()
658
+ except OSError as exc:
659
+ raise StudioError(
660
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
661
+ "Codex 插件缓存路径无法安全解析",
662
+ status_code=409,
663
+ details={"cache": str(cache_path)},
664
+ ) from exc
665
+ try:
666
+ cache.relative_to(home)
667
+ except ValueError as exc: # defensive if platform resolution semantics change
668
+ raise StudioError(
669
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
670
+ "Codex 插件缓存路径越出 CODEX_HOME",
671
+ status_code=409,
672
+ details={"cache": str(cache)},
673
+ ) from exc
674
+
675
+ def safe_root(candidate: Path) -> Path:
676
+ try:
677
+ relative = candidate.relative_to(cache_path)
678
+ except ValueError as exc:
679
+ raise StudioError(
680
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
681
+ "Codex 插件安装目录不在宿主缓存内",
682
+ status_code=409,
683
+ details={"path": str(candidate)},
684
+ ) from exc
685
+ cursor = cache_path
686
+ for part in relative.parts:
687
+ cursor /= part
688
+ if cursor.is_symlink():
689
+ raise StudioError(
690
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
691
+ "Codex 插件安装目录不能经过符号链接",
692
+ status_code=409,
693
+ details={"path": str(candidate)},
694
+ )
695
+ try:
696
+ resolved = candidate.resolve(strict=True)
697
+ resolved.relative_to(cache)
698
+ except (OSError, ValueError) as exc:
699
+ raise StudioError(
700
+ "CODEX_PLUGIN_INSTALLED_ROOT_UNSAFE",
701
+ "Codex 插件安装目录越出宿主缓存或无法安全解析",
702
+ status_code=409,
703
+ details={"path": str(candidate)},
704
+ ) from exc
705
+ return resolved
706
+
707
+ candidates: list[Path] = []
708
+ if version:
709
+ expected = cache / marketplace_name / plugin_name / version
710
+ if expected.is_dir():
711
+ candidates.append(safe_root(expected))
712
+ if cache.is_dir():
713
+ for manifest_path in cache.glob("*/*/*/.codex-plugin/plugin.json"):
714
+ root = safe_root(manifest_path.parent.parent)
715
+ if root not in candidates:
716
+ try:
717
+ manifest = _load_installed_plugin(root)[1]
718
+ except CodexPluginManifestError:
719
+ continue
720
+ if manifest.name == plugin_name and (
721
+ version is None or manifest.version == version or root.name == version
722
+ ):
723
+ candidates.append(root)
724
+ if len(candidates) != 1:
725
+ raise StudioError(
726
+ "CODEX_PLUGIN_INSTALLED_ROOT_NOT_FOUND",
727
+ "无法唯一定位 Codex App Server 安装的插件目录",
728
+ status_code=409,
729
+ details={
730
+ "marketplaceName": marketplace_name,
731
+ "pluginName": plugin_name,
732
+ "version": version,
733
+ "matches": [str(path) for path in candidates],
734
+ },
735
+ )
736
+ return candidates[0]
737
+
738
+
739
+ __all__ = [
740
+ "CodexPinnedMarketplace",
741
+ "CodexPluginSnapshotStore",
742
+ "CodexWorkspacePluginSnapshot",
743
+ "codex_plugin_ref",
744
+ "component_selector",
745
+ "find_installed_codex_plugin_root",
746
+ ]