agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.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 (371) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
  2. agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
  3. ksadk/a2a/__init__.py +178 -11
  4. ksadk/a2a/bootstrap.py +334 -0
  5. ksadk/a2a/card.py +120 -0
  6. ksadk/a2a/context_store.py +203 -0
  7. ksadk/a2a/control_plane.py +818 -0
  8. ksadk/a2a/credential.py +99 -0
  9. ksadk/a2a/event_adapter.py +149 -0
  10. ksadk/a2a/executor.py +406 -89
  11. ksadk/a2a/external_transport.py +516 -0
  12. ksadk/a2a/identity.py +304 -0
  13. ksadk/a2a/ids.py +22 -0
  14. ksadk/a2a/langgraph.py +285 -0
  15. ksadk/a2a/resume_store.py +201 -0
  16. ksadk/a2a/routes.py +105 -0
  17. ksadk/a2a/server.py +107 -60
  18. ksadk/a2a/space_client.py +1101 -0
  19. ksadk/a2a/task_adapter.py +423 -0
  20. ksadk/a2a/task_event_dispatcher.py +167 -0
  21. ksadk/a2a/task_event_outbox.py +326 -0
  22. ksadk/a2a/task_store.py +206 -0
  23. ksadk/a2ui/__init__.py +27 -0
  24. ksadk/a2ui/core.py +186 -0
  25. ksadk/a2ui/models.py +166 -0
  26. ksadk/a2ui/renderer.py +198 -0
  27. ksadk/agui/__init__.py +9 -0
  28. ksadk/agui/a2ui_projection.py +92 -0
  29. ksadk/agui/agent.py +857 -0
  30. ksadk/agui/config.py +86 -0
  31. ksadk/agui/routes.py +55 -0
  32. ksadk/api/client.py +233 -191
  33. ksadk/builders/__init__.py +2 -0
  34. ksadk/builders/base.py +16 -14
  35. ksadk/builders/code_builder.py +318 -236
  36. ksadk/builders/container_builder.py +187 -167
  37. ksadk/builders/framework_requirements.py +29 -11
  38. ksadk/builders/ks3_uploader.py +58 -27
  39. ksadk/builders/managed_runtime_builder.py +145 -0
  40. ksadk/builders/mcp_builder.py +91 -92
  41. ksadk/builders/requirements_utils.py +1 -5
  42. ksadk/cli/__init__.py +89 -171
  43. ksadk/cli/cmd_a2a.py +254 -70
  44. ksadk/cli/cmd_agent.py +19 -5
  45. ksadk/cli/cmd_build.py +158 -29
  46. ksadk/cli/cmd_completion.py +47 -35
  47. ksadk/cli/cmd_config.py +267 -198
  48. ksadk/cli/cmd_create.py +500 -720
  49. ksadk/cli/cmd_dashboard.py +120 -45
  50. ksadk/cli/cmd_deploy.py +117 -58
  51. ksadk/cli/cmd_destroy.py +44 -14
  52. ksadk/cli/cmd_files.py +63 -24
  53. ksadk/cli/cmd_hermes.py +168 -89
  54. ksadk/cli/cmd_invoke.py +184 -122
  55. ksadk/cli/cmd_launch.py +64 -28
  56. ksadk/cli/cmd_mcp.py +98 -64
  57. ksadk/cli/cmd_model.py +14 -5
  58. ksadk/cli/cmd_openclaw.py +483 -227
  59. ksadk/cli/cmd_replay.py +71 -0
  60. ksadk/cli/cmd_run.py +33 -10
  61. ksadk/cli/cmd_status.py +80 -31
  62. ksadk/cli/cmd_version.py +20 -13
  63. ksadk/cli/cmd_web.py +89 -13
  64. ksadk/cli/deploy_utils.py +20 -20
  65. ksadk/cli/dry_run.py +5 -3
  66. ksadk/cli/error_utils.py +37 -12
  67. ksadk/cli/global_options.py +1 -2
  68. ksadk/cli/local_runtime.py +1 -2
  69. ksadk/cli/model_catalog.py +6 -2
  70. ksadk/cli/network_options.py +34 -14
  71. ksadk/cli/resource_common.py +6 -2
  72. ksadk/cli/storage.py +0 -1
  73. ksadk/cli/ui.py +5 -3
  74. ksadk/cli/workflow_common.py +51 -17
  75. ksadk/codex/__init__.py +12 -0
  76. ksadk/codex/client.py +408 -0
  77. ksadk/codex/phase.py +143 -0
  78. ksadk/codex/runtime.py +449 -0
  79. ksadk/common/aicp_env.py +0 -1
  80. ksadk/common/auth.py +2 -2
  81. ksadk/common/constants.py +1 -3
  82. ksadk/common/llm_utils.py +17 -13
  83. ksadk/compat/__init__.py +5 -0
  84. ksadk/compat/adk_compat.py +200 -0
  85. ksadk/compat/copilotkit_a2ui.py +330 -0
  86. ksadk/configs/__init__.py +12 -12
  87. ksadk/configs/env_registry.py +500 -100
  88. ksadk/configs/global_config.py +2 -1
  89. ksadk/configs/settings.py +151 -124
  90. ksadk/conversations/__init__.py +7 -5
  91. ksadk/conversations/attachment_storage.py +16 -11
  92. ksadk/conversations/attachments.py +44 -36
  93. ksadk/conversations/compaction_pipeline.py +12 -12
  94. ksadk/conversations/compaction_prompt.py +9 -5
  95. ksadk/conversations/context.py +221 -6
  96. ksadk/conversations/message_projection.py +438 -51
  97. ksadk/conversations/model_context.py +12 -6
  98. ksadk/conversations/model_options.py +0 -1
  99. ksadk/conversations/normalize.py +20 -16
  100. ksadk/conversations/reasoning_markup.py +1 -1
  101. ksadk/conversations/runtime.py +339 -5255
  102. ksadk/conversations/runtime_compaction.py +333 -0
  103. ksadk/conversations/runtime_constants.py +27 -0
  104. ksadk/conversations/runtime_governance.py +185 -0
  105. ksadk/conversations/runtime_input.py +652 -0
  106. ksadk/conversations/runtime_invocation.py +395 -0
  107. ksadk/conversations/runtime_metadata.py +475 -0
  108. ksadk/conversations/runtime_observability.py +355 -0
  109. ksadk/conversations/runtime_payloads.py +272 -0
  110. ksadk/conversations/runtime_persistence.py +440 -0
  111. ksadk/conversations/runtime_preparation.py +418 -0
  112. ksadk/conversations/runtime_resume.py +816 -0
  113. ksadk/conversations/runtime_stream_events.py +902 -0
  114. ksadk/conversations/runtime_streaming.py +547 -0
  115. ksadk/conversations/semantic_summary.py +17 -5
  116. ksadk/conversations/session_title.py +6 -3
  117. ksadk/deployment/__init__.py +15 -16
  118. ksadk/deployment/agent_access.py +12 -23
  119. ksadk/deployment/base.py +51 -38
  120. ksadk/deployment/manager.py +63 -65
  121. ksadk/deployment/providers/serverless.py +309 -202
  122. ksadk/deployment/registry.py +38 -32
  123. ksadk/deployment/state.py +11 -11
  124. ksadk/deployment/ui_config.py +1 -1
  125. ksadk/detection/__init__.py +1 -1
  126. ksadk/detection/detector.py +146 -83
  127. ksadk/detection/mcp_detector.py +9 -6
  128. ksadk/events/__init__.py +25 -0
  129. ksadk/events/parser.py +191 -0
  130. ksadk/events/replay.py +37 -0
  131. ksadk/events/runtime_event.py +264 -0
  132. ksadk/events/store.py +317 -0
  133. ksadk/harness/__init__.py +34 -0
  134. ksadk/harness/app.py +278 -0
  135. ksadk/harness/config.py +181 -0
  136. ksadk/harness/reasoner.py +105 -0
  137. ksadk/harness/runner.py +211 -0
  138. ksadk/harness/sandbox.py +141 -0
  139. ksadk/harness/tools.py +222 -0
  140. ksadk/hermes_terminal.py +23 -12
  141. ksadk/identity/resolver.py +15 -9
  142. ksadk/ids.py +32 -0
  143. ksadk/knowledge_base/adk_tool.py +1 -1
  144. ksadk/knowledge_base/client.py +23 -29
  145. ksadk/managed_runtime.py +188 -0
  146. ksadk/markdown.py +5 -2
  147. ksadk/mcp_runtime/__init__.py +9 -6
  148. ksadk/memory/__init__.py +1 -1
  149. ksadk/memory/adk/__init__.py +2 -0
  150. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  151. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  152. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  153. ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
  154. ksadk/memory/adk/long_term_memory.py +31 -35
  155. ksadk/memory/adk/resilient_session_service.py +4 -5
  156. ksadk/memory/adk/short_term_memory.py +12 -21
  157. ksadk/memory/adk_tool.py +3 -2
  158. ksadk/memory/backends/base.py +19 -19
  159. ksadk/memory/backends/memory.py +24 -25
  160. ksadk/memory/backends/redis.py +31 -30
  161. ksadk/memory/langchain_tool.py +2 -1
  162. ksadk/memory/manager.py +52 -47
  163. ksadk/memory/service.py +10 -8
  164. ksadk/model_policy.py +15 -7
  165. ksadk/model_proxy/__init__.py +51 -0
  166. ksadk/model_proxy/bootstrap.py +80 -0
  167. ksadk/model_proxy/cache.py +165 -0
  168. ksadk/model_proxy/config.py +45 -0
  169. ksadk/model_proxy/demo_webui.py +115 -0
  170. ksadk/model_proxy/detect.py +145 -0
  171. ksadk/model_proxy/gate.py +68 -0
  172. ksadk/model_proxy/namespace.py +173 -0
  173. ksadk/model_proxy/protocol_proxy.py +22 -0
  174. ksadk/model_proxy/server.py +300 -0
  175. ksadk/model_proxy/transform.py +691 -0
  176. ksadk/openclaw_gateway.py +29 -14
  177. ksadk/runners/adk_runner.py +345 -120
  178. ksadk/runners/base_runner.py +46 -29
  179. ksadk/runners/codex_runner.py +132 -0
  180. ksadk/runners/deepagents_runner.py +0 -1
  181. ksadk/runners/factory.py +17 -5
  182. ksadk/runners/langchain_runner.py +29 -742
  183. ksadk/runners/langgraph_runner.py +352 -90
  184. ksadk/runners/patch_langchain.py +16 -16
  185. ksadk/runners/remote_runner.py +134 -33
  186. ksadk/runners/usage_accumulator.py +1 -0
  187. ksadk/runners/utils/langfuse.py +3 -3
  188. ksadk/runners/utils/loader.py +7 -7
  189. ksadk/runtime/__init__.py +41 -0
  190. ksadk/runtime/adapter.py +345 -0
  191. ksadk/runtime/framework_adapters.py +124 -0
  192. ksadk/runtime/preprocessing.py +118 -0
  193. ksadk/runtime/runner_adapter.py +873 -0
  194. ksadk/runtime_context.py +18 -3
  195. ksadk/runtime_state.py +0 -1
  196. ksadk/sandbox/__init__.py +4 -1
  197. ksadk/sandbox/backends/__init__.py +4 -1
  198. ksadk/sandbox/backends/e2b.py +13 -5
  199. ksadk/sandbox/backends/local_process.py +11 -3
  200. ksadk/sandbox/base.py +10 -15
  201. ksadk/sandbox/factory.py +14 -4
  202. ksadk/sandbox/registry.py +57 -6
  203. ksadk/server/api_models.py +15 -5
  204. ksadk/server/app.py +455 -3885
  205. ksadk/server/composition.py +21 -0
  206. ksadk/server/factory.py +624 -0
  207. ksadk/server/routes/__init__.py +1 -0
  208. ksadk/server/routes/checkpoint_resolution.py +116 -0
  209. ksadk/server/routes/common.py +713 -0
  210. ksadk/server/routes/control.py +327 -0
  211. ksadk/server/routes/dependencies.py +98 -0
  212. ksadk/server/routes/misc.py +448 -0
  213. ksadk/server/routes/models.py +443 -0
  214. ksadk/server/routes/openai_compat.py +207 -0
  215. ksadk/server/routes/projection.py +795 -0
  216. ksadk/server/routes/routers.py +52 -0
  217. ksadk/server/routes/run.py +726 -0
  218. ksadk/server/routes/sessions.py +649 -0
  219. ksadk/server/routes/streaming.py +223 -0
  220. ksadk/server/routes/workspace.py +381 -0
  221. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
  222. ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
  223. ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
  224. ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
  225. ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
  226. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
  227. ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
  228. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
  229. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
  230. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
  231. ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
  232. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
  233. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
  234. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
  235. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
  236. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
  237. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
  238. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
  239. ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
  240. ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
  241. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
  242. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
  243. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
  244. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
  245. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
  246. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
  247. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
  248. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
  249. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
  250. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
  251. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
  252. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
  253. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
  254. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
  255. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
  256. ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
  257. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
  258. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
  259. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
  260. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
  261. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
  262. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
  263. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
  264. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
  265. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
  266. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
  267. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
  268. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
  269. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
  270. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
  271. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
  272. ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
  273. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
  274. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
  275. ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
  276. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
  277. ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
  278. ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
  279. ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
  280. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
  281. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
  282. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
  283. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
  284. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
  285. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
  286. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
  287. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
  288. ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
  289. ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
  290. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
  291. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
  292. ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
  293. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
  294. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
  295. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
  296. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
  297. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
  298. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
  299. ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
  300. ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
  301. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
  302. ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
  303. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
  304. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
  305. ksadk/server/static/index.html +2 -2
  306. ksadk/server/terminal_sessions.py +111 -58
  307. ksadk/sessions/__init__.py +69 -19
  308. ksadk/sessions/base.py +31 -11
  309. ksadk/sessions/continuity.py +2 -3
  310. ksadk/sessions/in_memory.py +46 -2
  311. ksadk/sessions/local_service.py +148 -17
  312. ksadk/sessions/postgres_service.py +143 -25
  313. ksadk/sessions/resilient.py +36 -8
  314. ksadk/skills/models.py +17 -5
  315. ksadk/skills/package_store.py +5 -2
  316. ksadk/skills/runtime/agent.py +20 -5
  317. ksadk/skills/runtime/artifacts.py +1 -5
  318. ksadk/skills/runtime/backends/e2b.py +10 -4
  319. ksadk/skills/runtime/backends/local.py +15 -3
  320. ksadk/skills/runtime/base.py +1 -2
  321. ksadk/skills/runtime/executor.py +10 -3
  322. ksadk/skills/runtime/factory.py +4 -2
  323. ksadk/skills/runtime/loader.py +1 -2
  324. ksadk/skills/runtime/registry.py +15 -10
  325. ksadk/skills/runtime/request.py +3 -1
  326. ksadk/skills/service_client.py +38 -17
  327. ksadk/skills/tool_defs.py +15 -10
  328. ksadk/terminal_exec_policy.py +3 -4
  329. ksadk/tools/gateway.py +92 -15
  330. ksadk/tools/result_budget.py +12 -4
  331. ksadk/toolsets/__init__.py +134 -36
  332. ksadk/toolsets/platform.py +21 -5
  333. ksadk/toolsets/sandbox.py +82 -16
  334. ksadk/toolsets/skills.py +200 -39
  335. ksadk/toolsets/web.py +123 -26
  336. ksadk/toolsets/workspace.py +212 -101
  337. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  338. ksadk/tracing/exporters/langfuse_exporter.py +91 -76
  339. ksadk/tracing/setup.py +69 -53
  340. ksadk/tracing/span_utils.py +5 -2
  341. ksadk/tui/loop.py +78 -30
  342. ksadk/tui/stream_render.py +1 -0
  343. ksadk/ui_config.py +5 -3
  344. ksadk/version.py +1 -1
  345. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  346. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  347. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  348. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  349. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  350. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  351. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  352. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  353. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  354. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  355. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  356. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  357. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  358. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  359. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  360. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  361. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  362. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  363. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  364. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  365. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  366. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  367. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  368. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
  369. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
  370. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
  371. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
