agentengine-sdk-python 0.6.4__py3-none-any.whl → 0.7.0__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 (486) hide show
  1. agentengine_sdk_python-0.7.0.dist-info/METADATA +181 -0
  2. agentengine_sdk_python-0.7.0.dist-info/RECORD +482 -0
  3. {agentengine_sdk_python-0.6.4.dist-info → agentengine_sdk_python-0.7.0.dist-info}/WHEEL +1 -1
  4. agentengine_sdk_python-0.7.0.dist-info/entry_points.txt +3 -0
  5. agentengine_sdk_python-0.7.0.dist-info/licenses/LICENSE +175 -0
  6. agentengine_sdk_python-0.7.0.dist-info/top_level.txt +2 -0
  7. ksadk/__init__.py +13 -0
  8. ksadk/__main__.py +4 -0
  9. ksadk/a2a/__init__.py +15 -0
  10. ksadk/a2a/card_builder.py +64 -0
  11. ksadk/a2a/client.py +309 -0
  12. ksadk/a2a/executor.py +201 -0
  13. ksadk/a2a/server.py +79 -0
  14. ksadk/agents/__init__.py +20 -0
  15. ksadk/agents/base.py +370 -0
  16. ksadk/agents/context.py +38 -0
  17. ksadk/agents/event.py +35 -0
  18. ksadk/agents/loop_agent.py +71 -0
  19. ksadk/agents/parallel_agent.py +109 -0
  20. ksadk/agents/runner_adapter.py +24 -0
  21. ksadk/agents/sequential_agent.py +34 -0
  22. ksadk/api/__init__.py +3 -0
  23. ksadk/api/client.py +2246 -0
  24. ksadk/builders/__init__.py +20 -0
  25. ksadk/builders/base.py +66 -0
  26. ksadk/builders/code_builder.py +1990 -0
  27. ksadk/builders/container_builder.py +786 -0
  28. ksadk/builders/framework_requirements.py +59 -0
  29. ksadk/builders/ks3_uploader.py +389 -0
  30. ksadk/builders/mcp_builder.py +476 -0
  31. ksadk/builders/requirements_utils.py +75 -0
  32. ksadk/cli/__init__.py +531 -0
  33. ksadk/cli/__main__.py +4 -0
  34. ksadk/cli/agent_ref.py +204 -0
  35. ksadk/cli/cmd_a2a.py +167 -0
  36. ksadk/cli/cmd_agent.py +201 -0
  37. ksadk/cli/cmd_build.py +270 -0
  38. ksadk/cli/cmd_completion.py +304 -0
  39. ksadk/cli/cmd_config.py +758 -0
  40. ksadk/cli/cmd_create.py +2304 -0
  41. ksadk/cli/cmd_dashboard.py +900 -0
  42. ksadk/cli/cmd_deploy.py +704 -0
  43. ksadk/cli/cmd_destroy.py +345 -0
  44. ksadk/cli/cmd_files.py +1227 -0
  45. ksadk/cli/cmd_hermes.py +1263 -0
  46. ksadk/cli/cmd_invoke.py +1503 -0
  47. ksadk/cli/cmd_launch.py +564 -0
  48. ksadk/cli/cmd_mcp.py +1179 -0
  49. ksadk/cli/cmd_model.py +302 -0
  50. ksadk/cli/cmd_openclaw.py +3922 -0
  51. ksadk/cli/cmd_run.py +239 -0
  52. ksadk/cli/cmd_status.py +588 -0
  53. ksadk/cli/cmd_version.py +522 -0
  54. ksadk/cli/cmd_web.py +288 -0
  55. ksadk/cli/deploy_utils.py +87 -0
  56. ksadk/cli/dry_run.py +214 -0
  57. ksadk/cli/env_options.py +82 -0
  58. ksadk/cli/error_utils.py +525 -0
  59. ksadk/cli/global_options.py +31 -0
  60. ksadk/cli/local_runtime.py +97 -0
  61. ksadk/cli/model_catalog.py +136 -0
  62. ksadk/cli/network_options.py +412 -0
  63. ksadk/cli/resource_common.py +621 -0
  64. ksadk/cli/storage.py +84 -0
  65. ksadk/cli/ui.py +431 -0
  66. ksadk/cli/workflow_common.py +552 -0
  67. ksadk/common/__init__.py +14 -0
  68. ksadk/common/aicp_env.py +128 -0
  69. ksadk/common/auth.py +190 -0
  70. ksadk/common/constants.py +84 -0
  71. ksadk/common/llm_utils.py +61 -0
  72. ksadk/configs/__init__.py +61 -0
  73. ksadk/configs/env_registry.py +343 -0
  74. ksadk/configs/global_config.py +200 -0
  75. ksadk/configs/settings.py +706 -0
  76. ksadk/conversations/__init__.py +95 -0
  77. ksadk/conversations/attachment_storage.py +379 -0
  78. ksadk/conversations/attachments.py +774 -0
  79. ksadk/conversations/compaction_pipeline.py +387 -0
  80. ksadk/conversations/compaction_prompt.py +128 -0
  81. ksadk/conversations/context.py +303 -0
  82. ksadk/conversations/message_projection.py +269 -0
  83. ksadk/conversations/model_context.py +370 -0
  84. ksadk/conversations/model_options.py +136 -0
  85. ksadk/conversations/normalize.py +446 -0
  86. ksadk/conversations/reasoning_markup.py +91 -0
  87. ksadk/conversations/run_kinds.py +61 -0
  88. ksadk/conversations/run_status.py +53 -0
  89. ksadk/conversations/runtime.py +5276 -0
  90. ksadk/conversations/semantic_summary.py +359 -0
  91. ksadk/conversations/session_title.py +254 -0
  92. ksadk/deployment/__init__.py +83 -0
  93. ksadk/deployment/agent_access.py +226 -0
  94. ksadk/deployment/base.py +229 -0
  95. ksadk/deployment/manager.py +332 -0
  96. ksadk/deployment/providers/__init__.py +10 -0
  97. ksadk/deployment/providers/serverless.py +1115 -0
  98. ksadk/deployment/registry.py +120 -0
  99. ksadk/deployment/state.py +78 -0
  100. ksadk/deployment/ui_config.py +21 -0
  101. ksadk/detection/__init__.py +7 -0
  102. ksadk/detection/detector.py +431 -0
  103. ksadk/detection/mcp_detector.py +250 -0
  104. ksadk/hermes_terminal.py +467 -0
  105. ksadk/identity/__init__.py +17 -0
  106. ksadk/identity/resolver.py +385 -0
  107. ksadk/knowledge_base/__init__.py +62 -0
  108. ksadk/knowledge_base/adk_tool.py +47 -0
  109. ksadk/knowledge_base/client.py +297 -0
  110. ksadk/knowledge_base/langchain_tool.py +55 -0
  111. ksadk/knowledge_base/service.py +66 -0
  112. ksadk/knowledge_base/tool.py +50 -0
  113. ksadk/markdown.py +169 -0
  114. ksadk/mcp_runtime/__init__.py +231 -0
  115. ksadk/memory/__init__.py +57 -0
  116. ksadk/memory/adk/__init__.py +51 -0
  117. ksadk/memory/adk/backends/__init__.py +5 -0
  118. ksadk/memory/adk/backends/base_ltm_backend.py +52 -0
  119. ksadk/memory/adk/backends/http_ltm_backend.py +183 -0
  120. ksadk/memory/adk/backends/inmemory_ltm_backend.py +96 -0
  121. ksadk/memory/adk/backends/sdk_ltm_backend.py +456 -0
  122. ksadk/memory/adk/long_term_memory.py +273 -0
  123. ksadk/memory/adk/resilient_session_service.py +268 -0
  124. ksadk/memory/adk/short_term_memory.py +304 -0
  125. ksadk/memory/adk_tool.py +31 -0
  126. ksadk/memory/backends/__init__.py +6 -0
  127. ksadk/memory/backends/base.py +103 -0
  128. ksadk/memory/backends/memory.py +112 -0
  129. ksadk/memory/backends/redis.py +146 -0
  130. ksadk/memory/langchain_tool.py +39 -0
  131. ksadk/memory/ltm_backend_factory.py +24 -0
  132. ksadk/memory/manager.py +215 -0
  133. ksadk/memory/service.py +172 -0
  134. ksadk/memory/tool.py +96 -0
  135. ksadk/model_policy.py +223 -0
  136. ksadk/openclaw_gateway.py +378 -0
  137. ksadk/runners/__init__.py +8 -0
  138. ksadk/runners/adk_runner.py +1994 -0
  139. ksadk/runners/base_runner.py +305 -0
  140. ksadk/runners/deepagents_runner.py +13 -0
  141. ksadk/runners/factory.py +73 -0
  142. ksadk/runners/langchain_runner.py +751 -0
  143. ksadk/runners/langgraph_runner.py +985 -0
  144. ksadk/runners/patch_langchain.py +187 -0
  145. ksadk/runners/remote_runner.py +792 -0
  146. ksadk/runners/usage_accumulator.py +38 -0
  147. ksadk/runners/utils/__init__.py +19 -0
  148. ksadk/runners/utils/langfuse.py +230 -0
  149. ksadk/runners/utils/loader.py +62 -0
  150. ksadk/runtime_context.py +166 -0
  151. ksadk/runtime_state.py +25 -0
  152. ksadk/sandbox/__init__.py +28 -0
  153. ksadk/sandbox/backends/__init__.py +9 -0
  154. ksadk/sandbox/backends/e2b.py +154 -0
  155. ksadk/sandbox/backends/local_process.py +131 -0
  156. ksadk/sandbox/base.py +101 -0
  157. ksadk/sandbox/factory.py +53 -0
  158. ksadk/sandbox/registry.py +187 -0
  159. ksadk/server/__init__.py +7 -0
  160. ksadk/server/api_models.py +73 -0
  161. ksadk/server/app.py +3931 -0
  162. ksadk/server/static/assets/ArtifactsPanel-D-SSn2ee.js +1 -0
  163. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +9 -0
  164. ksadk/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  165. ksadk/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  166. ksadk/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  167. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  168. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  169. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  170. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  171. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  172. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  173. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  174. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  175. ksadk/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  176. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  177. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  178. ksadk/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  179. ksadk/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  180. ksadk/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  181. ksadk/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  182. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  183. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  184. ksadk/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  185. ksadk/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  186. ksadk/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  187. ksadk/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  188. ksadk/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  189. ksadk/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  190. ksadk/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  191. ksadk/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  192. ksadk/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  193. ksadk/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  194. ksadk/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  195. ksadk/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  196. ksadk/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  197. ksadk/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  198. ksadk/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  199. ksadk/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  200. ksadk/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  201. ksadk/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  202. ksadk/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  203. ksadk/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  204. ksadk/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  205. ksadk/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  206. ksadk/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  207. ksadk/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  208. ksadk/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  209. ksadk/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  210. ksadk/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  211. ksadk/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  212. ksadk/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  213. ksadk/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  214. ksadk/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  215. ksadk/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  216. ksadk/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  217. ksadk/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  218. ksadk/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  219. ksadk/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  220. ksadk/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  221. ksadk/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  222. ksadk/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  223. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +8 -0
  224. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
  225. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +303 -0
  226. ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
  227. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +1 -0
  228. ksadk/server/static/assets/addon-fit-DthTIhi3.js +1 -0
  229. ksadk/server/static/assets/apl-CnwPGSsG.js +1 -0
  230. ksadk/server/static/assets/arc-BA13sHc9.js +1 -0
  231. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +1 -0
  232. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-DzJzgVoL.js +36 -0
  233. ksadk/server/static/assets/asciiarmor-qTkVPQu6.js +1 -0
  234. ksadk/server/static/assets/asn1-Dr8qZg38.js +1 -0
  235. ksadk/server/static/assets/asterisk-Bja0s6e1.js +1 -0
  236. ksadk/server/static/assets/blockDiagram-GPEHLZMM-UTdVcZhn.js +132 -0
  237. ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
  238. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dix0GD4m.js +10 -0
  239. ksadk/server/static/assets/channel-CTuydARX.js +1 -0
  240. ksadk/server/static/assets/chunk-2J33WTMH-C2JxuZ42.js +1 -0
  241. ksadk/server/static/assets/chunk-4BX2VUAB-Be57QPgD.js +1 -0
  242. ksadk/server/static/assets/chunk-55IACEB6-WjSuy4nv.js +1 -0
  243. ksadk/server/static/assets/chunk-727SXJPM-BOovP-b5.js +206 -0
  244. ksadk/server/static/assets/chunk-AQP2D5EJ-DOmZNmWj.js +231 -0
  245. ksadk/server/static/assets/chunk-FMBD7UC4-DzwlodkU.js +15 -0
  246. ksadk/server/static/assets/chunk-ND2GUHAM-DMqAikEU.js +1 -0
  247. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +1 -0
  248. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +1 -0
  249. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +1 -0
  250. ksadk/server/static/assets/clike-DHH8Ad3s.js +1 -0
  251. ksadk/server/static/assets/clojure-BflJGmDX.js +1 -0
  252. ksadk/server/static/assets/cmake-CyVbuzPu.js +1 -0
  253. ksadk/server/static/assets/cobol-B_OZ4V-R.js +1 -0
  254. ksadk/server/static/assets/coffeescript-B2pKbFk8.js +1 -0
  255. ksadk/server/static/assets/commonlisp-CcllspGY.js +1 -0
  256. ksadk/server/static/assets/cose-bilkent-S5V4N54A-Zhy2GBnP.js +1 -0
  257. ksadk/server/static/assets/crystal-M5-qzICs.js +1 -0
  258. ksadk/server/static/assets/css-CYpP4FRV.js +1 -0
  259. ksadk/server/static/assets/cypher-p9eYesGn.js +1 -0
  260. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +321 -0
  261. ksadk/server/static/assets/d-BhMjBjQP.js +1 -0
  262. ksadk/server/static/assets/dagre-BM42HDAG-CbKrtIUz.js +4 -0
  263. ksadk/server/static/assets/dagre-Bx709z4p.js +1 -0
  264. ksadk/server/static/assets/defaultLocale-C8Fc0cco.js +1 -0
  265. ksadk/server/static/assets/diagram-2AECGRRQ-BRApgQRK.js +43 -0
  266. ksadk/server/static/assets/diagram-5GNKFQAL-D0xbnDiK.js +10 -0
  267. ksadk/server/static/assets/diagram-KO2AKTUF-CVugVI9L.js +3 -0
  268. ksadk/server/static/assets/diagram-LMA3HP47-DozUGgee.js +24 -0
  269. ksadk/server/static/assets/diagram-OG6HWLK6-ZOYsKlru.js +24 -0
  270. ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
  271. ksadk/server/static/assets/dist-2hInLS_J.js +9 -0
  272. ksadk/server/static/assets/dist-8EEyGgDx.js +1 -0
  273. ksadk/server/static/assets/dist-8_SfK1IP.js +1 -0
  274. ksadk/server/static/assets/dist-B0NP_Z0z.js +23 -0
  275. ksadk/server/static/assets/dist-BIJVDMuB.js +1 -0
  276. ksadk/server/static/assets/dist-BmlMPsCc.js +2 -0
  277. ksadk/server/static/assets/dist-BrCcQ47T.js +1 -0
  278. ksadk/server/static/assets/dist-BssVmjIo.js +6 -0
  279. ksadk/server/static/assets/dist-C3HIIaN5.js +1 -0
  280. ksadk/server/static/assets/dist-CPBtqRTW.js +1 -0
  281. ksadk/server/static/assets/dist-CkEKJFtk.js +1 -0
  282. ksadk/server/static/assets/dist-D-JMdWPQ.js +1 -0
  283. ksadk/server/static/assets/dist-D-xOD048.js +1 -0
  284. ksadk/server/static/assets/dist-D57wnGWd.js +1 -0
  285. ksadk/server/static/assets/dist-DL_NKc_z.js +1 -0
  286. ksadk/server/static/assets/dist-DMezvBGJ.js +1 -0
  287. ksadk/server/static/assets/dist-DmFaq_Iy.js +1 -0
  288. ksadk/server/static/assets/dist-Dp0k7bWI.js +1 -0
  289. ksadk/server/static/assets/dist-DpKtt4Bo.js +1 -0
  290. ksadk/server/static/assets/dist-DyOkZmze.js +11 -0
  291. ksadk/server/static/assets/dist-DyWsb78Q.js +1 -0
  292. ksadk/server/static/assets/dist-gX6GOLKq.js +1 -0
  293. ksadk/server/static/assets/dockerfile-BLkNEvjs.js +1 -0
  294. ksadk/server/static/assets/dtd-DTF72YNO.js +1 -0
  295. ksadk/server/static/assets/dylan-C6jEEEk-.js +1 -0
  296. ksadk/server/static/assets/ebnf-D4c0_ac3.js +1 -0
  297. ksadk/server/static/assets/ecl-BSZaIHnp.js +1 -0
  298. ksadk/server/static/assets/eiffel-BEjRio4Q.js +1 -0
  299. ksadk/server/static/assets/elm-Cshzl8qu.js +1 -0
  300. ksadk/server/static/assets/erDiagram-TEJ5UH35-Bk-9bgE5.js +85 -0
  301. ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
  302. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +1 -0
  303. ksadk/server/static/assets/factor-D7LVTn2l.js +1 -0
  304. ksadk/server/static/assets/fcl-ClOhbFR7.js +1 -0
  305. ksadk/server/static/assets/flowDiagram-I6XJVG4X-Dn9kZVuZ.js +162 -0
  306. ksadk/server/static/assets/forth-Cezjo90N.js +1 -0
  307. ksadk/server/static/assets/fortran-Bt6PBEDR.js +1 -0
  308. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-BGxXlJqm.js +292 -0
  309. ksadk/server/static/assets/gas-BHEdbvp9.js +1 -0
  310. ksadk/server/static/assets/gherkin-oBAE_ms0.js +1 -0
  311. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +1 -0
  312. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-C7Q0X-wi.js +106 -0
  313. ksadk/server/static/assets/graphlib-B8gBHxth.js +1 -0
  314. ksadk/server/static/assets/groovy-BC3IOsC8.js +1 -0
  315. ksadk/server/static/assets/haskell-BRsoo5mP.js +1 -0
  316. ksadk/server/static/assets/haxe-DIz0ZZqd.js +1 -0
  317. ksadk/server/static/assets/http-CLVgA2GD.js +1 -0
  318. ksadk/server/static/assets/idl-BUZw3wgd.js +1 -0
  319. ksadk/server/static/assets/index-C00Lwg3L.js +165 -0
  320. ksadk/server/static/assets/index-DAURbCsP.css +1 -0
  321. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +1 -0
  322. ksadk/server/static/assets/infoDiagram-5YYISTIA-BO_CSqq5.js +2 -0
  323. ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
  324. ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-eYLPLd46.js +70 -0
  325. ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
  326. ksadk/server/static/assets/journeyDiagram-JHISSGLW-De9geSb0.js +139 -0
  327. ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
  328. ksadk/server/static/assets/kanban-definition-UN3LZRKU-Cs80kQto.js +89 -0
  329. ksadk/server/static/assets/katex-DSrCFD8n.js +265 -0
  330. ksadk/server/static/assets/linear-CN9sbKTF.js +1 -0
  331. ksadk/server/static/assets/livescript-BXxG0Yva.js +1 -0
  332. ksadk/server/static/assets/lua-CiA1ziua.js +1 -0
  333. ksadk/server/static/assets/mathematica-u8YMmbU0.js +1 -0
  334. ksadk/server/static/assets/mbox-BEMVcqjs.js +1 -0
  335. ksadk/server/static/assets/mermaid-parser.core-DlgSBU8l.js +161 -0
  336. ksadk/server/static/assets/mindmap-definition-RKZ34NQL-9afz7Oug.js +96 -0
  337. ksadk/server/static/assets/mirc-C9zpzAZU.js +1 -0
  338. ksadk/server/static/assets/mllike-B45xgp2S.js +1 -0
  339. ksadk/server/static/assets/modelica-CqHI_q-D.js +1 -0
  340. ksadk/server/static/assets/mscgen-qgSLujhx.js +1 -0
  341. ksadk/server/static/assets/mumps-CW_TBmxz.js +1 -0
  342. ksadk/server/static/assets/nginx-BMaDbqW3.js +1 -0
  343. ksadk/server/static/assets/nsis-AQ_alPln.js +1 -0
  344. ksadk/server/static/assets/ntriples-d28e9m0E.js +1 -0
  345. ksadk/server/static/assets/octave-D2Q8cUp1.js +1 -0
  346. ksadk/server/static/assets/ordinal-hYBb2elL.js +1 -0
  347. ksadk/server/static/assets/oz-BwTct_5T.js +1 -0
  348. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +1 -0
  349. ksadk/server/static/assets/pascal-Dp_KdFgX.js +1 -0
  350. ksadk/server/static/assets/perl-CdEHsPfU.js +1 -0
  351. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +1 -0
  352. ksadk/server/static/assets/pieDiagram-4H26LBE5-DPv_VstN.js +30 -0
  353. ksadk/server/static/assets/pig-AF4Hwhju.js +1 -0
  354. ksadk/server/static/assets/powershell-CzG71I4L.js +1 -0
  355. ksadk/server/static/assets/properties-C357ku5U.js +1 -0
  356. ksadk/server/static/assets/protobuf-D1ij_kNL.js +1 -0
  357. ksadk/server/static/assets/pug-Bugr-47h.js +1 -0
  358. ksadk/server/static/assets/puppet-B4hC2X4m.js +1 -0
  359. ksadk/server/static/assets/python-BqYw9LYJ.js +1 -0
  360. ksadk/server/static/assets/q-B9NhS7L_.js +1 -0
  361. ksadk/server/static/assets/quadrantDiagram-W4KKPZXB-o77wZ1XK.js +7 -0
  362. ksadk/server/static/assets/r-DADKenSm.js +1 -0
  363. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +1 -0
  364. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-BYVw81VC.js +84 -0
  365. ksadk/server/static/assets/rpm-gpDK5sbt.js +1 -0
  366. ksadk/server/static/assets/ruby-DsYpTuWg.js +1 -0
  367. ksadk/server/static/assets/sankeyDiagram-5OEKKPKP-B7nZFMKT.js +40 -0
  368. ksadk/server/static/assets/sas-C2OyD2Y6.js +1 -0
  369. ksadk/server/static/assets/scheme-CyDdOh7e.js +1 -0
  370. ksadk/server/static/assets/sequenceDiagram-3UESZ5HK-BGRRrFw5.js +162 -0
  371. ksadk/server/static/assets/shell-Du5Qg9im.js +1 -0
  372. ksadk/server/static/assets/sieve-BAxa3IjF.js +1 -0
  373. ksadk/server/static/assets/simple-mode-DRpGK0lJ.js +1 -0
  374. ksadk/server/static/assets/smalltalk-BLp5-jwC.js +1 -0
  375. ksadk/server/static/assets/solr-BBopId9w.js +1 -0
  376. ksadk/server/static/assets/sparql-Dz-mlCAC.js +1 -0
  377. ksadk/server/static/assets/spreadsheet-CTIncYxj.js +1 -0
  378. ksadk/server/static/assets/sql-DcCJ9jop.js +1 -0
  379. ksadk/server/static/assets/stateDiagram-AJRCARHV-BUfHCoPs.js +1 -0
  380. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +1 -0
  381. ksadk/server/static/assets/stex-sDrdk2BW.js +1 -0
  382. ksadk/server/static/assets/stylus-DLLZ8dgm.js +1 -0
  383. ksadk/server/static/assets/swift-DKB6_1j6.js +1 -0
  384. ksadk/server/static/assets/tcl-BGfruO1u.js +1 -0
  385. ksadk/server/static/assets/textile-DWBqthVk.js +1 -0
  386. ksadk/server/static/assets/tiddlywiki-VlUiK86J.js +1 -0
  387. ksadk/server/static/assets/tiki-CxVlf5KZ.js +1 -0
  388. ksadk/server/static/assets/timeline-definition-PNZ67QCA-FbCTGrf9.js +120 -0
  389. ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
  390. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +1 -0
  391. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +1 -0
  392. ksadk/server/static/assets/troff-C2dAgh7P.js +1 -0
  393. ksadk/server/static/assets/ttcn-BePYh-hG.js +1 -0
  394. ksadk/server/static/assets/ttcn-cfg-CY0aot7Q.js +1 -0
  395. ksadk/server/static/assets/turtle-BDLWE2cD.js +1 -0
  396. ksadk/server/static/assets/vb-BthdM_4N.js +1 -0
  397. ksadk/server/static/assets/vbscript-D9f6rSsU.js +1 -0
  398. ksadk/server/static/assets/velocity-CqftRsjg.js +1 -0
  399. ksadk/server/static/assets/vennDiagram-CIIHVFJN-DWgwtPsJ.js +34 -0
  400. ksadk/server/static/assets/verilog-D-x6ne0Z.js +1 -0
  401. ksadk/server/static/assets/vhdl-CMrOq2q1.js +1 -0
  402. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +1 -0
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-2x8G-tTM.js +78 -0
  404. ksadk/server/static/assets/webidl-D5jiJvOU.js +1 -0
  405. ksadk/server/static/assets/xquery-fj_R-kMw.js +1 -0
  406. ksadk/server/static/assets/xterm-DooSxjI5.js +36 -0
  407. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-Drma3AYl.js +7 -0
  408. ksadk/server/static/assets/yacas-CXXgtw0p.js +1 -0
  409. ksadk/server/static/assets/z80-CL1naaMV.js +1 -0
  410. ksadk/server/static/favicon.svg +1 -0
  411. ksadk/server/static/icons.svg +24 -0
  412. ksadk/server/static/index.html +14 -0
  413. ksadk/server/terminal_sessions.py +551 -0
  414. ksadk/sessions/__init__.py +279 -0
  415. ksadk/sessions/base.py +354 -0
  416. ksadk/sessions/continuity.py +337 -0
  417. ksadk/sessions/errors.py +7 -0
  418. ksadk/sessions/in_memory.py +273 -0
  419. ksadk/sessions/local_service.py +949 -0
  420. ksadk/sessions/postgres_service.py +901 -0
  421. ksadk/sessions/resilience.py +52 -0
  422. ksadk/sessions/resilient.py +360 -0
  423. ksadk/sessions/sqlite_service.py +13 -0
  424. ksadk/skills/__init__.py +9 -0
  425. ksadk/skills/loader.py +46 -0
  426. ksadk/skills/models.py +120 -0
  427. ksadk/skills/package_store.py +104 -0
  428. ksadk/skills/runtime/__init__.py +17 -0
  429. ksadk/skills/runtime/agent.py +183 -0
  430. ksadk/skills/runtime/artifacts.py +39 -0
  431. ksadk/skills/runtime/backends/__init__.py +1 -0
  432. ksadk/skills/runtime/backends/disabled.py +8 -0
  433. ksadk/skills/runtime/backends/e2b.py +168 -0
  434. ksadk/skills/runtime/backends/local.py +95 -0
  435. ksadk/skills/runtime/base.py +103 -0
  436. ksadk/skills/runtime/executor.py +219 -0
  437. ksadk/skills/runtime/factory.py +37 -0
  438. ksadk/skills/runtime/loader.py +131 -0
  439. ksadk/skills/runtime/registry.py +150 -0
  440. ksadk/skills/runtime/request.py +67 -0
  441. ksadk/skills/service_client.py +239 -0
  442. ksadk/skills/service_env.py +58 -0
  443. ksadk/skills/tool_defs.py +221 -0
  444. ksadk/terminal_client.py +69 -0
  445. ksadk/terminal_exec_policy.py +229 -0
  446. ksadk/tools/__init__.py +17 -0
  447. ksadk/tools/gateway.py +230 -0
  448. ksadk/tools/result_budget.py +154 -0
  449. ksadk/toolsets/__init__.py +854 -0
  450. ksadk/toolsets/_langchain.py +11 -0
  451. ksadk/toolsets/platform.py +93 -0
  452. ksadk/toolsets/sandbox.py +310 -0
  453. ksadk/toolsets/skills.py +217 -0
  454. ksadk/toolsets/web.py +266 -0
  455. ksadk/toolsets/workspace.py +917 -0
  456. ksadk/toolsets/workspace_state.py +44 -0
  457. ksadk/tracing/__init__.py +37 -0
  458. ksadk/tracing/exporters/__init__.py +1 -0
  459. ksadk/tracing/exporters/inmemory_exporter.py +116 -0
  460. ksadk/tracing/exporters/langfuse_exporter.py +445 -0
  461. ksadk/tracing/setup.py +892 -0
  462. ksadk/tracing/span_utils.py +114 -0
  463. ksadk/tui/__init__.py +27 -0
  464. ksadk/tui/loop.py +1877 -0
  465. ksadk/tui/stream_render.py +68 -0
  466. ksadk/ui_config.py +168 -0
  467. ksadk/version.py +4 -0
  468. ksadk_runtime_common/__init__.py +20 -0
  469. ksadk_runtime_common/memory_backend/__init__.py +29 -0
  470. ksadk_runtime_common/memory_backend/manifest.py +79 -0
  471. ksadk_runtime_common/memory_backend/providers/__init__.py +6 -0
  472. ksadk_runtime_common/memory_backend/providers/lancedb.py +151 -0
  473. ksadk_runtime_common/memory_backend/providers/mem0.py +74 -0
  474. ksadk_runtime_common/memory_backend/registry.py +56 -0
  475. ksadk_runtime_common/memory_backend/render.py +71 -0
  476. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -0
  477. ksadk_runtime_common/workspace_files/__init__.py +29 -0
  478. ksadk_runtime_common/workspace_files/bootstrap.py +56 -0
  479. ksadk_runtime_common/workspace_files/constants.py +9 -0
  480. ksadk_runtime_common/workspace_files/path_utils.py +71 -0
  481. ksadk_runtime_common/workspace_files/preview.py +96 -0
  482. ksadk_runtime_common/workspace_files/router.py +254 -0
  483. agentengine_sdk_python/__init__.py +0 -3
  484. agentengine_sdk_python-0.6.4.dist-info/METADATA +0 -48
  485. agentengine_sdk_python-0.6.4.dist-info/RECORD +0 -5
  486. agentengine_sdk_python-0.6.4.dist-info/top_level.txt +0 -1
