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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
  2. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
  3. ksadk/_build_provenance.json +1 -1
  4. ksadk/api/client.py +105 -91
  5. ksadk/builders/code_builder.py +36 -9
  6. ksadk/builders/framework_requirements.py +2 -1
  7. ksadk/builders/ks3_uploader.py +36 -7
  8. ksadk/builders/managed_runtime_builder.py +1 -0
  9. ksadk/cli/__init__.py +32 -3
  10. ksadk/cli/cmd_managed_runtime.py +13 -1
  11. ksadk/cli/cmd_plugin.py +6 -1
  12. ksadk/cli/cmd_web.py +2 -5
  13. ksadk/cli/runtime_bootstrap.py +23 -1
  14. ksadk/codex/client.py +424 -96
  15. ksadk/codex/projection.py +24 -0
  16. ksadk/codex/runtime.py +56 -298
  17. ksadk/common/auth.py +16 -10
  18. ksadk/configs/env_registry.py +29 -1
  19. ksadk/conversations/message_projection.py +135 -14
  20. ksadk/conversations/projector.py +4 -6
  21. ksadk/conversations/runtime_invocation.py +5 -0
  22. ksadk/conversations/runtime_payloads.py +1 -0
  23. ksadk/conversations/runtime_preparation.py +30 -27
  24. ksadk/conversations/runtime_resume.py +50 -2
  25. ksadk/conversations/runtime_stream_events.py +5 -0
  26. ksadk/conversations/runtime_streaming.py +25 -7
  27. ksadk/deployment/env_forward.py +2 -2
  28. ksadk/deployment/providers/serverless.py +1 -1
  29. ksadk/events/adapters/_codex_validators.py +18 -7
  30. ksadk/events/adapters/langgraph.py +15 -1
  31. ksadk/events/canonical_store.py +3 -1
  32. ksadk/events/projections.py +1 -1
  33. ksadk/harness/config.py +2 -2
  34. ksadk/harness/runtime.py +27 -27
  35. ksadk/harness/tools.py +38 -13
  36. ksadk/interaction/provider.py +1 -0
  37. ksadk/interaction/providers/langgraph.py +1 -0
  38. ksadk/kernel/bootstrap.py +28 -4
  39. ksadk/kernel/ingress.py +15 -2
  40. ksadk/kernel/sqlite_store.py +27 -0
  41. ksadk/kernel/store.py +3 -0
  42. ksadk/kernel/worker.py +65 -10
  43. ksadk/knowledge_base/client.py +57 -27
  44. ksadk/mcp_runtime/__init__.py +12 -4
  45. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  46. ksadk/memory/adk/resilient_session_service.py +25 -17
  47. ksadk/memory/adk/short_term_memory.py +26 -9
  48. ksadk/memory/models.py +7 -4
  49. ksadk/memory/provider_resolver.py +3 -0
  50. ksadk/model_proxy/server.py +10 -5
  51. ksadk/plugins/__init__.py +4 -0
  52. ksadk/plugins/artifacts.py +275 -0
  53. ksadk/plugins/bridges/__init__.py +4 -2
  54. ksadk/plugins/bridges/codex.py +120 -13
  55. ksadk/plugins/bridges/dsh.py +340 -156
  56. ksadk/plugins/builtins.py +35 -36
  57. ksadk/plugins/bundle_security.py +28 -4
  58. ksadk/plugins/codex_manifest.py +983 -0
  59. ksadk/plugins/composition.py +8 -0
  60. ksadk/plugins/contracts.py +118 -0
  61. ksadk/plugins/delivery.py +153 -0
  62. ksadk/plugins/dsh_installation_digest.py +71 -0
  63. ksadk/plugins/dsh_toolchain.py +110 -21
  64. ksadk/plugins/ecosystem_probe.py +6 -6
  65. ksadk/plugins/host.py +102 -39
  66. ksadk/plugins/kernel_adapter.py +205 -0
  67. ksadk/plugins/providers/__init__.py +23 -0
  68. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  69. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  70. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  71. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  72. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  73. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  74. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  75. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  76. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  77. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  78. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  79. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  80. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  81. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  82. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  83. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  84. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  85. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  86. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  87. ksadk/plugins/providers/codex.py +335 -69
  88. ksadk/plugins/providers/codex_native.py +368 -0
  89. ksadk/plugins/providers/codex_turn.py +301 -0
  90. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  91. ksadk/plugins/providers/dsh_mcp.py +467 -0
  92. ksadk/plugins/providers/harness.py +118 -113
  93. ksadk/plugins/providers/mcp_projection.py +150 -0
  94. ksadk/plugins/providers/platform_resources.py +657 -0
  95. ksadk/plugins/resolver.py +8 -1
  96. ksadk/resource_runtime/__init__.py +4 -0
  97. ksadk/resource_runtime/broker.py +616 -0
  98. ksadk/resource_runtime/build_artifacts.py +165 -0
  99. ksadk/resource_runtime/contracts.py +138 -0
  100. ksadk/resource_runtime/discovery_receipts.py +100 -0
  101. ksadk/resource_runtime/discovery_skills.py +172 -0
  102. ksadk/resource_runtime/errors.py +6 -0
  103. ksadk/resource_runtime/ipc.py +142 -0
  104. ksadk/resource_runtime/kernel_approval.py +165 -0
  105. ksadk/resource_runtime/knowledge.py +114 -0
  106. ksadk/resource_runtime/langgraph.py +94 -0
  107. ksadk/resource_runtime/leases.py +191 -0
  108. ksadk/resource_runtime/managed_projection.py +186 -0
  109. ksadk/resource_runtime/mcp_server.py +138 -0
  110. ksadk/resource_runtime/memory_provider.py +318 -0
  111. ksadk/resource_runtime/memory_receipts.py +34 -0
  112. ksadk/resource_runtime/operation_ledger.py +211 -0
  113. ksadk/resource_runtime/plugin_config.py +48 -0
  114. ksadk/resource_runtime/policy_authorization.py +54 -0
  115. ksadk/resource_runtime/process.py +110 -0
  116. ksadk/resource_runtime/skill_artifacts.py +153 -0
  117. ksadk/resource_runtime/skill_runtime.py +42 -0
  118. ksadk/resource_runtime/skill_workspace.py +118 -0
  119. ksadk/resource_runtime/skills.py +215 -0
  120. ksadk/resource_runtime/snapshots.py +180 -0
  121. ksadk/resource_runtime/socket_server.py +103 -0
  122. ksadk/resource_runtime/supervisor.py +380 -0
  123. ksadk/resource_runtime/worker.py +504 -0
  124. ksadk/runners/_langgraph_runner_streams.py +74 -6
  125. ksadk/runners/adk_runner.py +149 -11
  126. ksadk/runners/base_runner.py +29 -1
  127. ksadk/runners/langgraph_runner.py +475 -145
  128. ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
  129. ksadk/runtime/adapter.py +2 -0
  130. ksadk/runtime/conversation_execution.py +92 -16
  131. ksadk/runtime/executor.py +78 -2
  132. ksadk/runtime/factory.py +29 -273
  133. ksadk/runtime/framework_adapters.py +23 -0
  134. ksadk/runtime/preprocessing.py +10 -2
  135. ksadk/runtime/runner_adapter.py +73 -14
  136. ksadk/runtime_context.py +40 -2
  137. ksadk/sandbox/backends/e2b.py +52 -11
  138. ksadk/sandbox/backends/local_process.py +9 -0
  139. ksadk/sandbox/base.py +2 -0
  140. ksadk/sandbox/e2b_connection.py +66 -0
  141. ksadk/scheduler/sqlite_store.py +18 -0
  142. ksadk/server/composition.py +2 -0
  143. ksadk/server/factory.py +5 -0
  144. ksadk/server/persistence_capability.py +516 -0
  145. ksadk/server/routes/control.py +210 -46
  146. ksadk/server/routes/dependencies.py +15 -0
  147. ksadk/server/routes/models.py +47 -4
  148. ksadk/server/routes/projection.py +252 -12
  149. ksadk/server/routes/sessions.py +284 -107
  150. ksadk/server/routes/streaming.py +43 -9
  151. ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  152. ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
  153. ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  154. ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  155. ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  156. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  157. ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
  158. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  159. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  160. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  161. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  162. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  163. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  164. ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  165. ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  166. ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  167. ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  168. ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  169. ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  170. ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  171. ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  172. ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  173. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  174. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  175. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  176. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  177. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  178. ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  179. ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
  180. ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  181. ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  182. ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  183. ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  184. ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  185. ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
  186. ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
  187. ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
  188. ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
  189. ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
  190. ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
  191. ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
  192. ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
  193. ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
  194. ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
  195. ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
  196. ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
  197. ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
  198. ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
  199. ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
  200. ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
  201. ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
  202. ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
  203. ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
  204. ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
  205. ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
  206. ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
  207. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  208. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  209. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  210. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  211. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  212. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  213. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  214. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  215. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  216. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  217. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  218. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  219. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  220. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  221. ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
  222. ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
  223. ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  224. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  225. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  226. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  227. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  228. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  229. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  230. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  231. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  232. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  233. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  234. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  235. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  236. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  237. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  238. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  239. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  240. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  241. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  242. ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  243. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  244. ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  245. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  246. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  247. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  248. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  249. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  250. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  251. ksadk/server/static/index.html +2 -2
  252. ksadk/session_context.py +66 -0
  253. ksadk/sessions/__init__.py +11 -21
  254. ksadk/sessions/_local_service_sync.py +263 -1
  255. ksadk/sessions/base.py +176 -0
  256. ksadk/sessions/errors.py +4 -0
  257. ksadk/sessions/in_memory.py +309 -19
  258. ksadk/sessions/local_service.py +83 -1
  259. ksadk/sessions/persistence.py +275 -0
  260. ksadk/sessions/postgres_service.py +358 -0
  261. ksadk/sessions/resilience.py +8 -0
  262. ksadk/sessions/resilient.py +362 -4
  263. ksadk/sessions/topology.py +135 -0
  264. ksadk/skills/models.py +26 -4
  265. ksadk/skills/package_store.py +186 -38
  266. ksadk/skills/runtime/agent.py +31 -6
  267. ksadk/skills/runtime/artifact_delivery.py +139 -0
  268. ksadk/skills/runtime/backends/e2b.py +98 -6
  269. ksadk/skills/runtime/backends/local.py +73 -8
  270. ksadk/skills/runtime/base.py +3 -0
  271. ksadk/skills/runtime/executor.py +2 -0
  272. ksadk/skills/runtime/loader.py +10 -2
  273. ksadk/skills/runtime/pinned.py +114 -0
  274. ksadk/skills/runtime/request.py +31 -0
  275. ksadk/skills/service_client.py +167 -28
  276. ksadk/studio/api.py +224 -42
  277. ksadk/studio/api_catalog_routes.py +18 -0
  278. ksadk/studio/api_plugin_routes.py +526 -95
  279. ksadk/studio/api_resource_connections.py +183 -0
  280. ksadk/studio/authoring_coordinator.py +19 -14
  281. ksadk/studio/builder.py +76 -0
  282. ksadk/studio/cloud.py +342 -104
  283. ksadk/studio/cloud_shared_web.py +565 -0
  284. ksadk/studio/codex_agent_service.py +128 -26
  285. ksadk/studio/codex_builder.py +241 -2
  286. ksadk/studio/codex_credentials.py +90 -0
  287. ksadk/studio/codex_manifest.py +31 -4
  288. ksadk/studio/codex_plugin_store.py +746 -0
  289. ksadk/studio/codex_provider_build.py +231 -0
  290. ksadk/studio/codex_run.py +184 -25
  291. ksadk/studio/compatibility_report.py +12 -1
  292. ksadk/studio/compiler.py +78 -14
  293. ksadk/studio/contracts.py +132 -6
  294. ksadk/studio/dsh_application.py +137 -0
  295. ksadk/studio/dsh_capability_service.py +1107 -0
  296. ksadk/studio/dsh_models.py +59 -0
  297. ksadk/studio/dsh_provider_registration.py +320 -13
  298. ksadk/studio/hosted_kernel.py +88 -13
  299. ksadk/studio/mcp_runtime.py +11 -3
  300. ksadk/studio/model_client.py +2 -2
  301. ksadk/studio/plugin_composition.py +190 -23
  302. ksadk/studio/plugin_kernel_adapter.py +12 -112
  303. ksadk/studio/plugin_runtime.py +224 -45
  304. ksadk/studio/resource_authority.py +637 -0
  305. ksadk/studio/resource_binding_validation.py +77 -0
  306. ksadk/studio/resource_build_admission.py +196 -0
  307. ksadk/studio/resource_build_materializer.py +149 -0
  308. ksadk/studio/resource_catalog.py +143 -2
  309. ksadk/studio/resource_connections.py +220 -0
  310. ksadk/studio/run_service.py +462 -52
  311. ksadk/studio/runtime_source.py +15 -7
  312. ksadk/studio/scheduler_assistant.py +317 -0
  313. ksadk/studio/scheduler_runtime.py +9 -0
  314. ksadk/studio/scheduler_service.py +3 -0
  315. ksadk/studio/service.py +490 -44
  316. ksadk/studio/shared_web.py +446 -62
  317. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  318. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  319. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  320. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  321. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  322. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  323. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  324. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  325. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  326. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  327. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  328. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  329. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  330. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  331. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  332. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  333. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  334. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  335. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  336. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  337. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  338. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  339. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  340. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  341. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  342. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  343. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  344. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  345. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  346. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  347. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  348. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  349. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  350. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  351. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  352. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  353. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  354. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  355. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  356. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  357. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  358. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  359. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  360. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  361. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  362. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  363. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  364. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  365. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  366. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  367. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  368. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  369. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  372. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  373. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  377. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  378. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  379. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  380. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  381. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  382. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  383. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  384. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  385. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  386. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  387. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  388. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  389. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  390. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  391. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  392. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  393. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  394. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  395. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  396. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  397. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  398. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  399. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  400. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  401. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  402. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  403. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  404. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  405. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  406. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  407. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  408. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  409. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  410. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  411. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  412. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  413. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  414. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  415. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  416. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  417. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  418. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  419. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  420. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  421. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  422. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  423. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  424. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  425. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  426. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  427. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  428. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  429. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  430. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  431. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  432. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  433. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  434. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  435. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  436. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  437. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  438. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  439. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  440. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  441. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  442. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  443. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  444. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  445. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  446. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  447. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  448. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  449. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  450. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  451. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  452. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  453. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  454. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  455. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  456. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  457. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  458. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  459. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  460. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  461. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  462. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  463. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  464. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  465. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  466. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  467. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  468. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  469. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  470. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  471. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  472. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  473. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  474. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  475. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  476. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  477. ksadk/studio/static/index.html +2 -2
  478. ksadk/version.py +1 -1
  479. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
  480. ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
  481. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
  482. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
  483. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
  484. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
  485. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
  486. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
  487. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
  488. ksadk/server/static/assets/index-B2k_urY8.js +0 -241
  489. ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
  490. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
  491. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
  492. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
  493. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
  494. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
  495. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
  496. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
  497. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
  498. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
  499. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
  500. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
  501. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
  502. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
  503. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  504. ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
  505. ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
  506. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  507. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  508. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  509. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