@@ -159,6 +159,12 @@ class ResilientSessionService(BaseSessionService):
159
159
  return await self._hydrate(durable)
160
160
  return live
161
161
 
162
+ async def get_session_metadata(self, session_id: str) -> Optional[Session]:
163
+ ok, durable = await self._call_primary("get_session_metadata", session_id)
164
+ if ok and durable is not None:
165
+ return cast(Session, durable)
166
+ return await self.fallback.get_session_metadata(session_id)
167
+
162
168
  async def list_sessions(
163
169
  self,
164
170
  agent_id: str,
@@ -174,16 +180,14 @@ class ResilientSessionService(BaseSessionService):
174
180
  limit,
175
181
  )
176
182
  if ok:
177
- for session in durable_sessions or []:
178
- await self._hydrate(session)
179
- return cast(
180
- list[Session],
181
- await self.fallback.list_sessions(agent_id, user_id, offset, limit),
182
- )
183
+ return cast(list[Session], durable_sessions or [])
184
+ return await self.fallback.list_sessions(agent_id, user_id, offset, limit)
183
185
 
184
186
  async def count_sessions(self, agent_id: str, user_id: Optional[str] = None) -> int:
185
- sessions = await self.list_sessions(agent_id, user_id)
186
- return len(sessions)
187
+ ok, total = await self._call_primary("count_sessions", agent_id, user_id)
188
+ if ok:
189
+ return int(total or 0)
190
+ return await self.fallback.count_sessions(agent_id, user_id)
187
191
 