@@ -0,0 +1,154 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import time
5
+ from typing import Any
6
+
7
+ from ksadk.sandbox.base import (
8
+ SandboxCommandResult,
9
+ SandboxError,
10
+ SandboxInputFile,
11
+ SandboxSession,
12
+ SandboxSpec,
13
+ )
14
+
15
+ _TRANSIENT_STARTUP_ERROR_NAMES = {
16
+ "NotFoundException",
17
+ "FileNotFoundException",
18
+ "SandboxNotFoundException",
19
+ }
20
+
21
+
22
+ def _startup_retry_attempts() -> int:
23
+ raw = os.environ.get("KSADK_SANDBOX_STARTUP_RETRY_ATTEMPTS", "6")
24
+ try:
25
+ return max(1, int(raw))
26
+ except ValueError:
27
+ return 6
28
+
29
+
30
+ def _startup_retry_delay() -> float:
31
+ raw = os.environ.get("KSADK_SANDBOX_STARTUP_RETRY_DELAY", "0.2")
32
+ try:
33
+ return max(0.0, float(raw))
34
+ except ValueError:
35
+ return 0.2
36
+
37
+
38
+ def _is_transient_startup_error(exc: Exception) -> bool:
39
+ return type(exc).__name__ in _TRANSIENT_STARTUP_ERROR_NAMES
40
+
41
+
42
+ def _with_startup_retry(operation):
43
+ attempts = _startup_retry_attempts()
44
+ delay = _startup_retry_delay()
45
+ last_exc: Exception | None = None
46
+ for attempt in range(attempts):
47
+ try:
48
+ return operation()
49
+ except Exception as exc:
50
+ if not _is_transient_startup_error(exc) or attempt >= attempts - 1:
51
+ raise
52
+ last_exc = exc
53
+ time.sleep(min(delay * (2**attempt), 1.0))
54
+ if last_exc is not None:
55
+ raise last_exc
56
+ raise SandboxError("E2B sandbox startup retry failed unexpectedly")
57
+
58
+
59
+ class E2BSandboxSession:
60
+ def __init__(self, sandbox: Any):
61
+ self._sandbox = sandbox
62
+
63
+ @property
64
+ def sandbox_id(self) -> str:
65
+ return str(getattr(self._sandbox, "sandbox_id", "") or "")
66
+
67
+ def write_file(self, path: str, data: str | bytes) -> None:
68
+ self._sandbox.files.write(path, data)
69
+
70
+ def read_file(self, path: str) -> str:
71
+ return str(self._sandbox.files.read(path))
72
+
73
+ def run_command(
74
+ self,
75
+ command: str,
76
+ *,
77
+ timeout: int | None = None,
78
+ env: dict[str, str] | None = None,
79
+ cwd: str | None = None,
80
+ ) -> SandboxCommandResult:
81
+ kwargs = {}
82
+ if timeout is not None:
83
+ kwargs["timeout"] = timeout
84
+ if env is not None:
85
+ kwargs["envs"] = env
86
+ if cwd is not None:
87
+ kwargs["cwd"] = cwd
88
+ result = self._sandbox.commands.run(command, **kwargs)
89
+ return SandboxCommandResult(
90
+ stdout=str(getattr(result, "stdout", "") or ""),
91
+ stderr=str(getattr(result, "stderr", "") or ""),
92
+ exit_code=getattr(result, "exit_code", None),
93
+ )
94
+
95
+ def get_host(self, port: int) -> str:
96
+ return str(self._sandbox.get_host(port))
97
+
98
+ def kill(self) -> None:
99
+ self._sandbox.kill()
100
+
101
+
102
+ class E2BSandboxBackend:
103
+ def __init__(
104
+ self,
105
+ *,
106
+ spec: SandboxSpec,
107
+ sandbox_cls: Any | None = None,
108
+ ):
109
+ if not spec.template_id:
110
+ raise SandboxError("E2B sandbox backend requires a template id")
111
+ self.spec = spec
112
+ self.sandbox_cls = sandbox_cls
113
+
114
+ def create_session(
115
+ self,
116
+ *,
117
+ session_id: str,
118
+ env: dict[str, str] | None = None,
119
+ input_files: list[SandboxInputFile] | None = None,
120
+ ) -> SandboxSession:
121
+ sandbox_cls = self.sandbox_cls
122
+ if sandbox_cls is None:
123
+ try:
124
+ from e2b import Sandbox
125
+ except ImportError as exc:
126
+ raise SandboxError("e2b>=2.0.0 is required for KSADK_SANDBOX_BACKEND=e2b") from exc
127
+ sandbox_cls = Sandbox
128
+
129
+ metadata = {
130
+ "runtime": "ksadk",
131
+ "sandbox_type": self.spec.sandbox_type.value,
132
+ **self.spec.metadata,
133
+ "session_id": session_id,
134
+ }
135
+ runtime_env = {**self.spec.env, **(env or {})}
136
+ sandbox = sandbox_cls.create(
137
+ template=self.spec.template_id,
138
+ timeout=self.spec.timeout,
139
+ metadata=metadata,
140
+ envs=runtime_env,
141
+ allow_internet_access=self.spec.allow_internet_access,
142
+ )
143
+ session = self._wrap_sandbox(sandbox)
144
+ self._wait_until_ready(session)
145
+ for item in input_files or []:
146
+ session.write_file(item.target_path, item.source.read_bytes())
147
+ return session
148
+
149
+ def _wrap_sandbox(self, sandbox: Any) -> E2BSandboxSession:
150
+ return E2BSandboxSession(sandbox)
151
+
152
+ def _wait_until_ready(self, session: E2BSandboxSession) -> None:
153
+ _with_startup_retry(lambda: session.run_command("true"))
154
+ _with_startup_retry(lambda: session.write_file("/tmp/.ksadk-sandbox-ready", ""))
@@ -0,0 +1,131 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import signal
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ from ksadk.sandbox.base import SandboxCommandResult, SandboxInputFile, SandboxSession
9
+
10
+
11
+ class LocalProcessSandboxSession:
12
+ def __init__(self, *, session_id: str, workspace_root: Path, backend_name: str = "local_process"):
13
+ self._session_id = session_id
14
+ self._workspace_root = workspace_root.expanduser().resolve()
15
+ self._workspace_root.mkdir(parents=True, exist_ok=True)
16
+ self._backend_name = backend_name
17
+
18
+ @property
19
+ def sandbox_id(self) -> str:
20
+ return f"{self._backend_name}:{self._session_id}"
21
+
22
+ def write_file(self, path: str, data: str | bytes) -> None:
23
+ target = self._resolve_workspace_path(path)
24
+ target.parent.mkdir(parents=True, exist_ok=True)
25
+ if isinstance(data, bytes):
26
+ target.write_bytes(data)
27
+ else:
28
+ target.write_text(data, encoding="utf-8")
29
+
30
+ def read_file(self, path: str) -> str:
31
+ return self._resolve_workspace_path(path).read_text(encoding="utf-8")
32
+
33
+ def run_command(
34
+ self,
35
+ command: str,
36
+ *,
37
+ timeout: int | None = None,
38
+ env: dict[str, str] | None = None,
39
+ cwd: str | None = None,
40
+ ) -> SandboxCommandResult:
41
+ try:
42
+ resolved_cwd = self._resolve_cwd(cwd or (env or {}).get("KSADK_COMMAND_CWD"))
43
+ except ValueError as exc:
44
+ return SandboxCommandResult(stderr=str(exc), exit_code=126)
45
+ process_env = self._allowed_env(env or {})
46
+ try:
47
+ process = subprocess.Popen(
48
+ command,
49
+ shell=True,
50
+ cwd=resolved_cwd,
51
+ env=process_env,
52
+ text=True,
53
+ stdout=subprocess.PIPE,
54
+ stderr=subprocess.PIPE,
55
+ start_new_session=True,
56
+ )
57
+ stdout, stderr = process.communicate(timeout=timeout)
58
+ return SandboxCommandResult(
59
+ stdout=stdout,
60
+ stderr=stderr,
61
+ exit_code=process.returncode,
62
+ )
63
+ except subprocess.TimeoutExpired as exc:
64
+ try:
65
+ os.killpg(process.pid, signal.SIGKILL)
66
+ except Exception:
67
+ pass
68
+ stdout, stderr = process.communicate()
69
+ return SandboxCommandResult(
70
+ stdout=stdout or exc.stdout or "",
71
+ stderr=(stderr or exc.stderr or "") + "\ncommand timed out",
72
+ exit_code=124,
73
+ )
74
+
75
+ def get_host(self, port: int) -> str:
76
+ return f"http://127.0.0.1:{int(port)}"
77
+
78
+ def kill(self) -> None:
79
+ return None
80
+
81
+ def _resolve_cwd(self, cwd: str | None) -> Path:
82
+ if not cwd:
83
+ return self._workspace_root
84
+ candidate = Path(cwd)
85
+ if not candidate.is_absolute():
86
+ candidate = self._workspace_root / candidate
87
+ resolved = candidate.expanduser().resolve()
88
+ if resolved != self._workspace_root and self._workspace_root not in resolved.parents:
89
+ raise ValueError("cwd must stay inside the sandbox workspace")
90
+ return resolved
91
+
92
+ def _resolve_workspace_path(self, path: str) -> Path:
93
+ raw = str(path or "").strip().lstrip("/") or "."
94
+ target = (self._workspace_root / raw).resolve()
95
+ if target != self._workspace_root and self._workspace_root not in target.parents:
96
+ raise ValueError("path must stay inside the sandbox workspace")
97
+ return target
98
+
99
+ @staticmethod
100
+ def _allowed_env(env: dict[str, str]) -> dict[str, str]:
101
+ allowed = {"PATH": os.environ.get("PATH", ""), "HOME": os.environ.get("HOME", "")}
102
+ for key, value in env.items():
103
+ if key.startswith("KSADK_COMMAND_"):
104
+ continue
105
+ if key.startswith(("KSADK_SAFE_", "PYTHON", "NODE", "UV_")):
106
+ allowed[key] = str(value)
107
+ return allowed
108
+
109
+
110
+ class LocalProcessSandboxBackend:
111
+ isolated = False
112
+
113
+ def __init__(self, *, workspace_root: Path, backend_name: str = "local_process"):
114
+ self.workspace_root = workspace_root
115
+ self.backend_name = backend_name
116
+
117
+ def create_session(
118
+ self,
119
+ *,
120
+ session_id: str,
121
+ env: dict[str, str] | None = None,
122
+ input_files: list[SandboxInputFile] | None = None,
123
+ ) -> SandboxSession:
124
+ session = LocalProcessSandboxSession(
125
+ session_id=session_id,
126
+ workspace_root=self.workspace_root,
127
+ backend_name=self.backend_name,
128
+ )
129
+ for item in input_files or []:
130
+ session.write_file(item.target_path, item.source.read_bytes())
131
+ return session
ksadk/sandbox/base.py ADDED
@@ -0,0 +1,101 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from enum import Enum
5
+ from pathlib import Path
6
+ from typing import Protocol
7
+
8
+
9
+ class SandboxError(RuntimeError):
10
+ pass
11
+
12
+
13
+ class SandboxType(str, Enum):
14
+ AIO = "aio"
15
+ CODE = "code"
16
+ BROWSER = "browser"
17
+ PRIVATE = "private"
18
+
19
+ @classmethod
20
+ def from_value(cls, value: str | "SandboxType" | None) -> "SandboxType":
21
+ if isinstance(value, SandboxType):
22
+ return value
23
+ normalized = (value or "").strip().lower().replace("_", "").replace("-", "").replace(" ", "")
24
+ aliases = {
25
+ "": cls.AIO,
26
+ "aio": cls.AIO,
27
+ "allinone": cls.AIO,
28
+ "code": cls.CODE,
29
+ "codeinterpreter": cls.CODE,
30
+ "codesandbox": cls.CODE,
31
+ "browser": cls.BROWSER,
32
+ "browsersandbox": cls.BROWSER,
33
+ "private": cls.PRIVATE,
34
+ "custom": cls.PRIVATE,
35
+ }
36
+ try:
37
+ return aliases[normalized]
38
+ except KeyError as exc:
39
+ raise SandboxError(f"Unsupported sandbox type: {value}") from exc
40
+
41
+
42
+ @dataclass(frozen=True)
43
+ class SandboxInputFile:
44
+ source: Path
45
+ target_path: str
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class SandboxCommandResult:
50
+ stdout: str = ""
51
+ stderr: str = ""
52
+ exit_code: int | None = None
53
+
54
+
55
+ @dataclass(frozen=True)
56
+ class SandboxSpec:
57
+ template_id: str
58
+ sandbox_type: SandboxType = SandboxType.AIO
59
+ timeout: int = 900
60
+ allow_internet_access: bool = True
61
+ metadata: dict[str, str] = field(default_factory=dict)
62
+ env: dict[str, str] = field(default_factory=dict)
63
+
64
+
65
+ class SandboxSession(Protocol):
66
+ @property
67
+ def sandbox_id(self) -> str:
68
+ ...
69
+
70
+ def write_file(self, path: str, data: str | bytes) -> None:
71
+ ...
72
+
73
+ def read_file(self, path: str) -> str:
74
+ ...
75
+
76
+ def run_command(
77
+ self,
78
+ command: str,
79
+ *,
80
+ timeout: int | None = None,
81
+ env: dict[str, str] | None = None,
82
+ cwd: str | None = None,
83
+ ) -> SandboxCommandResult:
84
+ ...
85
+
86
+ def get_host(self, port: int) -> str:
87
+ ...
88
+
89
+ def kill(self) -> None:
90
+ ...
91
+
92
+
93
+ class SandboxBackend(Protocol):
94
+ def create_session(
95
+ self,
96
+ *,
97
+ session_id: str,
98
+ env: dict[str, str] | None = None,
99
+ input_files: list[SandboxInputFile] | None = None,
100
+ ) -> SandboxSession:
101
+ ...
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from typing import Any
5
+
6
+ from ksadk.sandbox.backends.e2b import E2BSandboxBackend
7
+ from ksadk.sandbox.backends.local_process import LocalProcessSandboxBackend
8
+ from ksadk.sandbox.base import SandboxBackend, SandboxError, SandboxSpec, SandboxType
9
+ from ksadk.sessions.local_service import resolve_local_session_dir
10
+
11
+
12
+ def bool_env(name: str, default: bool = True) -> bool:
13
+ raw = os.environ.get(name)
14
+ if raw is None:
15
+ return default
16
+ return raw.strip().lower() in {"1", "true", "yes", "on"}
17
+
18
+
19
+ def create_sandbox_backend(
20
+ backend: str | None = None,
21
+ *,
22
+ sandbox_cls: Any | None = None,
23
+ ) -> SandboxBackend:
24
+ resolved = (backend or os.environ.get("KSADK_SANDBOX_BACKEND") or "e2b").strip().lower()
25
+ if resolved in {"local", "local_process"}:
26
+ return LocalProcessSandboxBackend(workspace_root=resolve_local_session_dir() / "workspace", backend_name="local_process")
27
+ if resolved in {"pod", "pod_process"}:
28
+ if not bool_env("KSADK_ALLOW_POD_PROCESS_TOOLS", False):
29
+ raise SandboxError("KSADK_ALLOW_POD_PROCESS_TOOLS=true is required for pod_process backend")
30
+ return LocalProcessSandboxBackend(workspace_root=resolve_local_session_dir() / "workspace", backend_name="pod_process")
31
+ if resolved != "e2b":
32
+ raise SandboxError(f"Unsupported sandbox backend: {resolved}")
33
+ return E2BSandboxBackend(spec=sandbox_spec_from_env(), sandbox_cls=sandbox_cls)
34
+
35
+
36
+ def sandbox_spec_from_env() -> SandboxSpec:
37
+ template_id = (
38
+ os.environ.get("KSADK_SANDBOX_TEMPLATE_ID")
39
+ or os.environ.get("KSADK_SKILL_RUNTIME_TEMPLATE_ID")
40
+ or ""
41
+ )
42
+ timeout = int(os.environ.get("KSADK_SANDBOX_TIMEOUT") or os.environ.get("KSADK_SKILL_RUNTIME_TIMEOUT") or "900")
43
+ allow_internet_access = bool_env(
44
+ "KSADK_SANDBOX_ALLOW_INTERNET_ACCESS",
45
+ bool_env("KSADK_SKILL_RUNTIME_ALLOW_INTERNET_ACCESS", True),
46
+ )
47
+ sandbox_type = SandboxType.from_value(os.environ.get("KSADK_SANDBOX_TYPE", "aio"))
48
+ return SandboxSpec(
49
+ template_id=template_id,
50
+ sandbox_type=sandbox_type,
51
+ timeout=timeout,
52
+ allow_internet_access=allow_internet_access,
53
+ )
@@ -0,0 +1,187 @@
1
+ from __future__ import annotations
2
+
3
+ import atexit
4
+ import logging
5
+ import os
6
+ import threading
7
+ import time
8
+ from dataclasses import dataclass
9
+
10
+ from ksadk.sandbox.base import SandboxBackend, SandboxSession
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # 后台 sweep 默认间隔(秒)。0 表示禁用后台 sweep,仅靠 get_or_create 时的惰性 sweep。
15
+ _DEFAULT_SWEEP_INTERVAL_SECONDS = 60
16
+
17
+
18
+ @dataclass
19
+ class SandboxRegistryEntry:
20
+ key: str
21
+ backend: str
22
+ session: SandboxSession
23
+ created_at: float
24
+ last_used_at: float
25
+ expires_at: float
26
+ isolated: bool
27
+
28
+ @property
29
+ def sandbox_id(self) -> str:
30
+ return self.session.sandbox_id
31
+
32
+
33
+ class SandboxRegistry:
34
+ def __init__(self):
35
+ self._entries: dict[str, SandboxRegistryEntry] = {}
36
+ # RLock 可重入:get_or_create 内部会调 sweep/kill/_enforce_quota。
37
+ self._lock = threading.RLock()
38
+ # idle_ttl 由 toolset 层在 get_or_create 时传入,后台 sweep 复用该值。
39
+ self._idle_ttl_seconds: int = 0
40
+ self._sweep_thread: threading.Thread | None = None
41
+ self._sweep_stop = threading.Event()
42
+ self._sweep_interval = self._resolve_sweep_interval()
43
+
44
+ @staticmethod
45
+ def _resolve_sweep_interval() -> int:
46
+ raw = os.environ.get("KSADK_SANDBOX_SWEEP_INTERVAL_SECONDS", str(_DEFAULT_SWEEP_INTERVAL_SECONDS))
47
+ try:
48
+ value = int(raw)
49
+ except (TypeError, ValueError):
50
+ return _DEFAULT_SWEEP_INTERVAL_SECONDS
51
+ return value if value > 0 else 0
52
+
53
+ def get_or_create(
54
+ self,
55
+ *,
56
+ key: str,
57
+ backend_name: str,
58
+ backend: SandboxBackend,
59
+ ttl_seconds: int,
60
+ isolated: bool,
61
+ idle_ttl_seconds: int | None = None,
62
+ max_sessions: int | None = None,
63
+ input_files: list | None = None,
64
+ now: float | None = None,
65
+ ) -> tuple[SandboxRegistryEntry, bool]:
66
+ current = time.time() if now is None else now
67
+ if idle_ttl_seconds is not None:
68
+ self._idle_ttl_seconds = int(idle_ttl_seconds or 0)
69
+ with self._lock:
70
+ self.sweep(now=current, idle_ttl_seconds=self._idle_ttl_seconds)
71
+ entry = self._entries.get(key)
72
+ if entry is not None and entry.expires_at > current:
73
+ entry.last_used_at = current
74
+ return entry, False
75
+ if entry is not None:
76
+ self.kill(key)
77
+ self._enforce_quota(max_sessions=max_sessions, keep_key=key)
78
+ session = backend.create_session(session_id=key, input_files=input_files or None)
79
+ entry = SandboxRegistryEntry(
80
+ key=key,
81
+ backend=backend_name,
82
+ session=session,
83
+ created_at=current,
84
+ last_used_at=current,
85
+ expires_at=current + max(1, int(ttl_seconds or 900)),
86
+ isolated=isolated,
87
+ )
88
+ self._entries[key] = entry
89
+ # 锁外启动后台线程,避免持锁创建线程。
90
+ self._start_sweep_thread()
91
+ return entry, True
92
+
93
+ def latest(self) -> SandboxRegistryEntry | None:
94
+ with self._lock:
95
+ if not self._entries:
96
+ return None
97
+ return max(self._entries.values(), key=lambda item: item.last_used_at)
98
+
99
+ def sweep(self, *, now: float | None = None, idle_ttl_seconds: int | None = None) -> int:
100
+ current = time.time() if now is None else now
101
+ idle_ttl = int(idle_ttl_seconds or 0)
102
+ with self._lock:
103
+ expired = [
104
+ key
105
+ for key, entry in self._entries.items()
106
+ if entry.expires_at <= current or (idle_ttl > 0 and current - entry.last_used_at > idle_ttl)
107
+ ]
108
+ for key in expired:
109
+ self.kill(key)
110
+ return len(expired)
111
+
112
+ def entries(self) -> list[SandboxRegistryEntry]:
113
+ with self._lock:
114
+ return list(self._entries.values())
115
+
116
+ def kill(self, key: str) -> bool:
117
+ with self._lock:
118
+ entry = self._entries.pop(key, None)
119
+ if entry is None:
120
+ return False
121
+ # session.kill() 是 E2B 网络 IO,放锁外避免持锁阻塞并发 get_or_create。
122
+ try:
123
+ entry.session.kill()
124
+ except Exception:
125
+ logger.exception("sandbox session kill failed for key=%s", key)
126
+ return True
127
+
128
+ def clear(self) -> None:
129
+ with self._lock:
130
+ keys = list(self._entries)
131
+ for key in keys:
132
+ self.kill(key)
133
+
134
+ def _enforce_quota(self, *, max_sessions: int | None, keep_key: str) -> None:
135
+ if not max_sessions or max_sessions < 1:
136
+ return
137
+ to_kill: list[str] = []
138
+ with self._lock:
139
+ while len(self._entries) - len(to_kill) >= max_sessions:
140
+ candidates = [
141
+ entry for entry in self._entries.values()
142
+ if entry.key != keep_key and entry.key not in to_kill
143
+ ]
144
+ if not candidates:
145
+ break
146
+ oldest = min(candidates, key=lambda item: item.last_used_at)
147
+ to_kill.append(oldest.key)
148
+ for key in to_kill:
149
+ self.kill(key)
150
+
151
+ def _start_sweep_thread(self) -> None:
152
+ if self._sweep_interval <= 0:
153
+ return
154
+ with self._lock:
155
+ if self._sweep_thread is not None and self._sweep_thread.is_alive():
156
+ return
157
+ self._sweep_stop.clear()
158
+ self._sweep_thread = threading.Thread(
159
+ target=self._sweep_loop,
160
+ name="ksadk-sandbox-sweep",
161
+ daemon=True,
162
+ )
163
+ self._sweep_thread.start()
164
+
165
+ def _sweep_loop(self) -> None:
166
+ while not self._sweep_stop.wait(timeout=self._sweep_interval):
167
+ try:
168
+ self.sweep(idle_ttl_seconds=self._idle_ttl_seconds)
169
+ except Exception:
170
+ logger.exception("sandbox background sweep failed")
171
+
172
+ def reset_for_tests(self) -> None:
173
+ """停后台 sweep 线程并清空所有 entry,用于测试隔离。"""
174
+ self._sweep_stop.set()
175
+ thread = self._sweep_thread
176
+ if thread is not None and thread.is_alive():
177
+ thread.join(timeout=2.0)
178
+ self._sweep_thread = None
179
+ self.clear()
180
+ self._idle_ttl_seconds = 0
181
+ self._sweep_stop.clear()
182
+
183
+
184
+ GLOBAL_SANDBOX_REGISTRY = SandboxRegistry()
185
+ # 进程退出时清理 sandbox,避免 E2B sandbox 活到服务端 timeout 才销毁(按秒计费)。
186
+ # clear() 幂等,与 server lifespan shutdown 重复调用安全。kill -9 不触发 atexit,只能靠 E2B 兜底。
187
+ atexit.register(GLOBAL_SANDBOX_REGISTRY.clear)
@@ -0,0 +1,7 @@
1
+ """
2
+ KsADK Server - FastAPI 服务模块
3
+ """
4
+
5
+ from ksadk.server.app import app, set_runner
6
+
7
+ __all__ = ["app", "set_runner"]