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
ksadk/tools/gateway.py CHANGED
@@ -1,19 +1,28 @@
1
1
  from __future__ import annotations
2
2
 
3
- import os
4
3
  import hashlib
5
4
  import json
5
+ import os
6
6
  import shlex
7
7
  from collections.abc import Callable, Mapping, Sequence
8
8
  from dataclasses import dataclass, field
9
9
  from typing import Any
10
10
  from uuid import uuid4
11
11
 
12
+ from ksadk.runtime_context import get_current_invocation_context
13
+
12
14
 
13
15
  @dataclass(frozen=True)
14
16
  class ToolPolicy:
15
17
  risk_level: str = "low"
16
18
  side_effects: Sequence[str] = field(default_factory=tuple)
19
+ # Approval scopes classify operations which might need an interactive
20
+ # decision. ``public_network`` is intentionally a read-only exception:
21
+ # web discovery must remain available in every approval profile.
22
+ approval_scopes: Sequence[str] = field(default_factory=tuple)
23
+ # Use only for tools whose operation is inherently safe to run without a
24
+ # human decision. This wins over a risk level or explicit legacy policy.
25
+ approval_exempt: bool = False
17
26
  requires_approval: bool | None = None
18
27
 
19
28
 
@@ -50,8 +59,9 @@ class ToolGateway:
50
59
 
51
60
  @staticmethod
52
61
  def _approval_mode() -> str:
53
- value = os.environ.get("KSADK_TOOL_APPROVAL_MODE", "").strip().lower()
54
- return value or "off"
62
+ context = get_current_invocation_context()
63
+ requested_mode = context.tool_approval_mode if context is not None else None
64
+ return normalize_tool_approval_mode(requested_mode)
55
65
 
56
66
  @staticmethod
57
67
  def _is_approved(approval: Mapping[str, Any] | None) -> bool:
@@ -108,24 +118,76 @@ def tool_policy_requires_approval(
108
118
  *,
109
119
  approval_mode: str | None = None,
110
120
  ) -> bool:
111
- mode = (approval_mode or os.environ.get("KSADK_TOOL_APPROVAL_MODE", "")).strip().lower() or "off"
121
+ mode = normalize_tool_approval_mode(approval_mode)
122
+ if policy.approval_exempt or _is_read_only_public_network_policy(policy):
123
+ return False
112
124
  if policy.requires_approval is not None:
113
- return policy.requires_approval and mode != "off"
114
- if mode != "strict":
125
+ return policy.requires_approval and mode != "full"
126
+ if mode == "full":
115
127
  return False
128
+ if mode == "ask" and policy.approval_scopes:
129
+ return True
116
130
  return policy.risk_level.lower() in {"medium", "high", "critical"}
117
131
 
118
132
 
133
+ def _is_read_only_public_network_policy(policy: ToolPolicy) -> bool:
134
+ """Keep public web reads available even under the most cautious profile.
135
+
136
+ A network write must declare a side effect, so it does not match this
137
+ exemption and can still require approval.
138
+ """
139
+ return bool(policy.approval_scopes) and set(policy.approval_scopes) <= {
140
+ "public_network"
141
+ } and not policy.side_effects
142
+
143
+
144
+ def normalize_tool_approval_mode(value: str | None = None) -> str:
145
+ """Resolve the compact runtime approval profile.
146
+
147
+ ``ask`` confirms risky and non-network scoped operations; ``risk``
148
+ confirms medium-and-higher risk only; ``full`` leaves default policies
149
+ unprompted. Public web reads remain approval-free in every profile. The
150
+ process environment remains a default for non-UI callers, while a
151
+ request-scoped mode wins for the duration of that invocation.
152
+ """
153
+ raw = str(value or os.environ.get("KSADK_TOOL_APPROVAL_MODE", "risk")).strip().lower()
154
+ return raw if raw in {"ask", "risk", "full"} else "risk"
155
+
156
+
157
+ def tool_approval_capability() -> dict[str, Any]:
158
+ """Describe the single profile interface exposed to hosted UIs."""
159
+ return {
160
+ "Modes": ["ask", "risk", "full"],
161
+ "DefaultMode": normalize_tool_approval_mode(),
162
+ "RuntimeOverride": True,
163
+ }
164
+
165
+
119
166
  def check_command_policy(command: str) -> dict[str, Any]:
120
167
  text = str(command or "").strip()
121
168
  if not text:
122
- return {"ok": False, "decision": "reject", "error_type": "command_required", "error_message": "command is required"}
169
+ return {
170
+ "ok": False,
171
+ "decision": "reject",
172
+ "error_type": "command_required",
173
+ "error_message": "command is required",
174
+ }
123
175
  try:
124
176
  tokens = shlex.split(text)
125
177
  except ValueError as exc:
126
- return {"ok": False, "decision": "reject", "error_type": "invalid_command", "error_message": str(exc)}
178
+ return {
179
+ "ok": False,
180
+ "decision": "reject",
181
+ "error_type": "invalid_command",
182
+ "error_message": str(exc),
183
+ }
127
184
  if not tokens:
128
- return {"ok": False, "decision": "reject", "error_type": "command_required", "error_message": "command is required"}
185
+ return {
186
+ "ok": False,
187
+ "decision": "reject",
188
+ "error_type": "command_required",
189
+ "error_message": "command is required",
190
+ }
129
191
  if _contains_recursive_rm(tokens):
130
192
  return _command_rejected("recursive rm is not allowed without explicit approval")
131
193
  if any(token in _DANGEROUS_COMMAND_TOKENS for token in tokens):
@@ -137,12 +199,19 @@ def check_command_policy(command: str) -> dict[str, Any]:
137
199
  if subcommand in _DANGEROUS_GIT_COMMANDS:
138
200
  return _command_rejected(f"git {subcommand} is not allowed without explicit approval")
139
201
  if _references_metadata_endpoint(tokens):
140
- return _command_rejected("metadata/private endpoint access is not allowed by default policy")
202
+ return _command_rejected(
203
+ "metadata/private endpoint access is not allowed by default policy"
204
+ )
141
205
  return {"ok": True, "decision": "allow", "reason": "default_allow"}
142
206
 
143
207
 
144
208
  def _command_rejected(message: str) -> dict[str, Any]:
145
- return {"ok": False, "decision": "reject", "error_type": "command_rejected", "error_message": message}
209
+ return {
210
+ "ok": False,
211
+ "decision": "reject",
212
+ "error_type": "command_rejected",
213
+ "error_message": message,
214
+ }
146
215
 
147
216
 
148
217
  def _contains_recursive_rm(tokens: Sequence[str]) -> bool:
@@ -162,7 +231,9 @@ def _references_metadata_endpoint(tokens: Sequence[str]) -> bool:
162
231
 
163
232
  def _canonical_tool_args(tool_args: Any) -> str:
164
233
  try:
165
- return json.dumps(tool_args or {}, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
234
+ return json.dumps(
235
+ tool_args or {}, ensure_ascii=False, sort_keys=True, separators=(",", ":")
236
+ )
166
237
  except TypeError:
167
238
  return json.dumps(str(tool_args), ensure_ascii=False, separators=(",", ":"))
168
239
 
@@ -185,7 +256,9 @@ def build_tool_receipt_idempotency_key(
185
256
  "tool_args": _canonical_tool_args(tool_args),
186
257
  }
187
258
  digest = hashlib.sha256(
188
- json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8")
259
+ json.dumps(payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode(
260
+ "utf-8"
261
+ )
189
262
  ).hexdigest()
190
263
  return f"tool_receipt:{digest}"
191
264
 
@@ -222,8 +295,12 @@ def approval_interrupt_info_from_result(
222
295
  or {}
223
296
  ),
224
297
  "risk_level": str(approval_request.get("risk_level") or result.get("risk_level") or ""),
225
- "side_effects": list(approval_request.get("side_effects") or result.get("side_effects") or []),
226
- "server_label": str(approval_request.get("server_label") or result.get("server_label") or "ksadk"),
298
+ "side_effects": list(
299
+ approval_request.get("side_effects") or result.get("side_effects") or []
300
+ ),
301
+ "server_label": str(
302
+ approval_request.get("server_label") or result.get("server_label") or "ksadk"
303
+ ),
227
304
  }
228
305
  if run_id:
229
306
  interrupt["run_id"] = str(run_id)
@@ -10,7 +10,6 @@ from uuid import uuid4
10
10
 
11
11
  from ksadk.sessions.local_service import resolve_local_session_dir
12
12
 
13
-
14
13
  _SAFE_NAME_RE = re.compile(r"[^A-Za-z0-9_.-]+")
15
14
 
16
15
 
@@ -58,7 +57,10 @@ def budget_tool_output(
58
57
  active_budget = budget or default_tool_result_budget()
59
58
  text, mime_type, extension = _stringify_value(value)
60
59
  original_chars = len(text)
61
- should_persist = original_chars > active_budget.persist_threshold_chars or original_chars > active_budget.max_chars
60
+ should_persist = (
61
+ original_chars > active_budget.persist_threshold_chars
62
+ or original_chars > active_budget.max_chars
63
+ )
62
64
  preview_limit = max(0, min(active_budget.preview_chars, active_budget.max_chars))
63
65
  preview = text[:preview_limit] if should_persist else text[: active_budget.max_chars]
64
66
  result: dict[str, Any] = {
@@ -126,7 +128,9 @@ def _persist_tool_output(
126
128
  or metadata.get("id")
127
129
  or uuid4().hex
128
130
  )
129
- stem = _safe_filename(f"{tool_use_id}.{field_name}") or _safe_filename(f"{tool_name}.{field_name}.{uuid4().hex}")
131
+ stem = _safe_filename(f"{tool_use_id}.{field_name}") or _safe_filename(
132
+ f"{tool_name}.{field_name}.{uuid4().hex}"
133
+ )
130
134
  path = (persist_dir / f"{stem}.{extension}").resolve()
131
135
  if persist_dir not in path.parents and path != persist_dir:
132
136
  raise ValueError("tool result path must stay inside persist_dir")
@@ -137,7 +141,11 @@ def _persist_tool_output(
137
141
  def _stringify_value(value: Any) -> tuple[str, str, str]:
138
142
  if isinstance(value, str):
139
143
  return value, "text/plain", "txt"
140
- return json.dumps(value, ensure_ascii=False, indent=2, sort_keys=True), "application/json", "json"
144
+ return (
145
+ json.dumps(value, ensure_ascii=False, indent=2, sort_keys=True),
146
+ "application/json",
147
+ "json",
148
+ )
141
149
 
142
150
 
143
151
  def _safe_filename(value: str) -> str:
@@ -3,34 +3,36 @@ from __future__ import annotations
3
3
  import json
4
4
  import os
5
5
  import re
6
- from collections.abc import Iterable
7
- from collections.abc import Mapping
6
+ from collections.abc import Callable, Iterable, Mapping
8
7
  from typing import Any
9
8
 
10
- from ksadk.toolsets.platform import get_platform_tools
11
- from ksadk.toolsets.platform import component_status
12
- from ksadk.toolsets.sandbox import get_sandbox_tools
9
+ from ksadk.tools.gateway import ToolPolicy, tool_policy_requires_approval
10
+ from ksadk.toolsets._langchain import as_tool
11
+ from ksadk.toolsets.platform import component_status, get_platform_tools
13
12
  from ksadk.toolsets.sandbox import (
14
13
  _SANDBOX_TOOL_POLICIES,
14
+ get_sandbox_tools,
15
15
  run_code,
16
16
  run_command,
17
17
  sandbox_backend_name,
18
18
  sandbox_status,
19
19
  )
20
- from ksadk.toolsets.skills import get_skill_tools
21
20
  from ksadk.toolsets.skills import (
22
21
  _SKILL_TOOL_POLICIES,
23
22
  _skill_execution_backend,
24
23
  execute_skills,
24
+ get_skill_tools,
25
+ list_skill_spaces,
25
26
  list_skills,
26
27
  load_skill,
27
28
  search_skills,
28
29
  )
29
- from ksadk.toolsets.workspace import get_workspace_tools
30
+ from ksadk.toolsets.web import _WEB_TOOL_POLICIES, get_web_tools, web_fetch, web_search
30
31
  from ksadk.toolsets.workspace import (
31
32
  _WORKSPACE_TOOL_POLICIES,
32
33
  delete_workspace_file,
33
34
  edit_workspace_file,
35
+ get_workspace_tools,
34
36
  lint_workspace_file,
35
37
  list_workspace_files,
36
38
  multi_edit_workspace_file,
@@ -40,10 +42,6 @@ from ksadk.toolsets.workspace import (
40
42
  write_workspace_file,
41
43
  write_workspace_files,
42
44
  )
43
- from ksadk.toolsets.web import get_web_tools
44
- from ksadk.toolsets.web import web_fetch, web_search, _WEB_TOOL_POLICIES
45
- from ksadk.tools.gateway import ToolPolicy, tool_policy_requires_approval
46
- from ksadk.toolsets._langchain import as_tool
47
45
 
48
46
  _DEFAULT_GROUPS = ("skill", "workspace", "platform", "sandbox", "web")
49
47
  _DISPATCHER_TOOL_NAME = "tool_dispatcher"
@@ -79,9 +77,12 @@ _TOOLSET_FACTORIES = {
79
77
  "web": get_web_tools,
80
78
  }
81
79
 
82
- _TOOLSET_DESCRIPTORS = {
80
+ _TOOLSET_DESCRIPTORS: dict[
81
+ str, tuple[tuple[Callable[..., Any], ToolPolicy, dict[str, Any]], ...]
82
+ ] = {
83
83
  "skill": (
84
84
  (list_skills, _SKILL_TOOL_POLICIES["list_skills"], {}),
85
+ (list_skill_spaces, _SKILL_TOOL_POLICIES["list_skill_spaces"], {}),
85
86
  (search_skills, _SKILL_TOOL_POLICIES["search_skills"], {}),
86
87
  (load_skill, _SKILL_TOOL_POLICIES["load_skill"], {}),
87
88
  (
@@ -95,20 +96,58 @@ _TOOLSET_DESCRIPTORS = {
95
96
  ),
96
97
  ),
97
98
  "workspace": (
98
- (workspace_status, _WORKSPACE_TOOL_POLICIES["workspace_status"], {"boundary": "workspace_root"}),
99
- (list_workspace_files, _WORKSPACE_TOOL_POLICIES["list_workspace_files"], {"boundary": "workspace_root"}),
100
- (read_workspace_file, _WORKSPACE_TOOL_POLICIES["read_workspace_file"], {"boundary": "workspace_root"}),
101
- (write_workspace_file, _WORKSPACE_TOOL_POLICIES["write_workspace_file"], {"boundary": "workspace_root"}),
102
- (write_workspace_files, _WORKSPACE_TOOL_POLICIES["write_workspace_files"], {"boundary": "workspace_root"}),
103
- (edit_workspace_file, _WORKSPACE_TOOL_POLICIES["edit_workspace_file"], {"boundary": "workspace_root"}),
104
- (multi_edit_workspace_file, _WORKSPACE_TOOL_POLICIES["multi_edit_workspace_file"], {"boundary": "workspace_root"}),
105
- (lint_workspace_file, _WORKSPACE_TOOL_POLICIES["lint_workspace_file"], {"boundary": "workspace_root"}),
106
- (search_workspace_files, _WORKSPACE_TOOL_POLICIES["search_workspace_files"], {"boundary": "workspace_root"}),
107
- (delete_workspace_file, _WORKSPACE_TOOL_POLICIES["delete_workspace_file"], {"boundary": "workspace_root"}),
108
- ),
109
- "platform": (
110
- (component_status, ToolPolicy(risk_level="low"), {}),
99
+ (
100
+ workspace_status,
101
+ _WORKSPACE_TOOL_POLICIES["workspace_status"],
102
+ {"boundary": "workspace_root"},
103
+ ),
104
+ (
105
+ list_workspace_files,
106
+ _WORKSPACE_TOOL_POLICIES["list_workspace_files"],
107
+ {"boundary": "workspace_root"},
108
+ ),
109
+ (
110
+ read_workspace_file,
111
+ _WORKSPACE_TOOL_POLICIES["read_workspace_file"],
112
+ {"boundary": "workspace_root"},
113
+ ),
114
+ (
115
+ write_workspace_file,
116
+ _WORKSPACE_TOOL_POLICIES["write_workspace_file"],
117
+ {"boundary": "workspace_root"},
118
+ ),
119
+ (
120
+ write_workspace_files,
121
+ _WORKSPACE_TOOL_POLICIES["write_workspace_files"],
122
+ {"boundary": "workspace_root"},
123
+ ),
124
+ (
125
+ edit_workspace_file,
126
+ _WORKSPACE_TOOL_POLICIES["edit_workspace_file"],
127
+ {"boundary": "workspace_root"},
128
+ ),
129
+ (
130
+ multi_edit_workspace_file,
131
+ _WORKSPACE_TOOL_POLICIES["multi_edit_workspace_file"],
132
+ {"boundary": "workspace_root"},
133
+ ),
134
+ (
135
+ lint_workspace_file,
136
+ _WORKSPACE_TOOL_POLICIES["lint_workspace_file"],
137
+ {"boundary": "workspace_root"},
138
+ ),
139
+ (
140
+ search_workspace_files,
141
+ _WORKSPACE_TOOL_POLICIES["search_workspace_files"],
142
+ {"boundary": "workspace_root"},
143
+ ),
144
+ (
145
+ delete_workspace_file,
146
+ _WORKSPACE_TOOL_POLICIES["delete_workspace_file"],
147
+ {"boundary": "workspace_root"},
148
+ ),
111
149
  ),
150
+ "platform": ((component_status, ToolPolicy(risk_level="low"), {}),),
112
151
  "sandbox": (
113
152
  (
114
153
  sandbox_status,
@@ -218,9 +257,38 @@ def tool_dispatcher(
218
257
  include: str | Iterable[str] | None = None,
219
258
  profile: str = "default",
220
259
  ) -> dict[str, Any]:
221
- """List, describe, or call ksadk built-in tools through one governed entrypoint."""
260
+ """List, describe, or call ksadk built-in tools through one governed entrypoint.
261
+
262
+ Args:
263
+ action: One of "list" (list available tools), "describe" (get a tool's
264
+ spec), or "call" (execute a tool). Common synonyms "call_tool",
265
+ "execute", "run" are auto-mapped to "call"; "get" to "describe".
266
+ tool_name: Required for "describe" and "call"; ignored for "list".
267
+ arguments: Tool arguments (dict or JSON string); used with "call".
268
+ include: Comma-separated tool groups to scope (e.g. "skill,sandbox").
269
+ profile: Tool profile name (default: "default").
270
+ """
222
271
 
223
272
  normalized_action = str(action or "").strip().lower()
273
+ # 兼容 LLM 常见同义词,避免 "call_tool"/"execute"/"run" 等导致 unknown_action。
274
+ _ACTION_SYNONYMS = {
275
+ "call_tool": "call",
276
+ "execute": "call",
277
+ "run": "call",
278
+ "invoke": "call",
279
+ "get": "describe",
280
+ "info": "describe",
281
+ "ls": "list",
282
+ "search": "list",
283
+ }
284
+ normalized_action = _ACTION_SYNONYMS.get(normalized_action, normalized_action)
285
+ # LLM 常把 tool_name 塞进 action(如 "list_skills"/"search_skills"/"run_command")。
286
+ # 如果 action 不是合法值,无论 tool_name 是否有值,都自动当成 "call":
287
+ # 有 tool_name → 直接 call; 无 tool_name → 把 action 值当 tool_name 再 call。
288
+ if normalized_action not in ("list", "describe", "call"):
289
+ if not tool_name:
290
+ tool_name = normalized_action
291
+ normalized_action = "call"
224
292
  requested_include = _normalize_include(include)
225
293
 
226
294
  if normalized_action == "list":
@@ -231,17 +299,25 @@ def tool_dispatcher(
231
299
  include_dispatcher=False,
232
300
  )
233
301
  except ValueError:
234
- return _unknown_tool_error(", ".join(requested_include) if requested_include else str(include or ""))
302
+ return _unknown_tool_error(
303
+ ", ".join(requested_include) if requested_include else str(include or "")
304
+ )
235
305
  return {"ok": True, "tools": specs, "tool_count": len(specs)}
236
306
 
237
307
  if normalized_action == "describe":
238
308
  target_name = _normalize_tool_name(tool_name)
239
309
  if not target_name:
240
- return {"ok": False, "error_type": "missing_tool_name", "error_message": "tool_name is required"}
310
+ return {
311
+ "ok": False,
312
+ "error_type": "missing_tool_name",
313
+ "error_message": "tool_name is required",
314
+ }
241
315
  if target_name in {_DISPATCHER_TOOL_NAME, _LEGACY_DISPATCHER_TOOL_NAME}:
242
316
  return _dispatcher_self_call_error()
243
317
  try:
244
- _, specs = _select_agentengine_tools(include=[target_name], profile=profile, include_dispatcher=False)
318
+ _, specs = _select_agentengine_tools(
319
+ include=[target_name], profile=profile, include_dispatcher=False
320
+ )
245
321
  except ValueError:
246
322
  return _unknown_tool_error(target_name)
247
323
  return {"ok": True, "tool": specs[0]}
@@ -249,15 +325,26 @@ def tool_dispatcher(
249
325
  if normalized_action == "call":
250
326
  target_name = _normalize_tool_name(tool_name)
251
327
  if not target_name:
252
- return {"ok": False, "error_type": "missing_tool_name", "error_message": "tool_name is required"}
328
+ return {
329
+ "ok": False,
330
+ "error_type": "missing_tool_name",
331
+ "error_message": "tool_name is required",
332
+ }
253
333
  if target_name in {_DISPATCHER_TOOL_NAME, _LEGACY_DISPATCHER_TOOL_NAME}:
254
334
  return _dispatcher_self_call_error()
255
335
  try:
256
- tools, specs = _select_agentengine_tools(include=[target_name], profile=profile, include_dispatcher=False)
336
+ tools, specs = _select_agentengine_tools(
337
+ include=[target_name], profile=profile, include_dispatcher=False
338
+ )
257
339
  except ValueError:
258
340
  return _unknown_tool_error(target_name)
259
341
  if specs and specs[0].get("enabled") is False:
260
- return {"ok": False, "error_type": "tool_disabled", "error_message": f"Tool is disabled: {target_name}", "tool_name": target_name}
342
+ return {
343
+ "ok": False,
344
+ "error_type": "tool_disabled",
345
+ "error_message": f"Tool is disabled: {target_name}",
346
+ "tool_name": target_name,
347
+ }
261
348
  tool_arguments, arguments_error = _normalize_tool_arguments(arguments)
262
349
  if arguments_error:
263
350
  return arguments_error
@@ -429,7 +516,9 @@ def _expand_requested_names(requested: list[str], tool_registry: Mapping[str, An
429
516
  return names
430
517
 
431
518
 
432
- def _expand_requested_descriptor_names(requested: list[str], descriptor_registry: Mapping[str, Any]) -> list[str]:
519
+ def _expand_requested_descriptor_names(
520
+ requested: list[str], descriptor_registry: Mapping[str, Any]
521
+ ) -> list[str]:
433
522
  names: list[str] = []
434
523
  for name in requested:
435
524
  canonical_name = _canonical_toolset_group(name)
@@ -560,7 +649,9 @@ def _normalize_tool_name(tool_name: str | None) -> str:
560
649
  return str(tool_name or "").strip()
561
650
 
562
651
 
563
- def _normalize_tool_arguments(arguments: dict[str, Any] | str | None) -> tuple[dict[str, Any], dict[str, Any] | None]:
652
+ def _normalize_tool_arguments(
653
+ arguments: dict[str, Any] | str | None,
654
+ ) -> tuple[dict[str, Any], dict[str, Any] | None]:
564
655
  if arguments is None:
565
656
  return {}, None
566
657
  if isinstance(arguments, dict):
@@ -594,7 +685,9 @@ def _normalize_tool_arguments(arguments: dict[str, Any] | str | None) -> tuple[d
594
685
  }
595
686
 
596
687
 
597
- def _normalize_dispatched_tool_arguments(tool_name: str, arguments: dict[str, Any]) -> dict[str, Any]:
688
+ def _normalize_dispatched_tool_arguments(
689
+ tool_name: str, arguments: dict[str, Any]
690
+ ) -> dict[str, Any]:
598
691
  if tool_name == "save_memory" and "content" not in arguments:
599
692
  if "key" in arguments and "value" in arguments:
600
693
  return {"content": f"{arguments['key']}: {_stringify_memory_value(arguments['value'])}"}
@@ -819,13 +912,18 @@ def _tool_spec(
819
912
  "risk_level": policy.risk_level,
820
913
  "requires_approval": tool_policy_requires_approval(policy),
821
914
  "side_effects": list(policy.side_effects),
915
+ "approval_scopes": list(policy.approval_scopes),
916
+ "approval_exempt": policy.approval_exempt,
822
917
  "enabled": True,
823
918
  }
824
919
  for key, value in dict(extras or {}).items():
825
920
  spec[key] = value() if callable(value) else value
826
921
  enabled = bool(spec.get("enabled", True))
827
922
  if name == "web_search":
828
- enabled = bool(os.environ.get("KSADK_WEB_SEARCH_PROVIDER") or os.environ.get("OPENCLAW_WEB_SEARCH_PROVIDER"))
923
+ enabled = bool(
924
+ os.environ.get("KSADK_WEB_SEARCH_PROVIDER")
925
+ or os.environ.get("OPENCLAW_WEB_SEARCH_PROVIDER")
926
+ )
829
927
  if name in {"run_command", "run_code", "sandbox_status"}:
830
928
  enabled = enabled and _enabled_backend(sandbox_backend_name())
831
929
  spec["enabled"] = enabled
@@ -34,8 +34,16 @@ def component_status() -> dict:
34
34
  "knowledge_base_bound": bool(_env("KSADK_KB_DATASET_ID")),
35
35
  "long_term_memory_bound": bool(_env("KSADK_LTM_NAMESPACE")),
36
36
  "skill_space_bound": bool(spaces),
37
- "isolated_execution": "enabled" if skill_runtime_backend not in {"", "disabled", "none", "off"} else "not_enabled",
38
- "sandbox_direct_tools": "enabled" if sandbox_backend not in {"", "disabled", "none", "off"} else "not_enabled",
37
+ "isolated_execution": (
38
+ "enabled"
39
+ if skill_runtime_backend not in {"", "disabled", "none", "off"}
40
+ else "not_enabled"
41
+ ),
42
+ "sandbox_direct_tools": (
43
+ "enabled"
44
+ if sandbox_backend not in {"", "disabled", "none", "off"}
45
+ else "not_enabled"
46
+ ),
39
47
  },
40
48
  "skill_space": {
41
49
  "space_ids": spaces,
@@ -48,13 +56,17 @@ def component_status() -> dict:
48
56
  "skill_runtime": {
49
57
  "backend": skill_runtime_backend,
50
58
  "enabled": skill_runtime_backend not in {"", "disabled", "none", "off"},
51
- "template_bound": bool(_env("KSADK_SANDBOX_TEMPLATE_ID") or _env("KSADK_SKILL_RUNTIME_TEMPLATE_ID")),
59
+ "template_bound": bool(
60
+ _env("KSADK_SANDBOX_TEMPLATE_ID") or _env("KSADK_SKILL_RUNTIME_TEMPLATE_ID")
61
+ ),
52
62
  "request_protocol": "--request-file JSON envelope",
53
63
  },
54
64
  "sandbox": {
55
65
  "backend": sandbox_backend,
56
66
  "enabled": sandbox_backend not in {"", "disabled", "none", "off"},
57
- "template_bound": bool(_env("KSADK_SANDBOX_TEMPLATE_ID") or _env("KSADK_SKILL_RUNTIME_TEMPLATE_ID")),
67
+ "template_bound": bool(
68
+ _env("KSADK_SANDBOX_TEMPLATE_ID") or _env("KSADK_SKILL_RUNTIME_TEMPLATE_ID")
69
+ ),
58
70
  "tools": ["sandbox_status", "run_command", "run_code"],
59
71
  },
60
72
  "workspace": {
@@ -71,7 +83,11 @@ def component_status() -> dict:
71
83
  "delete_workspace_file",
72
84
  ],
73
85
  "boundary": "Workspace tools are confined to the AgentEngine UI workspace directory.",
74
- "editing_model": "write tools support whole-file writes; edit_workspace_file supports exact snippet replacement; lint_workspace_file provides lightweight built-in checks.",
86
+ "editing_model": (
87
+ "write tools support whole-file writes; edit_workspace_file supports "
88
+ "exact snippet replacement; lint_workspace_file provides lightweight "
89
+ "built-in checks."
90
+ ),
75
91
  },
76
92
  }
77
93