188
192
  async def delete_session(self, session_id: str) -> bool:
189
193
  deleted = await self.fallback.delete_session(session_id)
@@ -288,6 +292,30 @@ class ResilientSessionService(BaseSessionService):
288
292
  await self.fallback.count_events(session_id, after_seq_id, before_seq_id),
289
293
  )
290
294
 
295
+ async def get_events_for_agent(
296
+ self,
297
+ agent_id: str,
298
+ user_id: Optional[str] = None,
299
+ offset: Optional[int] = None,
300
+ limit: Optional[int] = None,
301
+ ) -> list[SessionEvent]:
302
+ ok, events = await self._call_primary(
303
+ "get_events_for_agent", agent_id, user_id, offset, limit
304
+ )
305
+ if ok:
306
+ return cast(list[SessionEvent], events)
307
+ return await self.fallback.get_events_for_agent(agent_id, user_id, offset, limit)
308
+
309
+ async def count_events_for_agent(
310
+ self,
311
+ agent_id: str,
312
+ user_id: Optional[str] = None,
313
+ ) -> int:
314
+ ok, total = await self._call_primary("count_events_for_agent", agent_id, user_id)
315
+ if ok:
316
+ return int(total or 0)
317
+ return await self.fallback.count_events_for_agent(agent_id, user_id)
318
+
291
319
  async def get_state(
292
320
  self,
293
321
  agent_id: str,
ksadk/skills/models.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterable
3
4
  from dataclasses import dataclass
4
5
  from typing import Any
5
6
 
@@ -48,7 +49,9 @@ class SkillRef:
48
49
  name=str(payload.get("Name") or payload.get("name") or ""),
49
50
  description=str(payload.get("Description") or payload.get("description") or ""),
50
51
  status=str(payload.get("Status") or payload.get("status") or ""),
51
- content_hash=ContentHash.parse(payload.get("ContentHash") or payload.get("content_hash")),
52
+ content_hash=ContentHash.parse(
53
+ payload.get("ContentHash") or payload.get("content_hash")
54
+ ),
52
55
  archive_uri=str(payload.get("ArchiveUri") or payload.get("archive_uri") or ""),
53
56
  aliases=_string_tuple(payload.get("Aliases") or payload.get("aliases")),
54
57
  tags=_string_tuple(payload.get("Tags") or payload.get("tags")),
@@ -65,7 +68,9 @@ class SkillRef:
65
68
  version_key = self.version_id or self.version
66
69
  if not version_key and self.content_hash:
67
70
  version_key = self.content_hash.value
68
- return "__".join(part.replace("/", "_").replace(":", "_") for part in (identity, version_key) if part)
71
+ return "__".join(
72
+ part.replace("/", "_").replace(":", "_") for part in (identity, version_key) if part
73
+ )
69
74
 
70
75
  @property
71
76
  def is_active(self) -> bool:
@@ -90,14 +95,20 @@ class SkillListResponse:
90
95
  space_name: str = "",
91
96
  ) -> "SkillListResponse":
