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
@@ -1,10 +1,21 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import hashlib
4
+ import json
5
+ import os
4
6
  import shutil
7
+ import stat
8
+ import tempfile
9
+ import threading
5
10
  import zipfile
11
+ from contextlib import contextmanager
6
12
  from dataclasses import dataclass
7
- from pathlib import Path
13
+ from pathlib import Path, PurePosixPath
14
+
15
+ try:
16
+ import fcntl
17
+ except ImportError: # Windows legacy callers retain in-process synchronization.
18
+ fcntl = None
8
19
 
9
20
  from ksadk.skills.models import SkillRef
10
21
 
@@ -23,60 +34,128 @@ class SkillPackage:
23
34
 
24
35
 
25
36
  class PackageStore:
26
- def __init__(self, cache_dir: str | Path):
37
+ def __init__(
38
+ self,
39
+ cache_dir: str | Path,
40
+ *,
41
+ namespace: str = "",
42
+ require_hash: bool = False,
43
+ max_archive_bytes: int = 20 * 1024 * 1024,
44
+ max_extracted_bytes: int = 100 * 1024 * 1024,
45
+ max_files: int = 2000,
46
+ ):
47
+ if any(
48
+ type(value) is not int or value < 1
49
+ for value in (max_archive_bytes, max_extracted_bytes, max_files)
50
+ ):
51
+ raise ValueError("Skill package limits must be positive integers")
52
+ if require_hash and (not namespace or fcntl is None):
53
+ raise ValueError("Verified package stores require a namespace and process locking")
27
54
  self.cache_dir = Path(cache_dir)
28
- self.cache_dir.mkdir(parents=True, exist_ok=True)
55
+ self.cache_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
56
+ self.namespace = namespace
57
+ self.require_hash = require_hash
58
+ self.max_archive_bytes = max_archive_bytes
59
+ self.max_extracted_bytes = max_extracted_bytes
60
+ self.max_files = max_files
61
+ self._thread_lock = threading.RLock()
29
62
 
30
63
  def store_archive(self, ref: SkillRef, content: bytes) -> SkillPackage:
31
64
  self._verify_hash(ref, content)
32
- skill_dir = self._skill_dir(ref)
33
- archive_path = skill_dir / "archive.zip"
34
- extract_dir = skill_dir / "extracted"
35
-
36
- if archive_path.exists() and extract_dir.exists():
37
- cached = self.get_cached(ref)
65
+ with self._locked(ref):
66
+ cached = self._get_cached(ref)
38
67
  if cached is not None:
39
68
  return cached
40
-
41
- if skill_dir.exists():
42
- shutil.rmtree(skill_dir)
43
- skill_dir.mkdir(parents=True, exist_ok=True)
44
- archive_path.write_bytes(content)
45
- extract_dir.mkdir(parents=True, exist_ok=True)
46
- self._safe_extract(archive_path, extract_dir)
47
-
48
- return SkillPackage(
49
- ref=ref,
50
- archive_path=archive_path,
51
- extract_dir=extract_dir,
52
- root_dir=self._find_skill_root(extract_dir),
53
- cache_hit=False,
54
- )
69
+ skill_dir = self._skill_dir(ref)
70
+ stage = Path(tempfile.mkdtemp(prefix=".stage-", dir=self.cache_dir))
71
+ try:
72
+ (stage / "archive.zip").write_bytes(content)
73
+ os.chmod(stage / "archive.zip", 0o600)
74
+ extracted = stage / "extracted"
75
+ extracted.mkdir(mode=0o700)
76
+ self._safe_extract(stage / "archive.zip", extracted)
77
+ self._find_skill_root(extracted)
78
+ # Publish only a complete validated tree, under the per-key lock.
79
+ if skill_dir.is_symlink() or skill_dir.is_file():
80
+ skill_dir.unlink()
81
+ elif skill_dir.exists():
82
+ shutil.rmtree(skill_dir)
83
+ os.replace(stage, skill_dir)
84
+ except (OSError, zipfile.BadZipFile, RuntimeError, ValueError) as error:
85
+ raise SkillPackageError("Skill archive could not be safely materialized") from error
86
+ finally:
87
+ if stage.exists():
88
+ shutil.rmtree(stage)
89
+ return self._package(ref, skill_dir, cache_hit=False)
55
90
 
56
91
  def get_cached(self, ref: SkillRef) -> SkillPackage | None:
92
+ with self._locked(ref):
93
+ return self._get_cached(ref)
94
+
95
+ def _get_cached(self, ref: SkillRef) -> SkillPackage | None:
57
96
  skill_dir = self._skill_dir(ref)
58
97
  archive_path = skill_dir / "archive.zip"
59
98
  extract_dir = skill_dir / "extracted"
60
- if not archive_path.exists() or not extract_dir.exists():
99
+ if (
100
+ skill_dir.is_symlink()
101
+ or archive_path.is_symlink()
102
+ or extract_dir.is_symlink()
103
+ or not archive_path.is_file()
104
+ or not extract_dir.is_dir()
105
+ ):
61
106
  return None
62
- content = archive_path.read_bytes()
63
107
  try:
108
+ if archive_path.stat().st_size > self.max_archive_bytes:
109
+ return None
110
+ content = archive_path.read_bytes()
64
111
  self._verify_hash(ref, content)
65
- except SkillPackageError:
112
+ self._verify_tree(archive_path, extract_dir)
113
+ return self._package(ref, skill_dir, cache_hit=True)
114
+ except (RuntimeError, OSError, zipfile.BadZipFile, ValueError):
66
115
  return None
116
+
117
+ def _package(self, ref: SkillRef, skill_dir: Path, *, cache_hit: bool) -> SkillPackage:
67
118
  return SkillPackage(
68
119
  ref=ref,
69
- archive_path=archive_path,
70
- extract_dir=extract_dir,
71
- root_dir=self._find_skill_root(extract_dir),
72
- cache_hit=True,
120
+ archive_path=skill_dir / "archive.zip",
121
+ extract_dir=skill_dir / "extracted",
122
+ root_dir=self._find_skill_root(skill_dir / "extracted"),
123
+ cache_hit=cache_hit,
73
124
  )
74
125
 
75
126
  def _skill_dir(self, ref: SkillRef) -> Path:
76
- return self.cache_dir / (ref.cache_key or ref.name or "skill")
127
+ identity = [
128
+ self.namespace,
129
+ ref.skill_id,
130
+ ref.version_id,
131
+ ref.version,
132
+ ref.name,
133
+ ref.content_hash.render() if ref.content_hash else "",
134
+ ]
135
+ key = hashlib.sha256(json.dumps(identity, ensure_ascii=False).encode()).hexdigest()
136
+ return self.cache_dir / key
137
+
138
+ @contextmanager
139
+ def _locked(self, ref: SkillRef):
140
+ with self._thread_lock:
141
+ if fcntl is None:
142
+ yield
143
+ return
144
+ path = self._skill_dir(ref).with_suffix(".lock")
145
+ fd = os.open(path, os.O_CREAT | os.O_RDWR | os.O_NOFOLLOW, 0o600)
146
+ with os.fdopen(fd, "rb") as lock:
147
+ fcntl.flock(lock, fcntl.LOCK_EX)
148
+ try:
149
+ yield
150
+ finally:
151
+ fcntl.flock(lock, fcntl.LOCK_UN)
77
152
 
78
153
  def _verify_hash(self, ref: SkillRef, content: bytes) -> None:
154
+ if len(content) > self.max_archive_bytes:
155
+ raise SkillPackageError("Skill archive exceeds size limit")
79
156
  if not ref.content_hash:
157
+ if self.require_hash:
158
+ raise SkillPackageError("Verified Skill packages require ContentHash")
80
159
  return
81
160
  if ref.content_hash.algorithm != "sha256":
82
161
  raise SkillPackageError(
@@ -90,13 +169,82 @@ class PackageStore:
90
169
  )
91
170
 
92
171
  def _safe_extract(self, archive_path: Path, extract_dir: Path) -> None:
93
- base = extract_dir.resolve()
172
+ expanded = 0
173
+ with zipfile.ZipFile(archive_path) as archive:
174
+ for member, relative in self._members(archive):
175
+ target = extract_dir / relative
176
+ target.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
177
+ if member.is_dir():
178
+ target.mkdir(exist_ok=True, mode=0o700)
179
+ continue
180
+ with archive.open(member) as source, target.open("xb") as destination:
181
+ written = 0
182
+ while chunk := source.read(64 * 1024):
183
+ written += len(chunk)
184
+ expanded += len(chunk)
185
+ if written > member.file_size or expanded > self.max_extracted_bytes:
186
+ raise SkillPackageError("Expanded Skill package exceeds limits")
187
+ destination.write(chunk)
188
+ os.chmod(target, 0o700 if (member.external_attr >> 16) & 0o111 else 0o600)
189
+
190
+ def _members(self, archive: zipfile.ZipFile):
191
+ members = archive.infolist()
192
+ if (
193
+ len(members) > self.max_files
194
+ or sum(item.file_size for item in members) > self.max_extracted_bytes
195
+ ):
196
+ raise SkillPackageError("Expanded Skill package exceeds limits")
197
+ seen = set()
198
+ result = []
199
+ for member in members:
200
+ relative = PurePosixPath(member.filename)
201
+ kind = stat.S_IFMT(member.external_attr >> 16)
202
+ if (
203
+ not relative.parts
204
+ or relative.is_absolute()
205
+ or ".." in relative.parts
206
+ or "\\" in member.filename
207
+ or ":" in member.filename
208
+ or "\x00" in member.orig_filename
209
+ or kind not in (0, stat.S_IFREG, stat.S_IFDIR)
210
+ or relative in seen
211
+ or member.flag_bits & 1
212
+ ):
213
+ raise SkillPackageError("Unsafe Skill archive member")
214
+ seen.add(relative)
215
+ result.append((member, relative))
216
+ return result
217
+
218
+ def _verify_tree(self, archive_path: Path, extract_dir: Path) -> None:
219
+ expected = set()
94
220
  with zipfile.ZipFile(archive_path) as archive:
95
- for member in archive.infolist():
96
- target = (extract_dir / member.filename).resolve()
97
- if not str(target).startswith(str(base) + "/") and target != base:
98
- raise SkillPackageError(f"unsafe zip member: {member.filename}")
99
- archive.extractall(extract_dir)
221
+ for member, relative in self._members(archive):
222
+ expected.update(
223
+ parent for parent in relative.parents if parent != PurePosixPath(".")
224
+ )
225
+ expected.add(relative)
226
+ target = extract_dir / relative
227
+ if any((extract_dir / parent).is_symlink() for parent in relative.parents):
228
+ raise SkillPackageError("Skill cache contains a linked parent")
229
+ if target.is_symlink():
230
+ raise SkillPackageError("Skill cache contains a link")
231
+ if member.is_dir():
232
+ if not target.is_dir():
233
+ raise SkillPackageError("Skill cache directory missing")
234
+ continue
235
+ if not target.is_file() or target.stat().st_size != member.file_size:
236
+ raise SkillPackageError("Skill cache file changed")
237
+ with archive.open(member) as source, target.open("rb") as current:
238
+ while chunk := source.read(64 * 1024):
239
+ if chunk != current.read(len(chunk)):
240
+ raise SkillPackageError("Skill cache content changed")
241
+ actual = set()
242
+ for path in extract_dir.rglob("*"):
243
+ if path.is_symlink():
244
+ raise SkillPackageError("Skill cache contains a link")
245
+ actual.add(PurePosixPath(path.relative_to(extract_dir).as_posix()))
246
+ if actual != expected:
247
+ raise SkillPackageError("Skill cache file set changed")
100
248
 
101
249
  def _find_skill_root(self, extract_dir: Path) -> Path:
102
250
  if (extract_dir / "SKILL.md").exists():
@@ -13,6 +13,7 @@ from ksadk.skills.models import SkillRef
13
13
  from ksadk.skills.package_store import PackageStore
14
14
  from ksadk.skills.runtime import loader as runtime_loader
15
15
  from ksadk.skills.runtime import registry as runtime_registry
16
+ from ksadk.skills.runtime.artifact_delivery import export_artifacts
16
17
  from ksadk.skills.runtime.base import normalize_skill_names