@@ -8,13 +8,17 @@ import tempfile
8
8
  import time
9
9
  from pathlib import Path
10
10
 
11
+ from ksadk.skills.package_store import SkillPackage
12
+ from ksadk.skills.runtime.artifact_delivery import export_artifacts, import_artifacts
11
13
  from ksadk.skills.runtime.base import (
12
14
  SandboxInputFile,
15
+ SkillRuntimeError,
13
16
  SkillRuntimeResult,
14
17
  format_skill_names_env,
15
18
  normalize_skill_names,
16
19
  parse_output_files,
17
20
  )
21
+ from ksadk.skills.runtime.pinned import stage_packages
18
22
 
19
23
 
20
24
  def _coerce_output(value: str | bytes | None) -> str:
@@ -45,14 +49,29 @@ class LocalProcessSkillRuntimeBackend:
45
49
  skill_names: list[str] | None = None,
46
50
  env: dict[str, str] | None = None,
47
51
  input_files: list[SandboxInputFile] | None = None,
52
+ pinned_packages: list[SkillPackage] | None = None,
48
53
  timeout: int = 900,
49
54
  ) -> SkillRuntimeResult:
50
55
  started = time.monotonic()
51
- runtime_env = os.environ.copy()
56
+ if pinned_packages is not None and self.agent_path.resolve() != (
57
+ Path(__file__).resolve().parents[1] / "agent.py"
58
+ ):
59
+ raise ValueError("Pinned Skill execution requires the bundled runtime agent")
60
+ runtime_env = (
61
+ {
62
+ key: value
63
+ for key, value in os.environ.items()
64
+ if key in {"PATH", "LANG", "LC_ALL", "TMPDIR", "SYSTEMROOT"}
65
+ }
66
+ if pinned_packages is not None
67
+ else os.environ.copy()
68
+ )
52
69
  runtime_env.update(env or {})