92
97
  data = payload.get("Data") or payload.get("data") or {}
93
- skills_payload = data.get("Skills") or data.get("skills") or data.get("Items") or data.get("items") or []
98
+ skills_payload = (
99
+ data.get("Skills") or data.get("skills") or data.get("Items") or data.get("items") or []
100
+ )
94
101
  return cls(
95
102
  code=int(payload.get("Code") or payload.get("code") or 0),
96
103
  message=str(payload.get("Message") or payload.get("message") or ""),
97
104
  request_id=str(payload.get("RequestId") or payload.get("request_id") or ""),
98
105
  space_id=str(data.get("SkillSpaceId") or data.get("skill_space_id") or space_id),
99
- space_name=str(data.get("SkillSpaceName") or data.get("skill_space_name") or space_name),
100
- skills=[SkillRef.from_payload(item) for item in skills_payload if isinstance(item, dict)],
106
+ space_name=str(
107
+ data.get("SkillSpaceName") or data.get("skill_space_name") or space_name
108
+ ),
109
+ skills=[
110
+ SkillRef.from_payload(item) for item in skills_payload if isinstance(item, dict)
111
+ ],
101
112
  )
102
113
 
103
114
  def active_skills(self) -> list[SkillRef]:
@@ -107,6 +118,7 @@ class SkillListResponse:
107
118
  def _string_tuple(raw: Any) -> tuple[str, ...]:
108
119
  if raw is None:
109
120
  return ()
121
+ values: Iterable[Any]
110
122
  if isinstance(raw, str):
111
123
  values = raw.split(",")
112
124
  elif isinstance(raw, (list, tuple, set)):
@@ -79,11 +79,14 @@ class PackageStore:
79
79
  if not ref.content_hash:
80
80
  return
81
81
  if ref.content_hash.algorithm != "sha256":
82
- raise SkillPackageError(f"Unsupported ContentHash algorithm: {ref.content_hash.algorithm}")
82
+ raise SkillPackageError(
83
+ f"Unsupported ContentHash algorithm: {ref.content_hash.algorithm}"
84
+ )
83
85
  actual = hashlib.sha256(content).hexdigest()
84
86
  if actual.lower() != ref.content_hash.value.lower():
85
87
  raise SkillPackageError(
86
- f"ContentHash mismatch for {ref.name}: expected {ref.content_hash.render()}, got sha256:{actual}"
88
+ f"ContentHash mismatch for {ref.name}: expected "
89
+ f"{ref.content_hash.render()}, got sha256:{actual}"
87
90
  )
88
91
 
89
92
  def _safe_extract(self, archive_path: Path, extract_dir: Path) -> None:
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import json
4
4
  import os
5
- import subprocess
6
5
  import sys
7
6
  from dataclasses import asdict
8
7
  from pathlib import Path
@@ -12,15 +11,29 @@ import httpx
12
11
  from ksadk.skills.loader import LocalSkill
13
12
  from ksadk.skills.models import SkillRef
14
13
  from ksadk.skills.package_store import PackageStore
14
+ from ksadk.skills.runtime import loader as runtime_loader
15
+ from ksadk.skills.runtime import registry as runtime_registry
15
16
  from ksadk.skills.runtime.base import normalize_skill_names
16
17
  from ksadk.skills.runtime.executor import (
17
18
  WorkflowExecution,
18
19
  execute_workflow,
20
+ )
21
+ from ksadk.skills.runtime.executor import (
19
22
  _can_run_web_artifacts_builder as _executor_can_run_web_artifacts_builder,
23
+ )
24
+ from ksadk.skills.runtime.executor import (
20
25
  _run_command as _executor_run_command,
26
+ )
27
+ from ksadk.skills.runtime.executor import (
21
28
  _run_web_artifacts_builder as _executor_run_web_artifacts_builder,
29
+ )
30
+ from ksadk.skills.runtime.executor import (
22
31
  _runtime_timeout as _executor_runtime_timeout,
32
+ )
33
+ from ksadk.skills.runtime.executor import (
23
34
  _safe_project_name as _executor_safe_project_name,
35
+ )
36
+ from ksadk.skills.runtime.executor import (
24
37
  _tail as _executor_tail,
25
38
  )