17
18
  from ksadk.skills.runtime.executor import (
18
19
  WorkflowExecution,
@@ -36,12 +37,18 @@ from ksadk.skills.runtime.executor import (
36
37
  from ksadk.skills.runtime.executor import (
37
38
  _tail as _executor_tail,
38
39
  )
40
+ from ksadk.skills.runtime.pinned import (
41
+ PINNED_PACKAGE_PROTOCOL_VERSION as PINNED_PACKAGE_PROTOCOL_VERSION,
42
+ )
43
+ from ksadk.skills.runtime.pinned import load_pinned_packages
39
44
  from ksadk.skills.runtime.request import (
40
45
  SkillWorkflowRequest,
41
46
  SkillWorkflowRequestError,
42
47
  parse_workflow_request,
43
48
  )
44
49
 
50
+ ARTIFACT_DELIVERY_PROTOCOL_VERSION = 1
51
+
45
52
 
46
53
  def _skill_space_ids() -> list[str]:
47
54
  return runtime_registry.skill_space_ids()
@@ -126,13 +133,31 @@ def run_agent(
126
133
  return 1
127
134
 
128
135
  prompt = request.workflow_prompt
129
- selected_skill_names = request.skill_names or _selected_skill_names()
130
- loaded_skills = _load_skills(
131
- prompt=prompt,
132
- skill_names=selected_skill_names,
133
- service_transport=service_transport,
134
- )
136
+ selected_skill_names = request.skill_names
137
+ if request.pinned_packages is not None:
138
+ if request.package_directory is None:
139
+ raise SkillWorkflowRequestError("Pinned Skill delivery directory is missing")
140
+ loaded_skills = load_pinned_packages(request.pinned_packages, request.package_directory)
141
+ else:
142
+ selected_skill_names = selected_skill_names or _selected_skill_names()
143
+ loaded_skills = _load_skills(
144
+ prompt=prompt,
145
+ skill_names=selected_skill_names,
146
+ service_transport=service_transport,
147
+ )
135
148
  execution = _execute_workflow(prompt, loaded_skills, selected_skill_names=selected_skill_names)
149
+ if request.collect_artifacts and request.package_directory is not None:
150
+ try:
151
+ root = Path(os.environ.get("KSADK_SKILL_WORKDIR") or "/tmp/ksadk-skill-workflow")
152
+ receipt = export_artifacts(
153
+ execution.output_files, root, request.package_directory / "artifacts.zip"
154
+ )
155
+ execution.artifact_bundle = receipt.model_dump()
156
+ except Exception:
157
+ execution.status = "failed"
158
+ execution.error = "Skill artifact delivery failed"
159
+ execution.output_files = []
160
+ execution.artifacts = []
136
161
  print(f"workflow={prompt}")
137
162
  print(f"skill_spaces={','.join(_skill_space_ids())}")
138
163
  print(f"loaded_skills={','.join(skill.name for skill in loaded_skills)}")
@@ -0,0 +1,139 @@
1
+ """Bounded, verified artifact delivery before a Skill sandbox is destroyed."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import io
7
+ import os
8
+ import shutil
9
+ import stat
10
+ import tempfile
11
+ import zipfile
12
+ from pathlib import Path, PurePosixPath
13
+
14
+ from pydantic import BaseModel, ConfigDict, Field
15
+
16
+ MAX_FILES = 100
17
+ MAX_FILE_BYTES = 20 * 1024 * 1024
18
+ MAX_TOTAL_BYTES = 100 * 1024 * 1024
19
+ MAX_BUNDLE_BYTES = MAX_TOTAL_BYTES + 1024 * 1024
20
+
21
+
22
+ class ArtifactDeliveryError(ValueError):
23
+ pass
24
+
25
+
26
+ class ArtifactBundle(BaseModel):
27
+ model_config = ConfigDict(extra="forbid", frozen=True, hide_input_in_errors=True)
28
+
29
+ sha256: str = Field(pattern=r"^[0-9a-f]{64}$", strict=True)
30
+ size: int = Field(ge=0, le=MAX_BUNDLE_BYTES, strict=True)
31
+ file_count: int = Field(ge=0, le=MAX_FILES, strict=True)
32
+
33
+
34
+ def _name(raw: str) -> str:
35
+ path = PurePosixPath(raw)
36
+ if (
37
+ not raw
38
+ or len(raw) > 512
39
+ or path.is_absolute()
40
+ or ".." in path.parts
41
+ or "\\" in raw
42
+ or ":" in raw
43
+ or "\x00" in raw
44
+ or str(path) != raw
45
+ or raw == "."
46
+ ):
47
+ raise ArtifactDeliveryError("Invalid artifact relative path")
48
+ return raw
49
+
50
+
51
+ def export_artifacts(paths: list[str], root: Path, destination: Path) -> ArtifactBundle:
52
+ """Only export regular files under the execution workspace, never symlinks."""
53
+ if len(paths) > MAX_FILES:
54
+ raise ArtifactDeliveryError("Too many artifacts")
55
+ root = root.resolve()
56
+ total = 0
57
+ names = set()
58
+ opened = zipfile.ZipFile(destination, "x", compression=zipfile.ZIP_STORED)
59
+ try:
60
+ with opened as archive:
61
+ for raw in paths:
62
+ path = Path(raw)
63
+ if not path.is_absolute():
64
+ path = root / path
65
+ try:
66
+ relative = path.relative_to(root)
67
+ name = _name(relative.as_posix())
68
+ except ValueError:
69
+ raise ArtifactDeliveryError(
70
+ "Artifact is outside the execution workspace"
71
+ ) from None
72
+ if name in names:
73
+ raise ArtifactDeliveryError("Duplicate artifact path")
74
+ names.add(name)
75
+ current = root
76
+ for part in relative.parts:
77
+ current = current / part
78
+ if current.is_symlink():
79
+ raise ArtifactDeliveryError("Artifact links are not allowed")
80
+ descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
81
+ with os.fdopen(descriptor, "rb") as source:
82
+ info = os.fstat(source.fileno())
83
+ if not stat.S_ISREG(info.st_mode) or info.st_size > MAX_FILE_BYTES:
84
+ raise ArtifactDeliveryError("Artifact is not a bounded regular file")
85
+ content = source.read(MAX_FILE_BYTES + 1)
86
+ total += len(content)
87
+ if len(content) > MAX_FILE_BYTES or total > MAX_TOTAL_BYTES:
88
+ raise ArtifactDeliveryError("Artifact size limit exceeded")
89
+ archive.writestr(name, content)
90
+ os.chmod(destination, 0o600)
91
+ content = destination.read_bytes()
92
+ return ArtifactBundle(
93
+ sha256=hashlib.sha256(content).hexdigest(), size=len(content), file_count=len(names)
94
+ )
95
+ except Exception:
96
+ destination.unlink(missing_ok=True)
97
+ raise
98
+
99
+
100
+ def import_artifacts(
101
+ content: bytes, receipt: ArtifactBundle, *, parent: Path | None = None
102
+ ) -> list[str]:
103
+ """Verify the full bundle before publishing any consumer-visible paths."""
104
+ if len(content) != receipt.size or hashlib.sha256(content).hexdigest() != receipt.sha256:
105
+ raise ArtifactDeliveryError("Artifact bundle integrity mismatch")
106
+ directory = Path(tempfile.mkdtemp(prefix="ksadk-skill-artifacts-", dir=parent))
107
+ try:
108
+ with zipfile.ZipFile(io.BytesIO(content)) as archive:
109
+ entries = archive.infolist()
110
+ if len(entries) != receipt.file_count:
111
+ raise ArtifactDeliveryError("Artifact file count mismatch")
112
+ total = 0
113
+ names = set()
114
+ outputs = []
115
+ for entry in entries:
116
+ name = _name(entry.filename)
117
+ mode = entry.external_attr >> 16
118
+ if name in names or entry.is_dir() or stat.S_IFMT(mode) not in {0, stat.S_IFREG}:
119
+ raise ArtifactDeliveryError("Artifact bundle contains invalid file entries")
120
+ names.add(name)
121
+ total += entry.file_size
122
+ if entry.file_size > MAX_FILE_BYTES or total > MAX_TOTAL_BYTES:
123
+ raise ArtifactDeliveryError("Artifact size limit exceeded")
124
+ with archive.open(entry) as source:
125
+ data = source.read(MAX_FILE_BYTES + 1)
126
+ if len(data) != entry.file_size or len(data) > MAX_FILE_BYTES:
127
+ raise ArtifactDeliveryError("Artifact size mismatch")
128
+ target = directory / name
129
+ target.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
130
+ with target.open("xb") as output:
131
+ os.chmod(target, 0o600)
132
+ output.write(data)
133
+ outputs.append(str(target))
134
+ if not outputs:
135
+ directory.rmdir()
136
+ return outputs
137
+ except Exception:
138
+ shutil.rmtree(directory)
139
+ raise
@@ -2,7 +2,10 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import os
5
+ import secrets
6
+ import tempfile
5
7
  import time
8
+ from pathlib import Path, PurePosixPath
6
9
  from typing import Any
7
10
 
8
11
  from ksadk.sandbox import (
@@ -12,6 +15,9 @@ from ksadk.sandbox import (
12
15
  from ksadk.sandbox import (
13
16
  SandboxInputFile as RuntimeSandboxInputFile,
14
17
  )
18
+ from ksadk.sandbox.e2b_connection import ExplicitE2BConnection
19
+ from ksadk.skills.package_store import SkillPackage
20
+ from ksadk.skills.runtime.artifact_delivery import ArtifactBundle, import_artifacts
15
21
  from ksadk.skills.runtime.base import (
16
22
  SandboxInputFile,
17
23
  SkillRuntimeError,
@@ -20,6 +26,7 @@ from ksadk.skills.runtime.base import (
20
26
  normalize_skill_names,
21
27
  parse_output_files,
22
28
  )
29
+ from ksadk.skills.runtime.pinned import read_archive, stage_packages
23
30
 
24
31
 
25
32
  def _bool_env(name: str, default: bool = True) -> bool:
@@ -48,6 +55,10 @@ def _redact(value: str) -> str:
48
55
 
49
56
 
50
57
  class E2BSkillRuntimeBackend:
58
+ def preflight(self) -> None:
59
+ """Read-only local dependency check; does not prove upstream authorization."""
60
+ self.sandbox_backend.check_available()
61
+
51
62
  def __init__(
52
63
  self,
53
64
  *,
@@ -55,6 +66,8 @@ class E2BSkillRuntimeBackend:
55
66
  template_id: str,
56
67
  timeout: int = 900,
57
68
  allow_internet_access: bool = True,
69
+ connection: ExplicitE2BConnection | None = None,
70
+ artifact_directory: Path | None = None,
58
71
  ):
59
72
  if not template_id:
60
73
  raise SkillRuntimeError(
@@ -64,6 +77,7 @@ class E2BSkillRuntimeBackend:
64
77
  self.template_id = template_id
65
78
  self.timeout = timeout
66
79
  self.allow_internet_access = allow_internet_access
80
+ self.artifact_directory = artifact_directory
67
81
  self.sandbox_backend = E2BSandboxBackend(
68
82
  spec=SandboxSpec(
69
83
  template_id=template_id,
@@ -72,6 +86,7 @@ class E2BSkillRuntimeBackend:
72
86
  metadata={"component": "skill-runtime"},
73
87
  ),
74
88
  sandbox_cls=sandbox_cls,
89
+ connection=connection,
75
90
  )
76
91
 
77
92
  @classmethod
@@ -109,17 +124,31 @@ class E2BSkillRuntimeBackend:
109
124
  skill_names: list[str] | None = None,
110
125
  env: dict[str, str] | None = None,
111
126
  input_files: list[SandboxInputFile] | None = None,
127
+ pinned_packages: list[SkillPackage] | None = None,
112
128
  timeout: int = 900,
113
129
  ) -> SkillRuntimeResult:
114
130
  session = None
115
131
  started = time.monotonic()
116
132
  effective_timeout = timeout or self.timeout
117
133
  try:
134
+ if pinned_packages is not None:
135
+ for item in input_files or []:
136
+ target = PurePosixPath(item.target_path)
137
+ if (
138
+ not target.is_relative_to("/workspace/inputs")
139
+ or ".." in target.parts
140
+ or "\\" in item.target_path
141
+ ):
142
+ raise SkillRuntimeError(
143
+ "Pinned Skill inputs must be under /workspace/inputs"
144
+ )
118
145
  sandbox_env = {
119
146
  "KSADK_SKILL_SPACE_IDS": ",".join(skill_space_ids),
120
147
  "SKILL_SPACE_ID": skill_space_ids[0] if skill_space_ids else "",
121
148
  }
122
- if public_spaces := os.environ.get("KSADK_PUBLIC_SKILL_SPACE_IDS"):
149
+ if pinned_packages is None and (
150
+ public_spaces := os.environ.get("KSADK_PUBLIC_SKILL_SPACE_IDS")
151
+ ):
123
152
  sandbox_env["KSADK_PUBLIC_SKILL_SPACE_IDS"] = public_spaces
124
153
  selected_skill_names = format_skill_names_env(skill_names)
125
154
  if selected_skill_names:
@@ -135,26 +164,89 @@ class E2BSkillRuntimeBackend:
135
164
  )
136
165
 
137
166
  request_path = "/tmp/ksadk-workflow-request.json"
167
+ request = {
168
+ "workflow_prompt": workflow_prompt,
169
+ "skill_names": normalize_skill_names(skill_names),
170
+ }
171
+ if pinned_packages is not None:
172
+ probe = session.run_command(
173
+ "python -I -c 'from ksadk.skills.runtime.agent import "
174
+ "PINNED_PACKAGE_PROTOCOL_VERSION, ARTIFACT_DELIVERY_PROTOCOL_VERSION; "
175
+ 'print(f"{PINNED_PACKAGE_PROTOCOL_VERSION}:{ARTIFACT_DELIVERY_PROTOCOL_VERSION}")\'',
176
+ timeout=min(effective_timeout, 10),
177
+ env=sandbox_env,
178
+ )
179
+ if probe.exit_code != 0 or probe.stdout.strip() != "1:1":
180
+ raise SkillRuntimeError(
181
+ "Sandbox runtime does not support pinned Skill protocol v1"
182
+ )
183
+ delivery = "/tmp/ksadk-pinned-" + secrets.token_hex(16)
184
+ prepared = session.run_command(
185
+ f"mkdir -m 700 {delivery}", timeout=min(effective_timeout, 10), env=sandbox_env
186
+ )
187
+ if prepared.exit_code != 0:
188
+ raise SkillRuntimeError("Could not prepare pinned Skill delivery directory")
189
+ with tempfile.TemporaryDirectory(prefix="ksadk-skill-transfer-") as directory:
190
+ entries = stage_packages(pinned_packages, Path(directory))
191
+ for entry in entries:
192
+ session.write_file(
193
+ f"{delivery}/{entry.archive_name}",
194
+ read_archive(Path(directory) / entry.archive_name),
195
+ )
196
+ request["pinned_packages"] = [entry.model_dump() for entry in entries]
197
+ request["pinned_protocol_version"] = 1
198
+ request["collect_artifacts"] = True
199
+ sandbox_env["KSADK_SKILL_WORKDIR"] = f"{delivery}/work"
200
+ request_path = f"{delivery}/workflow-request.json"
138
201
  session.write_file(
139
202
  request_path,
140
203
  json.dumps(
141
- {
142
- "workflow_prompt": workflow_prompt,
143
- "skill_names": normalize_skill_names(skill_names),
144
- },
204
+ request,
145
205
  ensure_ascii=False,
146
206
  ).encode("utf-8"),
147
207
  )
148
208
  command = f"python -u /home/ksadk/agent.py --request-file {request_path}"
209
+ if pinned_packages is not None:
210
+ command = (
211
+ f"python -I -u -m ksadk.skills.runtime.agent --request-file {request_path}"
212
+ )
149
213
  result = session.run_command(command, timeout=effective_timeout, env=sandbox_env)
150
214
  stdout = result.stdout
215
+ output_files = parse_output_files(stdout)
216
+ if pinned_packages is not None:
217
+ payloads = [
218
+ json.loads(line.split("=", 1)[1])
219
+ for line in stdout.splitlines()
220
+ if line.startswith("workflow_result=")
221
+ ]
222
+ if len(payloads) != 1 or not isinstance(payloads[0], dict):
223
+ raise SkillRuntimeError("Sandbox did not return a unique workflow result")
224
+ payload = payloads[0]
225
+ if payload.get("artifact_bundle") is None:
226
+ raise SkillRuntimeError("Sandbox did not return an artifact delivery receipt")
227
+ receipt = ArtifactBundle.model_validate(payload["artifact_bundle"])
228
+ content = session.read_file_bytes(
229
+ f"{delivery}/artifacts.zip", max_bytes=receipt.size
230
+ )
231
+ output_files = import_artifacts(content, receipt, parent=self.artifact_directory)
232
+ payload["output_files"] = output_files
233
+ payload["artifacts"] = output_files
234
+ stdout = (
235
+ "\n".join(
236
+ "workflow_result=" + json.dumps(payload, ensure_ascii=False, sort_keys=True)
237
+ if line.startswith("workflow_result=")
238
+ else line
239
+ for line in stdout.splitlines()
240
+ )
241
+ + "\n"
242
+ )
151
243
  return SkillRuntimeResult(
152
244
  runtime_id=session.sandbox_id,
153
245
  exit_code=result.exit_code,
154
246
  stdout=stdout,
155
247
  stderr=result.stderr,
156
248
  duration_ms=int((time.monotonic() - started) * 1000),
157
- output_files=parse_output_files(stdout),
249
+ output_files=output_files,
158
250
  )
159
251
  except Exception as exc:
160
252
  error_type = type(exc).__name__