53
70
  runtime_env["KSADK_SKILL_SPACE_IDS"] = ",".join(skill_space_ids)
54
71
  runtime_env["SKILL_SPACE_ID"] = skill_space_ids[0] if skill_space_ids else ""
55
- if public_spaces := os.environ.get("KSADK_PUBLIC_SKILL_SPACE_IDS"):
72
+ if pinned_packages is None and (
73
+ public_spaces := os.environ.get("KSADK_PUBLIC_SKILL_SPACE_IDS")
74
+ ):
56
75
  runtime_env["KSADK_PUBLIC_SKILL_SPACE_IDS"] = public_spaces
57
76
  selected_skill_names = format_skill_names_env(skill_names)
58
77
  if selected_skill_names:
@@ -62,12 +81,27 @@ class LocalProcessSkillRuntimeBackend:
62
81
  try:
63
82
  with tempfile.TemporaryDirectory(prefix="ksadk-skill-runtime-") as tmp_dir:
64
83
  request_path = Path(tmp_dir) / "workflow-request.json"
84
+ request = {
85
+ "workflow_prompt": workflow_prompt,
86
+ "skill_names": normalize_skill_names(skill_names),
87
+ }
88
+ if pinned_packages is not None:
89
+ entries = stage_packages(pinned_packages, Path(tmp_dir))
90
+ request["pinned_packages"] = [entry.model_dump() for entry in entries]
91
+ request["pinned_protocol_version"] = 1
92
+ if not runtime_env.get("KSADK_SKILL_WORKDIR"):
93
+ # Artifacts outlive the temporary archive delivery directory.
94
+ runtime_env["KSADK_SKILL_WORKDIR"] = tempfile.mkdtemp(
95
+ prefix="ksadk-pinned-artifacts-"
96
+ )
97
+ # Use the same canonical root in the child and host validator
98
+ # (macOS temporary directories may be reached through /var).
99
+ runtime_env["KSADK_SKILL_WORKDIR"] = str(
100
+ Path(runtime_env["KSADK_SKILL_WORKDIR"]).resolve()
101
+ )
65
102
  request_path.write_text(
66
103
  json.dumps(
67
- {
68
- "workflow_prompt": workflow_prompt,
69
- "skill_names": normalize_skill_names(skill_names),
70
- },
104
+ request,
71
105
  ensure_ascii=False,
72
106
  ),
73
107
  encoding="utf-8",
@@ -75,6 +109,7 @@ class LocalProcessSkillRuntimeBackend:
75
109
  completed = subprocess.run(
76
110
  [
77
111
  sys.executable,
112
+ *(["-I"] if pinned_packages is not None else []),
78
113
  "-u",
79
114
  str(self.agent_path),
80
115
  "--request-file",
@@ -86,13 +121,43 @@ class LocalProcessSkillRuntimeBackend:
86
121
  env=runtime_env,
87
122
  check=False,
88
123
  )
124
+ stdout = completed.stdout
125
+ output_files = parse_output_files(stdout)
126
+ if pinned_packages is not None:
127
+ payloads = [
128
+ json.loads(line.split("=", 1)[1])
129
+ for line in stdout.splitlines()
130
+ if line.startswith("workflow_result=")
131
+ ]
132
+ if len(payloads) != 1 or not isinstance(payloads[0], dict):
133
+ raise SkillRuntimeError("Runtime did not return a unique workflow result")
134
+ payload = payloads[0]
135
+ paths = payload.get("output_files")
136
+ if not isinstance(paths, list) or any(not isinstance(p, str) for p in paths):
137
+ raise SkillRuntimeError("Runtime returned invalid artifact paths")
138
+ # Snapshot only bounded regular files from the admitted workspace.
139
+ # A workflow's stdout is not authority to read arbitrary host files.
140
+ bundle_path = Path(tmp_dir) / "artifacts.zip"
141
+ receipt = export_artifacts(
142
+ paths, Path(runtime_env["KSADK_SKILL_WORKDIR"]), bundle_path
143
+ )
144
+ output_files = import_artifacts(bundle_path.read_bytes(), receipt)
145
+ payload["output_files"] = output_files
146
+ payload["artifacts"] = output_files
147
+ payload["artifact_bundle"] = receipt.model_dump()
148
+ stdout = "\n".join(
149
+ "workflow_result=" + json.dumps(payload, ensure_ascii=False, sort_keys=True)
150
+ if line.startswith("workflow_result=")
151
+ else line
152
+ for line in stdout.splitlines()
153
+ ) + "\n"
89
154
  return SkillRuntimeResult(
90
155
  runtime_id=f"local:{session_id}",
91
156
  exit_code=completed.returncode,
92
- stdout=completed.stdout,
157
+ stdout=stdout,
93
158
  stderr=completed.stderr,
94
159
  duration_ms=int((time.monotonic() - started) * 1000),
95
- output_files=parse_output_files(completed.stdout),
160
+ output_files=output_files,
96
161
  )
97
162
  except subprocess.TimeoutExpired as exc:
98
163
  return SkillRuntimeResult(
@@ -5,6 +5,8 @@ from dataclasses import dataclass, field
5
5
  from pathlib import Path
6
6
  from typing import Protocol, Sequence
7
7
 
8
+ from ksadk.skills.package_store import SkillPackage
9
+
8
10
 
9
11
  class SkillRuntimeError(RuntimeError):
10
12
  pass
@@ -56,6 +58,7 @@ class SkillRuntimeBackend(Protocol):
56
58
  skill_names: list[str] | None = None,
57
59
  env: dict[str, str] | None = None,
58
60
  input_files: list[SandboxInputFile] | None = None,
61
+ pinned_packages: list[SkillPackage] | None = None,
59
62
  timeout: int = 900,
60
63
  ) -> SkillRuntimeResult: ...
61
64
 
@@ -27,6 +27,7 @@ class WorkflowExecution:
27
27
  artifacts: list[str] = field(default_factory=list)
28
28
  warnings: list[str] = field(default_factory=list)
29
29
  error: str = ""
30
+ artifact_bundle: dict[str, object] | None = None
30
31
 
31
32
 
32
33
  def execute_workflow(
@@ -136,6 +137,7 @@ def _run_generic_workflow(skill: LocalSkill, prompt: str) -> WorkflowExecution:
136
137
  workdir = _skill_workdir()
137
138
  workdir.mkdir(parents=True, exist_ok=True)
138
139
  output_dir = workdir / "artifacts"
140
+ output_dir.mkdir(parents=True, exist_ok=True)
139
141
  timeout = _runtime_timeout()
140
142
  command = _run_command(
141
143
  ["bash", str(skill.root_dir / "scripts" / "run-workflow.sh")],
@@ -49,10 +49,14 @@ def load_skills(
49
49
  seen_names: set[str] = {skill.name.lower() for skill in skills if skill.name}
50
50
  for space_id in registry.user_skill_space_ids():
51
51
  listing = client.list_skills_by_space_id(space_id)
52
+ if listing.truncated:
53
+ warnings.append(
54
+ "Skill directory is incomplete; selection covers only retrieved entries"
55
+ )
52
56
  selected_refs.extend(
53
57
  registry.dedupe_skill_refs(
54
58
  registry.select_remote_skill_refs(
55
- listing.active_skills(),
59
+ listing.active_skills(allow_partial=True),
56
60
  prompt,
57
61
  skill_names=skill_names,
58
62
  ),
@@ -62,9 +66,13 @@ def load_skills(
62
66
 
63
67
  if registry.public_skill_space_ids():
64
68
  listing = client.list_available_premade_skills()
69
+ if listing.truncated:
70
+ warnings.append(
71
+ "Public Skill directory is incomplete; selection covers only retrieved entries"
72
+ )
65
73
  selected_refs.extend(
66
74
  registry.dedupe_skill_refs(
67
- registry.select_public_skill_refs(listing.active_skills()),
75
+ registry.select_public_skill_refs(listing.active_skills(allow_partial=True)),
68
76
  seen_names=seen_names,
69
77
  )
70
78
  )
@@ -0,0 +1,114 @@
1
+ """Transport and consume exact Skill archives without directory discovery.
2
+
3
+ The trusted caller authorizes the package set before staging. This contract
4
+ verifies bytes at the consumer; it is not an authorization or sandbox boundary.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import hashlib
10
+ import os
11
+ import stat
12
+ from pathlib import Path
13
+
14
+ from pydantic import BaseModel, ConfigDict, Field
15
+
16
+ from ksadk.skills.loader import LocalSkill, load_local_skill
17
+ from ksadk.skills.models import ContentHash, SkillRef
18
+ from ksadk.skills.package_store import PackageStore, SkillPackage, SkillPackageError
19
+
20
+ MAX_ARCHIVE_BYTES = 20 * 1024 * 1024
21
+ MAX_PACKAGES = 32
22
+ PINNED_PACKAGE_PROTOCOL_VERSION = 1
23
+
24
+
25
+ class PinnedSkillArchive(BaseModel):
26
+ model_config = ConfigDict(extra="forbid", frozen=True, hide_input_in_errors=True)
27
+
28
+ skill_id: str = Field(min_length=1, max_length=256, strict=True)
29
+ version_id: str = Field(min_length=1, max_length=256, strict=True)
30
+ name: str = Field(min_length=1, max_length=256, strict=True)
31
+ content_hash: str = Field(pattern=r"^sha256:[0-9a-f]{64}$", strict=True)
32
+ archive_name: str = Field(pattern=r"^[0-9a-f]{64}\.zip$", strict=True)
33
+
34
+ def skill_ref(self) -> SkillRef:
35
+ return SkillRef(
36
+ skill_id=self.skill_id,
37
+ version_id=self.version_id,
38
+ version="",
39
+ name=self.name,
40
+ content_hash=ContentHash.parse(self.content_hash),
41
+ )
42
+
43
+
44
+ def read_archive(path: Path) -> bytes:
45
+ """Read a bounded regular archive, rejecting a symlink at the final component."""
46
+ descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
47
+ with os.fdopen(descriptor, "rb") as stream:
48
+ info = os.fstat(stream.fileno())
49
+ if not stat.S_ISREG(info.st_mode) or info.st_size > MAX_ARCHIVE_BYTES:
50
+ raise SkillPackageError("Pinned Skill archive is not a bounded regular file")
51
+ content = stream.read(MAX_ARCHIVE_BYTES + 1)
52
+ if len(content) > MAX_ARCHIVE_BYTES:
53
+ raise SkillPackageError("Pinned Skill archive exceeds size limit")
54
+ return content
55
+
56
+
57
+ def validate_package_set(entries: tuple[PinnedSkillArchive, ...]) -> None:
58
+ if len(entries) > MAX_PACKAGES:
59
+ raise SkillPackageError("Too many pinned Skill packages")
60
+ if len({entry.skill_id for entry in entries}) != len(entries) or len(
61
+ {entry.name.casefold() for entry in entries}
62
+ ) != len(entries):
63
+ raise SkillPackageError("Pinned Skill identities and names must be unique")
64
+
65
+
66
+ def stage_packages(packages: list[SkillPackage], directory: Path) -> tuple[PinnedSkillArchive, ...]:
67
+ """Copy verified archives into a private request delivery directory."""
68
+ if len(packages) > MAX_PACKAGES:
69
+ raise SkillPackageError("Too many pinned Skill packages")
70
+ entries = tuple(
71
+ PinnedSkillArchive(
72
+ skill_id=package.ref.skill_id,
73
+ version_id=package.ref.version_id,
74
+ name=package.ref.name,
75
+ content_hash=package.ref.content_hash.render() if package.ref.content_hash else "",
76
+ archive_name=(package.ref.content_hash.value if package.ref.content_hash else "")
77
+ + ".zip",
78
+ )
79
+ for package in packages
80
+ )
81
+ validate_package_set(entries)
82
+ for package, entry in zip(packages, entries, strict=True):
83
+ content = read_archive(package.archive_path)
84
+ if "sha256:" + hashlib.sha256(content).hexdigest() != entry.content_hash:
85
+ raise SkillPackageError("Pinned Skill archive digest mismatch")
86
+ target = directory / entry.archive_name
87
+ if target.exists():
88
+ if read_archive(target) != content:
89
+ raise SkillPackageError("Pinned Skill archive destination conflict")
90
+ continue
91
+ with target.open("xb") as output:
92
+ os.chmod(target, 0o600)
93
+ output.write(content)
94
+ return entries
95
+
96
+
97
+ def load_pinned_packages(
98
+ entries: tuple[PinnedSkillArchive, ...], directory: Path
99
+ ) -> list[LocalSkill]:
100
+ """Use only supplied archives; never read environment Skill directories or APIs."""
101
+ validate_package_set(entries)
102
+ store = PackageStore(
103
+ directory / "extracted-packages", namespace="pinned-request", require_hash=True
104
+ )
105
+ skills = []
106
+ for entry in entries:
107
+ package = store.store_archive(
108
+ entry.skill_ref(), read_archive(directory / entry.archive_name)
109
+ )
110
+ skill = load_local_skill(package.root_dir)
111
+ if skill.name != entry.name:
112
+ raise SkillPackageError("Pinned Skill name does not match its manifest")
113
+ skills.append(skill)
114
+ return skills
@@ -5,7 +5,11 @@ from dataclasses import dataclass, field
5
5
  from pathlib import Path
6
6
  from typing import Any
7
7
 
8
+ from pydantic import ValidationError
9
+
10
+ from ksadk.skills.package_store import SkillPackageError
8
11
  from ksadk.skills.runtime.base import normalize_skill_names
12
+ from ksadk.skills.runtime.pinned import PinnedSkillArchive, validate_package_set
9
13
 
10
14
 
11
15
  class SkillWorkflowRequestError(ValueError):
@@ -16,6 +20,9 @@ class SkillWorkflowRequestError(ValueError):
16
20
  class SkillWorkflowRequest:
17
21
  workflow_prompt: str = ""
18
22
  skill_names: list[str] = field(default_factory=list)
23
+ pinned_packages: tuple[PinnedSkillArchive, ...] | None = None
24
+ package_directory: Path | None = None
25
+ collect_artifacts: bool = False
19
26
 
20
27
 
21
28
  def parse_workflow_request(argv: list[str]) -> SkillWorkflowRequest:
@@ -56,9 +63,33 @@ def _request_from_json_file(path: str) -> SkillWorkflowRequest:
56
63
  raise SkillWorkflowRequestError("request file must contain a JSON object")
57
64
  prompt = payload.get("workflow_prompt", payload.get("prompt", ""))
58
65
  skill_names = _skill_names_from_payload(payload)
66
+ pinned_packages = None
67
+ if "pinned_protocol_version" in payload and "pinned_packages" not in payload:
68
+ raise SkillWorkflowRequestError("Pinned Skill manifest is missing")
69
+ if "pinned_packages" in payload:
70
+ version = payload.get("pinned_protocol_version")
71
+ if type(version) is not int or version != 1:
72
+ raise SkillWorkflowRequestError("Unsupported pinned Skill protocol version")
73
+ raw = payload["pinned_packages"]
74
+ if not isinstance(raw, list):
75
+ raise SkillWorkflowRequestError("pinned_packages must be an array")
76
+ try:
77
+ pinned_packages = tuple(PinnedSkillArchive.model_validate(item) for item in raw)
78
+ validate_package_set(pinned_packages)
79
+ except (ValidationError, SkillPackageError):
80
+ raise SkillWorkflowRequestError("Invalid pinned Skill manifest") from None
81
+ allowed = {entry.name.casefold() for entry in pinned_packages}
82
+ if any(name.casefold() not in allowed for name in skill_names):
83
+ raise SkillWorkflowRequestError("Selected Skill is not in the pinned manifest")
84
+ collect_artifacts = payload.get("collect_artifacts", False)
85
+ if type(collect_artifacts) is not bool or (collect_artifacts and pinned_packages is None):
86
+ raise SkillWorkflowRequestError("Artifact collection requires a pinned request")
59
87
  return SkillWorkflowRequest(
60
88
  workflow_prompt=str(prompt or ""),
61
89
  skill_names=skill_names,
90
+ pinned_packages=pinned_packages,
91
+ package_directory=Path(path).resolve().parent if pinned_packages is not None else None,
92
+ collect_artifacts=collect_artifacts,
62
93
  )
63
94
 
64
95
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  from collections.abc import Mapping
5
+ from dataclasses import replace
5
6
  from typing import Any
6
7
  from urllib.parse import quote, urlsplit, urlunsplit
7
8
 
@@ -41,26 +42,44 @@ class SkillServiceClient:
41
42
  extra_headers: Mapping[str, str] | None = None,
42
43
  timeout: float = 60.0,
43
44
  transport: httpx.BaseTransport | None = None,
45
+ allow_env_fallback: bool = True,
44
46
  ):
47
+ self.allow_env_fallback = allow_env_fallback
48
+ resolve_env = _env if allow_env_fallback else lambda *names: ""
45
49
  self.base_url = _normalize_base_url(base_url)
46
50
  self.token = token
47
- self.access_key = access_key or _env(
51
+ self.access_key = access_key or resolve_env(
48
52
  "KSADK_SKILL_SERVICE_ACCESS_KEY", "KSYUN_ACCESS_KEY", "KS3_ACCESS_KEY"
49
53
  )
50
- self.secret_key = secret_key or _env(
54
+ self.secret_key = secret_key or resolve_env(
51
55
  "KSADK_SKILL_SERVICE_SECRET_KEY", "KSYUN_SECRET_KEY", "KS3_SECRET_KEY"
52
56
  )
53
- self.account_id = account_id or _env("KSADK_SKILL_SERVICE_ACCOUNT_ID", "KSYUN_ACCOUNT_ID")
57
+ self.account_id = account_id or resolve_env(
58
+ "KSADK_SKILL_SERVICE_ACCOUNT_ID", "KSYUN_ACCOUNT_ID"
59
+ )
54
60
  self.logical_region = (
55
- region or _env("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
61
+ region or resolve_env("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
62
+ )
63
+ if not allow_env_fallback:
64
+ if not region or region.strip().lower() == "pre-online":
65
+ raise ValueError("Explicit Skill clients require a concrete region")
66
+ if token and (access_key or secret_key):
67
+ raise ValueError("Explicit Skill clients cannot mix token and signing credentials")
68
+ if bool(access_key) != bool(secret_key):
69
+ raise ValueError("Both signing credentials are required")
70
+ self.region = (
71
+ _normalize_control_region(self.logical_region)
72
+ if allow_env_fallback
73
+ else self.logical_region.strip()
74
+ )
75
+ self.custom_source = (
76
+ _resolve_custom_source(self.logical_region) if allow_env_fallback else ""
56
77
  )
57
- self.region = _normalize_control_region(self.logical_region)
58
- self.custom_source = _resolve_custom_source(self.logical_region)
59
- self.api_version = api_version or os.environ.get(
60
- "KSADK_SKILL_SERVICE_API_VERSION", "2024-06-12"
78
+ self.api_version = (
79
+ api_version or resolve_env("KSADK_SKILL_SERVICE_API_VERSION") or "2024-06-12"
61
80
  )
62
- self.sign_service = sign_service or os.environ.get(
63
- "KSADK_SKILL_SERVICE_SIGN_SERVICE", "aicp"
81
+ self.sign_service = (
82
+ sign_service or resolve_env("KSADK_SKILL_SERVICE_SIGN_SERVICE") or "aicp"
64
83
  )
65
84
  self.extra_headers = dict(extra_headers or {})
66
85
  self.timeout = timeout
@@ -71,6 +90,7 @@ class SkillServiceClient:
71
90
  secret_access_key=self.secret_key,
72
91
  region=self.region,
73
92
  service=self.sign_service,
93
+ allow_env_fallback=allow_env_fallback,
74
94
  )
75
95
 
76
96
  def action_url(self, action: str) -> str:
@@ -87,21 +107,113 @@ class SkillServiceClient:
87
107
  {"PageNumber": page_number, "PageSize": page_size},
88
108
  )
89
109
 
90
- def list_skills_by_space_id(self, space_id: str) -> SkillListResponse:
91
- if self._is_kop_mode():
92
- payload = self._get_json(
93
- "ListSkillsBySpaceId",
94
- {"SpaceId": space_id, "PageNumber": 1, "PageSize": 100},
95
- )
96
- else:
110
+ def list_skills_by_space_id(self, space_id: str, *, max_pages: int = 20) -> SkillListResponse:
111
+ if type(max_pages) is not int or not 1 <= max_pages <= 1000:
112
+ raise ValueError("Skill directory page budget must be 1..1000")
113
+ if not self._is_kop_mode():
114
+ # Legacy REST endpoints do not advertise a paging contract. Preserve
115
+ # their request shape and report known incompleteness explicitly.
97
116
  payload = self._get_json("ListSkillsBySpaceId", {"SpaceId": space_id})
98
- return SkillListResponse.from_payload(payload, space_id=space_id)
117
+ result = SkillListResponse.from_payload(payload, space_id=space_id)
118
+ if result.space_id != space_id:
119
+ raise ValueError("Skill directory does not match the requested space")
120
+ if result.total_count is not None and result.total_count > len(result.skills):
121
+ return replace(result, truncated=True, pagination_warning="pagination_unavailable")
122
+ return result
123
+ skills = []
124
+ seen = set()
125
+ total = None
126
+ for page_number in range(1, max_pages + 1):
127
+ result = self.list_skills_page(space_id, page_number=page_number)
128
+ if page_number > 1 and result.total_count != total:
129
+ return replace(
130
+ result,
131
+ skills=skills,
132
+ truncated=True,
133
+ next_page=None,
134
+ pagination_warning="directory_changed",
135
+ )
136
+ total = result.total_count
137
+ identities = [(skill.skill_id, skill.version_id) for skill in result.skills]
138
+ if (
139
+ any(not identity[0] for identity in identities)
140
+ or len(set(identities)) != len(identities)
141
+ or any(identity in seen for identity in identities)
142
+ ):
143
+ return replace(
144
+ result,
145
+ skills=skills,
146
+ truncated=True,
147
+ next_page=None,
148
+ pagination_warning="pagination_repeated",
149
+ )
150
+ seen.update(identities)
151
+ skills.extend(result.skills)
152
+ if total is not None and len(skills) > total:
153
+ return replace(
154
+ result,
155
+ skills=skills,
156
+ truncated=True,
157
+ next_page=None,
158
+ pagination_warning="directory_changed",
159
+ )
160
+ if total is not None and len(skills) == total:
161
+ return replace(result, skills=skills, truncated=False, next_page=None)
162
+ if len(result.skills) < 100:
163
+ incomplete = total is not None and len(skills) < total
164
+ return replace(
165
+ result,
166
+ skills=skills,
167
+ truncated=incomplete,
168
+ next_page=None,
169
+ pagination_warning="directory_incomplete" if incomplete else "",
170
+ )
171
+ return replace(
172
+ result,
173
+ skills=skills,
174
+ truncated=True,
175
+ next_page=max_pages + 1,
176
+ pagination_warning="page_budget_exhausted",
177
+ )
178
+
179
+ def list_skills_page(
180
+ self, space_id: str, *, page_number: int = 1, page_size: int = 100
181
+ ) -> SkillListResponse:
182
+ if not self._is_kop_mode():
183
+ raise ValueError("This Skill endpoint does not advertise pagination")
184
+ if (
185
+ type(page_number) is not int
186
+ or page_number < 1
187
+ or type(page_size) is not int
188
+ or not 1 <= page_size <= 100
189
+ ):
190
+ raise ValueError("Invalid Skill directory page parameters")
191
+ payload = self._get_json(
192
+ "ListSkillsBySpaceId",
193
+ {
194
+ "SpaceId": space_id,
195
+ "PageNumber": page_number,
196
+ "PageSize": page_size,
197
+ },
198
+ )
199
+ result = SkillListResponse.from_payload(payload, space_id=space_id)
200
+ if result.space_id != space_id or len(result.skills) > page_size:
201
+ raise ValueError("Skill directory page does not match the requested space or limit")
202
+ more = (
203
+ page_number * page_size < result.total_count
204
+ if result.total_count is not None
205
+ else len(result.skills) == page_size
206
+ )
207
+ return replace(result, truncated=more, next_page=page_number + 1 if more else None)
99
208
 
100
209
  def list_available_premade_skills(self) -> SkillListResponse:
101
210
  payload = self._get_json("ListAvailablePremadeSkills", {})
102
- return SkillListResponse.from_payload(
211
+ result = SkillListResponse.from_payload(
103
212
  payload, space_id="public", space_name="Public Skills"
104
213
  )
214
+ if result.total_count is not None and result.total_count > len(result.skills):
215
+ return replace(result, truncated=True, pagination_warning="pagination_unavailable")
216
+ return result
105
217
 
106
218
  def get_skill_download_url(self, skill: SkillRef) -> str:
107
219
  action = "GetSkillDownloadUrl" if skill.version_id else "GetPremadeSkillDownloadUrl"
@@ -115,15 +227,33 @@ class SkillServiceClient:
115
227
  data = payload.get("Data") or payload.get("data") or {}
116
228
  return str(data.get("DownloadUrl") or data.get("download_url") or "")
117
229
 
118
- def download_skill_archive(self, skill: SkillRef) -> bytes:
230
+ def download_skill_archive(
231
+ self, skill: SkillRef, *, max_bytes: int = 20 * 1024 * 1024
232
+ ) -> bytes:
233
+ if type(max_bytes) is not int or max_bytes < 1:
234
+ raise ValueError("Skill archive size limit must be a positive integer")
119
235
  download_url = self.get_skill_download_url(skill)
120
236
  if not download_url:
121
237
  raise ValueError(f"Skill Service did not return DownloadUrl for {skill.skill_id}")
122
- download_url = _rewrite_ks3_to_internal(download_url)
123
- with httpx.Client(**self._client_kwargs()) as client:
124
- response = client.get(download_url)
125
- response.raise_for_status()
126
- return bytes(response.content)
238
+ if self.allow_env_fallback:
239
+ download_url = _rewrite_ks3_to_internal(download_url)
240
+ try:
241
+ with httpx.Client(**self._client_kwargs()) as client:
242
+ with client.stream("GET", download_url) as response:
243
+ response.raise_for_status()
244
+ length = response.headers.get("content-length", "")
245
+ if length.isdigit() and int(length) > max_bytes:
246
+ raise ValueError("Skill archive exceeds download limit")
247
+ content = bytearray()
248
+ for chunk in response.iter_bytes(chunk_size=64 * 1024):
249
+ if len(content) + len(chunk) > max_bytes:
250
+ raise ValueError("Skill archive exceeds download limit")
251
+ content.extend(chunk)
252
+ return bytes(content)
253
+ except httpx.HTTPError:
254
+ # Download URLs can carry temporary credentials; do not expose the
255
+ # HTTP exception's URL through logs or the consumer's tool result.
256
+ raise ValueError("Skill archive download failed") from None
127
257
 
128
258
  def _get_json(self, action: str, params: dict[str, Any]) -> dict[str, Any]:
129
259
  if self._is_kop_mode():
@@ -155,6 +285,8 @@ class SkillServiceClient:
155
285
 
156
286
  def _client_kwargs(self) -> dict[str, Any]:
157
287
  kwargs: dict[str, Any] = {"timeout": self.timeout}
288
+ if not self.allow_env_fallback:
289
+ kwargs["trust_env"] = False
158
290
  if self.transport is not None:
159
291
  kwargs["transport"] = self.transport
160
292
  return kwargs
@@ -201,6 +333,7 @@ class SkillServiceClient:
201
333
  headers=headers,
202
334
  auth=self._auth.get_auth(),
203
335
  timeout=self.timeout,
336
+ allow_redirects=False,
204
337
  )
205
338
  requests_response.raise_for_status()
206
339
  data = requests_response.json()
@@ -219,8 +352,16 @@ class SkillServiceClient:
219
352
  def _requests(self) -> requests.Session:
220
353
  if self._requests_session is None:
221
354
  self._requests_session = requests.Session()
355
+ if not self.allow_env_fallback:
356
+ self._requests_session.trust_env = False
222
357
  return self._requests_session
223
358
 
359
+ def close(self) -> None:
360
+ """Release the signing session when its owning activation ends."""
361
+ if self._requests_session is not None:
362
+ self._requests_session.close()
363
+ self._requests_session = None
364
+
224
365
  def _is_kop_mode(self) -> bool:
225
366
  """Match only exact AICP control-plane endpoints.
226
367
 
@@ -287,9 +428,7 @@ def _rewrite_ks3_to_internal(url: str) -> str:
287
428
 
288
429
  from ksadk.common.constants import get_ks3_endpoints
289
430
 
290
- region = os.environ.get(
291
- "KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION"
292
- ) or "cn-beijing-6"
431
+ region = os.environ.get("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
293
432
  public_ep, internal_ep = get_ks3_endpoints(region)
294
433
  if not public_ep or not internal_ep:
295
434
  return url