26
39
  from ksadk.skills.runtime.request import (
@@ -28,8 +41,6 @@ from ksadk.skills.runtime.request import (
28
41
  SkillWorkflowRequestError,
29
42
  parse_workflow_request,
30
43
  )
31
- from ksadk.skills.runtime import loader as runtime_loader
32
- from ksadk.skills.runtime import registry as runtime_registry
33
44
 
34
45
 
35
46
  def _skill_space_ids() -> list[str]:
@@ -109,7 +120,9 @@ def run_agent(
109
120
  print("workflow=")
110
121
  print(f"skill_spaces={','.join(_skill_space_ids())}")
111
122
  print("loaded_skills=")
112
- print(f"workflow_result={json.dumps(asdict(execution), ensure_ascii=False, sort_keys=True)}")
123
+ print(
124
+ f"workflow_result={json.dumps(asdict(execution), ensure_ascii=False, sort_keys=True)}"
125
+ )
113
126
  return 1
114
127
 
115
128
  prompt = request.workflow_prompt
@@ -125,7 +138,9 @@ def run_agent(
125
138
  print(f"loaded_skills={','.join(skill.name for skill in loaded_skills)}")
126
139
  print(f"selected_skills={json.dumps(selected_skill_names, ensure_ascii=False, sort_keys=True)}")
127
140
  if _SKILL_LOAD_WARNINGS:
128
- print(f"skill_warnings={json.dumps(_SKILL_LOAD_WARNINGS, ensure_ascii=False, sort_keys=True)}")
141
+ print(
142
+ f"skill_warnings={json.dumps(_SKILL_LOAD_WARNINGS, ensure_ascii=False, sort_keys=True)}"
143
+ )
129
144
  print(f"workflow_result={json.dumps(asdict(execution), ensure_ascii=False, sort_keys=True)}")
130
145
  return 0 if execution.status != "failed" else 1
131
146
 
@@ -20,11 +20,7 @@ def parse_artifact_lines(stdout: str) -> list[str]:
20
20
  def collect_output_dir_artifacts(output_dir: Path) -> list[str]:
21
21
  if not output_dir.is_dir():
22
22
  return []
23
- return [
24
- str(path)
25
- for path in sorted(output_dir.rglob("*"))
26
- if path.is_file()
27
- ]
23
+ return [str(path) for path in sorted(output_dir.rglob("*")) if path.is_file()]
28
24
 
29
25
 
30
26
  def merge_artifacts(*groups: list[str]) -> list[str]:
@@ -7,9 +7,11 @@ from typing import Any
7
7
 
8
8
  from ksadk.sandbox import (
9
9
  E2BSandboxBackend,
10
- SandboxInputFile as RuntimeSandboxInputFile,
11
10
  SandboxSpec,
12
11
  )
12
+ from ksadk.sandbox import (
13
+ SandboxInputFile as RuntimeSandboxInputFile,
14
+ )
13
15
  from ksadk.skills.runtime.base import (
14
16
  SandboxInputFile,
15
17
  SkillRuntimeError,
@@ -75,10 +77,10 @@ class E2BSkillRuntimeBackend:
75
77
  @classmethod
76
78
  def from_env(cls) -> "E2BSkillRuntimeBackend":
77
79
  try:
78
- from e2b import Sandbox
80
+ from e2b import Sandbox # type: ignore[import-untyped]
79
81
  except ImportError as exc:
80
82
  raise SkillRuntimeError(
81
- "e2b>=2.0.0 is required for KSADK_SKILL_RUNTIME_BACKEND=e2b"
83
+ "e2b>=2.15.3,<2.25.0 is required for KSADK_SKILL_RUNTIME_BACKEND=e2b"
82
84
  ) from exc
83
85
  return cls(
84
86
  sandbox_cls=Sandbox,
@@ -87,7 +89,11 @@ class E2BSkillRuntimeBackend:
87
89
  or os.environ.get("KSADK_SKILL_RUNTIME_TEMPLATE_ID")
88
90
  or ""
89
91
  ),
90
- timeout=int(os.environ.get("KSADK_SANDBOX_TIMEOUT") or os.environ.get("KSADK_SKILL_RUNTIME_TIMEOUT") or "900"),
92
+ timeout=int(
93
+ os.environ.get("KSADK_SANDBOX_TIMEOUT")
94
+ or os.environ.get("KSADK_SKILL_RUNTIME_TIMEOUT")
95
+ or "900"
96
+ ),
91
97
  allow_internet_access=_bool_env(
92
98
  "KSADK_SANDBOX_ALLOW_INTERNET_ACCESS",
93
99
  _bool_env("KSADK_SKILL_RUNTIME_ALLOW_INTERNET_ACCESS", True),
@@ -17,6 +17,12 @@ from ksadk.skills.runtime.base import (
17
17
  )
18
18
 
19
19
 
20
+ def _coerce_output(value: str | bytes | None) -> str:
21
+ if isinstance(value, bytes):
22
+ return value.decode("utf-8", errors="replace")
23
+ return value or ""
24
+
25
+
20
26
  class LocalProcessSkillRuntimeBackend:
21
27
  def __init__(self, agent_path: str | Path, timeout: int = 900):
22
28
  self.agent_path = Path(agent_path)
@@ -67,7 +73,13 @@ class LocalProcessSkillRuntimeBackend:
67
73
  encoding="utf-8",
68
74
  )
69
75
  completed = subprocess.run(
70
- [sys.executable, "-u", str(self.agent_path), "--request-file", str(request_path)],
76
+ [
77
+ sys.executable,
78
+ "-u",
79
+ str(self.agent_path),
80
+ "--request-file",
81
+ str(request_path),
82
+ ],
71
83
  text=True,
72
84
  capture_output=True,
73
85
  timeout=timeout or self.timeout,
@@ -86,8 +98,8 @@ class LocalProcessSkillRuntimeBackend:
86
98
  return SkillRuntimeResult(
87
99
  runtime_id=f"local:{session_id}",
88
100
  exit_code=None,
89
- stdout=exc.stdout or "",
90
- stderr=exc.stderr or "",
101
+ stdout=_coerce_output(exc.stdout),
102
+ stderr=_coerce_output(exc.stderr),
91
103
  duration_ms=int((time.monotonic() - started) * 1000),
92
104
  timed_out=True,
93
105
  error_type="TimeoutExpired",
@@ -57,8 +57,7 @@ class SkillRuntimeBackend(Protocol):
57
57
  env: dict[str, str] | None = None,
58
58
  input_files: list[SandboxInputFile] | None = None,
59
59
  timeout: int = 900,
60
- ) -> SkillRuntimeResult:
61
- ...
60
+ ) -> SkillRuntimeResult: ...
62
61
 
63
62
 
64
63
  def parse_output_files(stdout: str) -> list[str]:
@@ -82,7 +82,10 @@ def _can_run_web_artifacts_builder(skill: LocalSkill, prompt: str) -> bool:
82
82
  if not init_script.exists() or not bundle_script.exists():
83
83
  return False
84
84
  normalized = prompt.lower()
85
- return any(marker in normalized for marker in ("web-artifacts-builder", "artifact", "bundle", "html", "react"))
85
+ return any(
86
+ marker in normalized
87
+ for marker in ("web-artifacts-builder", "artifact", "bundle", "html", "react")
88
+ )
86
89
 
87
90
 
88
91
  def _can_run_generic_workflow(skill: LocalSkill) -> bool:
@@ -91,7 +94,9 @@ def _can_run_generic_workflow(skill: LocalSkill) -> bool:
91
94
 
92
95
  def _run_web_artifacts_builder(skill: LocalSkill) -> WorkflowExecution:
93
96
  workdir = _skill_workdir()
94
- project_name = _safe_project_name(os.environ.get("KSADK_SKILL_ARTIFACT_PROJECT") or "ksadk-artifact")
97
+ project_name = _safe_project_name(
98
+ os.environ.get("KSADK_SKILL_ARTIFACT_PROJECT") or "ksadk-artifact"
99
+ )
95
100
  project_dir = workdir / project_name
96
101
  workdir.mkdir(parents=True, exist_ok=True)
97
102
  if project_dir.exists():
@@ -114,7 +119,9 @@ def _run_web_artifacts_builder(skill: LocalSkill) -> WorkflowExecution:
114
119
  timeout=timeout,
115
120
  )
116
121
  commands.append(bundle_result)
117
- output_files = [str(project_dir / "bundle.html")] if (project_dir / "bundle.html").exists() else []
122
+ output_files = (
123
+ [str(project_dir / "bundle.html")] if (project_dir / "bundle.html").exists() else []
124
+ )
118
125
  status = "ok" if bundle_result["exit_code"] == 0 and output_files else "failed"
119
126
  return WorkflowExecution(
120
127
  status=status,
@@ -2,10 +2,10 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
 
5
- from ksadk.skills.runtime.base import SkillRuntimeBackend
6
5
  from ksadk.skills.runtime.backends.disabled import DisabledSkillRuntimeBackend
7
6
  from ksadk.skills.runtime.backends.e2b import E2BSkillRuntimeBackend
8
7
  from ksadk.skills.runtime.backends.local import LocalProcessSkillRuntimeBackend
8
+ from ksadk.skills.runtime.base import SkillRuntimeBackend
9
9
 
10
10
 
11
11
  def _resolve_backend(backend: str | None = None) -> str:
@@ -20,7 +20,9 @@ def _resolve_backend(backend: str | None = None) -> str:
20
20
  if sandbox_backend and sandbox_backend not in {"disabled", "none", "off"}:
21
21
  return sandbox_backend
22
22
 
23
- if os.environ.get("KSADK_SANDBOX_TEMPLATE_ID") or os.environ.get("KSADK_SKILL_RUNTIME_TEMPLATE_ID"):
23
+ if os.environ.get("KSADK_SANDBOX_TEMPLATE_ID") or os.environ.get(
24
+ "KSADK_SKILL_RUNTIME_TEMPLATE_ID"
25
+ ):
24
26
  return "e2b"
25
27
 
26
28
  return "disabled"
@@ -37,8 +37,7 @@ def load_skills(
37
37
  return SkillLoadResult(skills=skills, warnings=warnings)
38
38
 
39
39
  cache_dir = Path(
40
- os.environ.get("KSADK_SKILL_CACHE_DIR")
41
- or Path(tempfile.gettempdir()) / "ksadk-skill-cache"
40
+ os.environ.get("KSADK_SKILL_CACHE_DIR") or Path(tempfile.gettempdir()) / "ksadk-skill-cache"
42
41
  )
43
42
  client = SkillServiceClient(
44
43
  base_url=service_url,
@@ -7,8 +7,14 @@ from ksadk.skills.models import SkillRef
7
7
  from ksadk.skills.runtime.base import normalize_skill_names
8
8
  from ksadk.skills.service_env import (
9
9
  parse_skill_space_ids,
10
+ )
11
+ from ksadk.skills.service_env import (
10
12
  public_skill_space_ids as configured_public_skill_space_ids,
13
+ )
14
+ from ksadk.skills.service_env import (
11
15
  skill_space_ids as configured_skill_space_ids,
16
+ )
17
+ from ksadk.skills.service_env import (
12
18
  user_skill_space_ids as configured_user_skill_space_ids,
13
19
  )
14
20
 
@@ -44,14 +50,13 @@ def dedupe_skill_refs(skill_refs: list[SkillRef], *, seen_names: set[str]) -> li
44
50
 
45
51
 
46
52
  def select_public_skill_refs(skill_refs: list[SkillRef]) -> list[SkillRef]:
47
- allowlist = {name.lower() for name in normalize_skill_names(os.environ.get("KSADK_PUBLIC_SKILL_ALLOWLIST", ""))}
53
+ allowlist = {
54
+ name.lower()
55
+ for name in normalize_skill_names(os.environ.get("KSADK_PUBLIC_SKILL_ALLOWLIST", ""))
56
+ }
48
57
  if not allowlist:
49
58
  return [skill for skill in skill_refs if skill.name]
50
- return [
51
- skill
52
- for skill in skill_refs
53
- if skill.name and skill.name.lower() in allowlist
54
- ]
59
+ return [skill for skill in skill_refs if skill.name and skill.name.lower() in allowlist]
55
60
 
56
61
 
57
62
  def select_remote_skill_refs(
@@ -118,7 +123,9 @@ def match_skill_refs(
118
123
  return matches
119
124
 
120
125
 
121
- def _metadata_score(skill: SkillRef, normalized_prompt: str, prompt_tokens: set[str]) -> tuple[int, str]:
126
+ def _metadata_score(
127
+ skill: SkillRef, normalized_prompt: str, prompt_tokens: set[str]
128
+ ) -> tuple[int, str]:
122
129
  if skill.name and skill.name.lower() in normalized_prompt:
123
130
  return 90, "name"
124
131
  for alias in skill.aliases:
@@ -144,7 +151,5 @@ def _metadata_score(skill: SkillRef, normalized_prompt: str, prompt_tokens: set[
144
151
 
145
152
  def _tokens(value: str) -> set[str]:
146
153
  return {
147
- token
148
- for token in re.split(r"[^0-9a-zA-Z\u4e00-\u9fff]+", value.lower())
149
- if len(token) >= 2
154
+ token for token in re.split(r"[^0-9a-zA-Z\u4e00-\u9fff]+", value.lower()) if len(token) >= 2
150
155
  }
@@ -28,7 +28,9 @@ def parse_workflow_request(argv: list[str]) -> SkillWorkflowRequest:
28
28
  if has_request_file:
29
29
  return _request_from_json_file(_option_value(args, "--request-file"))
30
30
  if has_prompt_file:
31
- return SkillWorkflowRequest(workflow_prompt=Path(_option_value(args, "--prompt-file")).read_text(encoding="utf-8"))
31
+ return SkillWorkflowRequest(
32
+ workflow_prompt=Path(_option_value(args, "--prompt-file")).read_text(encoding="utf-8")
33
+ )
32
34
  if not args:
33
35
  return SkillWorkflowRequest()
34
36
  return SkillWorkflowRequest(workflow_prompt=args[0])
@@ -9,9 +9,16 @@ import httpx
9
9
  import requests
10
10
 
11
11
  from ksadk.common.auth import AWSV4Auth
12
-
13
12
  from ksadk.skills.models import SkillListResponse, SkillRef
14
13
 
14
+ _KOP_HOSTS = frozenset(
15
+ {
16
+ "aicp.inner.api.ksyun.com",
17
+ "aicp.internal.api.ksyun.com",
18
+ "aicp.api.ksyun.com",
19
+ }
20
+ )
21
+
15
22
 
16
23
  class SkillServiceClient:
17
24
  def __init__(
@@ -31,14 +38,24 @@ class SkillServiceClient:
31
38
  ):
32
39
  self.base_url = _normalize_base_url(base_url)
33
40
  self.token = token
34
- self.access_key = access_key or _env("KSADK_SKILL_SERVICE_ACCESS_KEY", "KSYUN_ACCESS_KEY", "KS3_ACCESS_KEY")
35
- self.secret_key = secret_key or _env("KSADK_SKILL_SERVICE_SECRET_KEY", "KSYUN_SECRET_KEY", "KS3_SECRET_KEY")
41
+ self.access_key = access_key or _env(
42
+ "KSADK_SKILL_SERVICE_ACCESS_KEY", "KSYUN_ACCESS_KEY", "KS3_ACCESS_KEY"
43
+ )
44
+ self.secret_key = secret_key or _env(
45
+ "KSADK_SKILL_SERVICE_SECRET_KEY", "KSYUN_SECRET_KEY", "KS3_SECRET_KEY"
46
+ )
36
47
  self.account_id = account_id or _env("KSADK_SKILL_SERVICE_ACCOUNT_ID", "KSYUN_ACCOUNT_ID")
37
- self.logical_region = region or _env("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
48
+ self.logical_region = (
49
+ region or _env("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
50
+ )
38
51
  self.region = _normalize_control_region(self.logical_region)
39
52
  self.custom_source = _resolve_custom_source(self.logical_region)
40
- self.api_version = api_version or os.environ.get("KSADK_SKILL_SERVICE_API_VERSION", "2024-06-12")
41
- self.sign_service = sign_service or os.environ.get("KSADK_SKILL_SERVICE_SIGN_SERVICE", "aicp")
53
+ self.api_version = api_version or os.environ.get(
54
+ "KSADK_SKILL_SERVICE_API_VERSION", "2024-06-12"
55
+ )
56
+ self.sign_service = sign_service or os.environ.get(
57
+ "KSADK_SKILL_SERVICE_SIGN_SERVICE", "aicp"
58
+ )
42
59
  self.extra_headers = dict(extra_headers or {})
43
60
  self.timeout = timeout
44
61
  self.transport = transport
@@ -76,7 +93,9 @@ class SkillServiceClient:
76
93
 
77
94
  def list_available_premade_skills(self) -> SkillListResponse:
78
95
  payload = self._get_json("ListAvailablePremadeSkills", {})
79
- return SkillListResponse.from_payload(payload, space_id="public", space_name="Public Skills")
96
+ return SkillListResponse.from_payload(
97
+ payload, space_id="public", space_name="Public Skills"
98
+ )
80
99
 
81
100
  def get_skill_download_url(self, skill: SkillRef) -> str:
82
101
  action = "GetSkillDownloadUrl" if skill.version_id else "GetPremadeSkillDownloadUrl"
@@ -97,7 +116,7 @@ class SkillServiceClient:
97
116
  with httpx.Client(**self._client_kwargs()) as client:
98
117
  response = client.get(download_url)
99
118
  response.raise_for_status()
100
- return response.content
119
+ return bytes(response.content)
101
120
 
102
121
  def _get_json(self, action: str, params: dict[str, Any]) -> dict[str, Any]:
103
122
  if self._is_kop_mode():
@@ -169,15 +188,15 @@ class SkillServiceClient:
169
188
  "Set KSADK_SKILL_SERVICE_ACCESS_KEY/KSADK_SKILL_SERVICE_SECRET_KEY "
170
189
  "or KSYUN_ACCESS_KEY/KSYUN_SECRET_KEY."
171
190
  )
172
- response = self._requests().get(
191
+ requests_response = self._requests().get(
173
192
  self._kop_base_url() + "/",
174
193
  params=query,
175
194
  headers=headers,
176
195
  auth=self._auth.get_auth(),
177
196
  timeout=self.timeout,
178
197
  )
179
- response.raise_for_status()
180
- data = response.json()
198
+ requests_response.raise_for_status()
199
+ data = requests_response.json()
181
200
  if not isinstance(data, dict):
182
201
  raise ValueError(f"Skill Service returned non-object response for {action}")
183
202
  code = data.get("Code", data.get("code"))
@@ -196,12 +215,14 @@ class SkillServiceClient:
196
215
  return self._requests_session
197
216
 
198
217
  def _is_kop_mode(self) -> bool:
199
- host = urlsplit(self.base_url).netloc.lower()
200
- return (
201
- host.endswith("aicp.inner.api.ksyun.com")
202
- or host.endswith("aicp.internal.api.ksyun.com")
203
- or host.endswith("aicp.api.ksyun.com")
204
- )
218
+ """Match only exact, TLS-protected AICP control-plane endpoints.
219
+
220
+ A user-controlled URL such as ``aicp.api.ksyun.com.attacker.example``
221
+ must never receive KOP signing headers.
222
+ """
223
+ parsed = urlsplit(self.base_url)
224
+ host = (parsed.hostname or "").lower()
225
+ return parsed.scheme == "https" and host in _KOP_HOSTS
205
226
 
206
227
  def _kop_base_url(self) -> str:
207
228
  parsed = urlsplit(self.base_url)
ksadk/skills/tool_defs.py CHANGED
@@ -12,9 +12,11 @@ from ksadk.skills.service_env import (
12
12
  public_skill_space_ids,
13
13
  resolve_skill_service_url,
14
14
  should_resolve_child_skill_service_url,
15
- skill_space_ids as configured_skill_space_ids,
16
15
  user_skill_space_ids,
17
16
  )
17
+ from ksadk.skills.service_env import (
18
+ skill_space_ids as configured_skill_space_ids,
19
+ )
18
20
 
19
21
  RUNTIME_AGENT_ENV_NAMES = (
20
22
  "KSADK_SKILL_SERVICE_URL",
@@ -51,11 +53,7 @@ def _parse_skill_space_ids(*raw_values: str) -> list[str]:
51
53
 
52
54
 
53
55
  def runtime_agent_env_from_process(skill_space_ids: list[str] | None = None) -> dict[str, str]:
54
- env = {
55
- name: value
56
- for name in RUNTIME_AGENT_ENV_NAMES
57
- if (value := os.environ.get(name))
58
- }
56
+ env = {name: value for name in RUNTIME_AGENT_ENV_NAMES if (value := os.environ.get(name))}
59
57
  if "KSADK_SKILL_SERVICE_ACCOUNT_ID" not in env and (
60
58
  account_id := os.environ.get("KSYUN_ACCOUNT_ID")
61
59
  ):
@@ -72,7 +70,11 @@ def runtime_agent_env_from_process(skill_space_ids: list[str] | None = None) ->
72
70
  if value:
73
71
  env[target] = value
74
72
  break
75
- if has_spaces and should_resolve_child_skill_service_url() and "KSADK_SKILL_SERVICE_URL" not in env:
73
+ if (
74
+ has_spaces
75
+ and should_resolve_child_skill_service_url()
76
+ and "KSADK_SKILL_SERVICE_URL" not in env
77
+ ):
76
78
  service_url = resolve_skill_service_url(require_spaces=False)
77
79
  if service_url:
78
80
  env["KSADK_SKILL_SERVICE_URL"] = service_url
@@ -125,7 +127,8 @@ def load_remote_skill_manifests(skill_space_ids: list[str] | None = None) -> lis
125
127
  seen: set[str] = set()
126
128
  limit = _manifest_limit()
127
129
  public_allowlist = {
128
- name.lower() for name in normalize_skill_names(os.environ.get("KSADK_PUBLIC_SKILL_ALLOWLIST", ""))
130
+ name.lower()
131
+ for name in normalize_skill_names(os.environ.get("KSADK_PUBLIC_SKILL_ALLOWLIST", ""))
129
132
  }
130
133
  for space_id in user_spaces:
131
134
  listing = client.list_skills_by_space_id(space_id)
@@ -161,8 +164,10 @@ def build_skill_manifest_instruction(manifests: list[dict[str, str]]) -> str:
161
164
  lines = [
162
165
  "",
163
166
  "Available remote skills are listed below. Use them only when they match the user's task.",
164
- "When a skill is useful, call execute_skills with the original workflow_prompt and skill_names set to the exact skill name.",
165
- "Do not assume full skill instructions are already loaded; execute_skills loads selected skills on demand.",
167
+ "When a skill is useful, call execute_skills with the original workflow_prompt "
168
+ "and skill_names set to the exact skill name.",
169
+ "Do not assume full skill instructions are already loaded; execute_skills loads "
170
+ "selected skills on demand.",
166
171
  "",
167
172
  "Remote skills:",
168
173
  ]
@@ -140,10 +140,9 @@ def validate_terminal_exec_argv(
140
140
 
141
141
  normalized = normalize_exec_argv(argv, policy_name=policy.name)
142
142
  allowed_exact = tuple(tuple(item) for item in policy.default_exact)
143
- allowed_prefixes = (
144
- tuple(tuple(item) for item in policy.default_prefixes)
145
- + _env_allowlist_prefixes(policy.env_names, policy_name=policy.name)
146
- )
143
+ allowed_prefixes = tuple(
144
+ tuple(item) for item in policy.default_prefixes
145
+ ) + _env_allowlist_prefixes(policy.env_names, policy_name=policy.name)
147
146
 
148
147
  if _matches_exact_or_prefix(
149
148
  normalized,