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
@@ -8,7 +8,7 @@ import re
8
8
  import shutil
9
9
  import subprocess
10
10
  from pathlib import Path
11
- from typing import Any
11
+ from typing import Any, Callable
12
12
 
13
13
  from ksadk.sessions.local_service import resolve_local_session_dir
14
14
  from ksadk.tools.gateway import ToolPolicy, default_tool_gateway
@@ -16,7 +16,6 @@ from ksadk.tools.result_budget import budget_tool_output, default_tool_result_bu
16
16
  from ksadk.toolsets._langchain import as_tool
17
17
  from ksadk.toolsets.workspace_state import WorkspaceReadState, get_read_state, record_read_state
18
18
 
19
-
20
19
  _WORKSPACE_TOOL_POLICIES = {
21
20
  "workspace_status": ToolPolicy(risk_level="low"),
22
21
  "list_workspace_files": ToolPolicy(risk_level="low"),
@@ -35,8 +34,14 @@ def _gateway():
35
34
  return default_tool_gateway(_WORKSPACE_TOOL_POLICIES)
36
35
 
37
36
 
37
+ def _dict_result(value: Any, *, tool_name: str) -> dict[str, Any]:
38
+ if not isinstance(value, dict):
39
+ raise TypeError(f"{tool_name} returned {type(value).__name__}, expected dict")
40
+ return dict(value)
41
+
42
+
38
43
  def workspace_root() -> Path:
39
- return resolve_local_session_dir() / "workspace"
44
+ return Path(resolve_local_session_dir()) / "workspace"
40
45
 
41
46
 
42
47
  def resolve_workspace_path(relative_path: str) -> Path:
@@ -55,7 +60,10 @@ def workspace_relative(path: Path) -> str:
55
60
  def workspace_status() -> dict[str, Any]:
56
61
  """Return current AgentEngine workspace status."""
57
62
 
58
- return _gateway().invoke("workspace_status", _workspace_status_impl)
63
+ return _dict_result(
64
+ _gateway().invoke("workspace_status", _workspace_status_impl),
65
+ tool_name="workspace_status",
66
+ )
59
67
 
60
68
 
61
69
  def _workspace_status_impl() -> dict[str, Any]:
@@ -83,15 +91,18 @@ def list_workspace_files(
83
91
  ) -> dict[str, Any]:
84
92
  """List files under the AgentEngine workspace."""
85
93
 
86
- return _gateway().invoke(
87
- "list_workspace_files",
88
- _list_workspace_files_impl,
89
- path,
90
- glob,
91
- recursive,
92
- include_dirs,
93
- max_results,
94
- sort_by,
94
+ return _dict_result(
95
+ _gateway().invoke(
96
+ "list_workspace_files",
97
+ _list_workspace_files_impl,
98
+ path,
99
+ glob,
100
+ recursive,
101
+ include_dirs,
102
+ max_results,
103
+ sort_by,
104
+ ),
105
+ tool_name="list_workspace_files",
95
106
  )
96
107
 
97
108
 
@@ -117,17 +128,31 @@ def _list_workspace_files_impl(
117
128
  items = [
118
129
  item
119
130
  for item in items
120
- if fnmatch.fnmatch(workspace_relative(item), pattern) or fnmatch.fnmatch(item.name, pattern)
131
+ if fnmatch.fnmatch(workspace_relative(item), pattern)
132
+ or fnmatch.fnmatch(item.name, pattern)
121
133
  ]
122
134
  if not include_dirs:
123
135
  items = [item for item in items if item.is_file()]
124
136
  sort_key = str(sort_by or "name").strip().lower()
137
+ key: Callable[[Path], tuple[Any, ...]]
125
138
  if sort_key == "mtime":
126
- key = lambda candidate: (candidate.stat().st_mtime_ns, workspace_relative(candidate))
139
+
140
+ def key(candidate: Path) -> tuple[Any, ...]:
141
+ return candidate.stat().st_mtime_ns, workspace_relative(candidate)
142
+
127
143
  elif sort_key == "size":
128
- key = lambda candidate: (candidate.stat().st_size if candidate.is_file() else 0, workspace_relative(candidate))
144
+
145
+ def key(candidate: Path) -> tuple[Any, ...]:
146
+ return (
147
+ candidate.stat().st_size if candidate.is_file() else 0,
148
+ workspace_relative(candidate),
149
+ )
150
+
129
151
  else:
130
- key = lambda candidate: (workspace_relative(candidate).lower(), candidate.is_file())
152
+
153
+ def key(candidate: Path) -> tuple[Any, ...]:
154
+ return workspace_relative(candidate).lower(), candidate.is_file()
155
+
131
156
  limit = max(1, min(int(max_results or 500), 5000))
132
157
  sorted_items = sorted(items, key=key)
133
158
  entries = [
@@ -140,7 +165,13 @@ def _list_workspace_files_impl(
140
165
  }
141
166
  for item in sorted_items[:limit]
142
167
  ]
143
- return {"ok": True, "path": path, "recursive": recursive, "entries": entries, "truncated": len(sorted_items) > len(entries)}
168
+ return {
169
+ "ok": True,
170
+ "path": path,
171
+ "recursive": recursive,
172
+ "entries": entries,
173
+ "truncated": len(sorted_items) > len(entries),
174
+ }
144
175
 
145
176
 
146
177
  def read_workspace_file(
@@ -155,14 +186,17 @@ def read_workspace_file(
155
186
  Do not issue a dependent read and edit in the same parallel tool-call batch.
156
187
  """
157
188
 
158
- return _gateway().invoke(
159
- "read_workspace_file",
160
- _read_workspace_file_impl,
161
- path,
162
- start_line,
163
- end_line,
164
- max_chars,
165
- include_line_numbers,
189
+ return _dict_result(
190
+ _gateway().invoke(
191
+ "read_workspace_file",
192
+ _read_workspace_file_impl,
193
+ path,
194
+ start_line,
195
+ end_line,
196
+ max_chars,
197
+ include_line_numbers,
198
+ ),
199
+ tool_name="read_workspace_file",
166
200
  )
167
201
 
168
202
 
@@ -201,7 +235,9 @@ def _read_workspace_file_impl(
201
235
  field_name="content",
202
236
  value=content,
203
237
  metadata={"tool_use_id": f"read_{relative.replace('/', '_')}"},
204
- budget=default_tool_result_budget(max_chars=limit, preview_chars=limit, persist_threshold_chars=limit),
238
+ budget=default_tool_result_budget(
239
+ max_chars=limit, preview_chars=limit, persist_threshold_chars=limit
240
+ ),
205
241
  )
206
242
  partial = start != 1 or end != total_lines
207
243
  record_read_state(
@@ -251,13 +287,16 @@ def write_workspace_file(
251
287
  ) -> dict[str, Any]:
252
288
  """Write a UTF-8 text file inside the AgentEngine workspace."""
253
289
 
254
- return _gateway().invoke(
255
- "write_workspace_file",
256
- _write_workspace_file_impl,
257
- path,
258
- content,
259
- overwrite,
260
- approval=approval,
290
+ return _dict_result(
291
+ _gateway().invoke(
292
+ "write_workspace_file",
293
+ _write_workspace_file_impl,
294
+ path,
295
+ content,
296
+ overwrite,
297
+ approval=approval,
298
+ ),
299
+ tool_name="write_workspace_file",
261
300
  )
262
301
 
263
302
 
@@ -282,16 +321,21 @@ def write_workspace_files(
282
321
  ) -> dict[str, Any]:
283
322
  """Write multiple UTF-8 text files inside the AgentEngine workspace."""
284
323
 
285
- return _gateway().invoke(
286
- "write_workspace_files",
287
- _write_workspace_files_impl,
288
- files,
289
- overwrite,
290
- approval=approval,
324
+ return _dict_result(
325
+ _gateway().invoke(
326
+ "write_workspace_files",
327
+ _write_workspace_files_impl,
328
+ files,
329
+ overwrite,
330
+ approval=approval,
331
+ ),
332
+ tool_name="write_workspace_files",
291
333
  )
292
334
 
293
335
 
294
- def _write_workspace_files_impl(files: list[dict[str, Any]], overwrite: bool = True) -> dict[str, Any]:
336
+ def _write_workspace_files_impl(
337
+ files: list[dict[str, Any]], overwrite: bool = True
338
+ ) -> dict[str, Any]:
295
339
  if not isinstance(files, list) or not files:
296
340
  return {"ok": False, "error_message": "files must be a non-empty list"}
297
341
  written = []
@@ -301,7 +345,9 @@ def _write_workspace_files_impl(files: list[dict[str, Any]], overwrite: bool = T
301
345
  path = str(item.get("path") or "").strip()
302
346
  if not path:
303
347
  return {"ok": False, "error_message": "each file item requires path"}
304
- result = _write_workspace_file_impl(path, str(item.get("content") or ""), overwrite=overwrite)
348
+ result = _write_workspace_file_impl(
349
+ path, str(item.get("content") or ""), overwrite=overwrite
350
+ )
305
351
  if not result.get("ok"):
306
352
  return result
307
353
  written.append({"path": result["path"], "size": result["size"]})
@@ -321,15 +367,18 @@ def edit_workspace_file(
321
367
  The read must complete before this call; do not batch a dependent read and edit.
322
368
  """
323
369
 
324
- return _gateway().invoke(
325
- "edit_workspace_file",
326
- _edit_workspace_file_impl,
327
- path,
328
- old_text,
329
- new_text,
330
- expected_replacements,
331
- replace_all,
332
- approval=approval,
370
+ return _dict_result(
371
+ _gateway().invoke(
372
+ "edit_workspace_file",
373
+ _edit_workspace_file_impl,
374
+ path,
375
+ old_text,
376
+ new_text,
377
+ expected_replacements,
378
+ replace_all,
379
+ approval=approval,
380
+ ),
381
+ tool_name="edit_workspace_file",
333
382
  )
334
383
 
335
384
 
@@ -351,6 +400,8 @@ def _edit_workspace_file_impl(
351
400
  text, error = _read_workspace_text(target)
352
401
  if error is not None:
353
402
  return {**error, "path": path}
403
+ if text is None:
404
+ return {"ok": False, "path": path, "error_message": "workspace file read failed"}
354
405
  edit_result = _apply_single_edit(
355
406
  text,
356
407
  old_text,
@@ -390,13 +441,16 @@ def multi_edit_workspace_file(
390
441
  The read must complete before this call; do not batch a dependent read and edit.
391
442
  """
392
443
 
393
- return _gateway().invoke(
394
- "multi_edit_workspace_file",
395
- _multi_edit_workspace_file_impl,
396
- path,
397
- edits,
398
- replace_all,
399
- approval=approval,
444
+ return _dict_result(
445
+ _gateway().invoke(
446
+ "multi_edit_workspace_file",
447
+ _multi_edit_workspace_file_impl,
448
+ path,
449
+ edits,
450
+ replace_all,
451
+ approval=approval,
452
+ ),
453
+ tool_name="multi_edit_workspace_file",
400
454
  )
401
455
 
402
456
 
@@ -478,7 +532,10 @@ def _multi_edit_workspace_file_impl(
478
532
  def lint_workspace_file(path: str, language: str = "auto") -> dict[str, Any]:
479
533
  """Run lightweight built-in lint checks for a UTF-8 workspace text file."""
480
534
 
481
- return _gateway().invoke("lint_workspace_file", _lint_workspace_file_impl, path, language)
535
+ return _dict_result(
536
+ _gateway().invoke("lint_workspace_file", _lint_workspace_file_impl, path, language),
537
+ tool_name="lint_workspace_file",
538
+ )
482
539
 
483
540
 
484
541
  def _lint_workspace_file_impl(path: str, language: str = "auto") -> dict[str, Any]:
@@ -515,9 +572,23 @@ def _lint_workspace_file_impl(path: str, language: str = "auto") -> dict[str, An
515
572
  else:
516
573
  for line_no, line in enumerate((text or "").splitlines(), start=1):
517
574
  if "\x00" in line:
518
- issues.append({"severity": "error", "line": line_no, "column": line.index("\x00") + 1, "message": "NUL byte found"})
575
+ issues.append(
576
+ {
577
+ "severity": "error",
578
+ "line": line_no,
579
+ "column": line.index("\x00") + 1,
580
+ "message": "NUL byte found",
581
+ }
582
+ )
519
583
  if line.rstrip("\n\r") != line.rstrip():
520
- issues.append({"severity": "warning", "line": line_no, "column": len(line), "message": "trailing whitespace"})
584
+ issues.append(
585
+ {
586
+ "severity": "warning",
587
+ "line": line_no,
588
+ "column": len(line),
589
+ "message": "trailing whitespace",
590
+ }
591
+ )
521
592
  if len(issues) >= 20:
522
593
  break
523
594
  return {
@@ -557,16 +628,19 @@ def search_workspace_files(
557
628
  ) -> dict[str, Any]:
558
629
  """Search UTF-8 text files in the AgentEngine workspace."""
559
630
 
560
- return _gateway().invoke(
561
- "search_workspace_files",
562
- _search_workspace_files_impl,
563
- query,
564
- path,
565
- is_regex,
566
- glob,
567
- case_sensitive,
568
- context_lines,
569
- max_results,
631
+ return _dict_result(
632
+ _gateway().invoke(
633
+ "search_workspace_files",
634
+ _search_workspace_files_impl,
635
+ query,
636
+ path,
637
+ is_regex,
638
+ glob,
639
+ case_sensitive,
640
+ context_lines,
641
+ max_results,
642
+ ),
643
+ tool_name="search_workspace_files",
570
644
  )
571
645
 
572
646
 
@@ -584,15 +658,23 @@ def _search_workspace_files_impl(
584
658
  return {"ok": False, "error_message": "query is required"}
585
659
  base = resolve_workspace_path(path)
586
660
  if shutil.which("rg") and not context_lines:
587
- rg_result = _search_with_rg(needle, base, is_regex, glob, case_sensitive, context_lines, max_results)
661
+ rg_result = _search_with_rg(
662
+ needle, base, is_regex, glob, case_sensitive, context_lines, max_results
663
+ )
588
664
  if rg_result is not None:
589
- return _search_payload(query, path, rg_result["results"], rg_result["truncated"], context_lines, "rg")
665
+ return _search_payload(
666
+ query, path, rg_result["results"], rg_result["truncated"], context_lines, "rg"
667
+ )
590
668
  candidates = [base] if base.is_file() else [item for item in base.rglob("*") if item.is_file()]
591
669
  if glob:
592
- candidates = [item for item in candidates if fnmatch.fnmatch(workspace_relative(item), glob) or fnmatch.fnmatch(item.name, glob)]
670
+ candidates = [
671
+ item
672
+ for item in candidates
673
+ if fnmatch.fnmatch(workspace_relative(item), glob) or fnmatch.fnmatch(item.name, glob)
674
+ ]
593
675
  flags = 0 if case_sensitive else re.IGNORECASE
594
676
  pattern = re.compile(needle if is_regex else re.escape(needle), flags)
595
- results = []
677
+ results: list[dict[str, Any]] = []
596
678
  limit = max(1, min(int(max_results or 100), 5000))
597
679
  context_limit = max(0, min(int(context_lines or 0), 20))
598
680
  truncated = False
@@ -665,7 +747,7 @@ def _search_with_rg(
665
747
  return None
666
748
  if completed.returncode not in {0, 1}:
667
749
  return None
668
- results = []
750
+ results: list[dict[str, Any]] = []
669
751
  limit = max(1, min(int(max_results or 100), 5000))
670
752
  truncated = False
671
753
  for raw_line in completed.stdout.splitlines():
@@ -725,13 +807,19 @@ def _validate_read_state(target: Path, relative: str) -> dict[str, Any] | None:
725
807
  "suggested_action": f"Call read_workspace_file(path={relative!r}) before editing.",
726
808
  }
727
809
  stat = target.stat() if target.exists() else None
728
- if stat is None or stat.st_mtime_ns != read_state.mtime_ns or stat.st_size != read_state.size_bytes:
810
+ if (
811
+ stat is None
812
+ or stat.st_mtime_ns != read_state.mtime_ns
813
+ or stat.st_size != read_state.size_bytes
814
+ ):
729
815
  return {
730
816
  "ok": False,
731
817
  "path": relative,
732
818
  "error_type": "file_modified_since_read",
733
819
  "error_message": "workspace file changed since last read",
734
- "suggested_action": f"Re-read the file with read_workspace_file(path={relative!r}) and retry.",
820
+ "suggested_action": (
821
+ f"Re-read the file with read_workspace_file(path={relative!r}) " "and retry."
822
+ ),
735
823
  }
736
824
  return None
737
825
 
@@ -761,7 +849,17 @@ def _apply_single_edit(
761
849
  "error_message": "old_text was not found in the workspace file",
762
850
  "occurrences": 0,
763
851
  "nearby_candidates": _nearby_candidates(text, old),
764
- "suggested_action": "Use one nearby candidate as old_text, or call read_workspace_file with line numbers and retry.",
852
+ "suggested_action": (
853
+ "Use one nearby candidate as old_text, or call read_workspace_file "
854
+ "with line numbers and retry."
855
+ ),
856
+ }
857
+ if actual_old is None:
858
+ return {
859
+ "ok": False,
860
+ "path": relative,
861
+ "error_type": "snippet_not_found",
862
+ "error_message": "old_text was not found in the workspace file",
765
863
  }
766
864
  if not replace_all and occurrences != expected:
767
865
  return {
@@ -772,7 +870,10 @@ def _apply_single_edit(
772
870
  "occurrences": occurrences,
773
871
  "expected_replacements": expected,
774
872
  "matches": matches,
775
- "suggested_action": "Provide a larger unique old_text snippet, set expected_replacements, or use replace_all=true.",
873
+ "suggested_action": (
874
+ "Provide a larger unique old_text snippet, set expected_replacements, "
875
+ "or use replace_all=true."
876
+ ),
776
877
  }
777
878
  replacements = occurrences if replace_all else expected
778
879
  return {
@@ -809,11 +910,15 @@ def _match_previews(text: str, needle: str, limit: int = 20) -> list[dict[str, A
809
910
 
810
911
  def _nearby_candidates(text: str, old: str, limit: int = 5) -> list[dict[str, Any]]:
811
912
  old_norm = _normalize_quotes(old).strip()
812
- candidates = []
913
+ candidates: list[dict[str, Any]] = []
813
914
  for line_no, line in enumerate(text.splitlines(), start=1):
814
915
  ratio = difflib.SequenceMatcher(None, old_norm, _normalize_quotes(line).strip()).ratio()
815
- if old_norm and (old_norm[: max(1, min(4, len(old_norm)))] in _normalize_quotes(line) or ratio > 0.45):
816
- candidates.append({"line": line_no, "text": line.strip(), "snippet": line, "score": round(ratio, 3)})
916
+ if old_norm and (
917
+ old_norm[: max(1, min(4, len(old_norm)))] in _normalize_quotes(line) or ratio > 0.45
918
+ ):
919
+ candidates.append(
920
+ {"line": line_no, "text": line.strip(), "snippet": line, "score": round(ratio, 3)}
921
+ )
817
922
  candidates.sort(key=lambda item: (-float(item["score"]), int(item["line"])))
818
923
  return candidates[:limit]
819
924
 
@@ -830,11 +935,14 @@ def _build_diff(relative: str, before: str, after: str) -> str:
830
935
 
831
936
 
832
937
  def _budget_diff(tool_name: str, diff: str, relative: str) -> dict[str, Any]:
833
- return budget_tool_output(
938
+ return _dict_result(
939
+ budget_tool_output(
940
+ tool_name=tool_name,
941
+ field_name="diff",
942
+ value=diff,
943
+ metadata={"tool_use_id": f"{tool_name}_{relative.replace('/', '_')}"},
944
+ ),
834
945
  tool_name=tool_name,
835
- field_name="diff",
836
- value=diff,
837
- metadata={"tool_use_id": f"{tool_name}_{relative.replace('/', '_')}"},
838
946
  )
839
947
 
840
948
 
@@ -857,7 +965,8 @@ def _find_actual_string(text: str, old: str) -> tuple[str | None, bool]:
857
965
  if old in text:
858
966
  return old, False
859
967
  normalized_old = _normalize_quotes(old)
860
- for candidate in {normalized_old, old.translate(str.maketrans({'"': "“", "'": "‘"}))}:
968
+ smart_quote_map: dict[str, str | int | None] = {'"': "“", "'": "‘"}
969
+ for candidate in {normalized_old, old.translate(str.maketrans(smart_quote_map))}:
861
970
  if candidate and candidate in text:
862
971
  return candidate, True
863
972
  normalized_text = _normalize_quotes(text)
@@ -868,24 +977,26 @@ def _find_actual_string(text: str, old: str) -> tuple[str | None, bool]:
868
977
 
869
978
 
870
979
  def _normalize_quotes(value: str) -> str:
871
- return value.translate(
872
- str.maketrans(
873
- {
874
- "“": '"',
875
- "”": '"',
876
- "„": '"',
877
- "‘": "'",
878
- "’": "'",
879
- "‚": "'",
880
- }
881
- )
882
- )
980
+ quote_map: dict[str, str | int | None] = {
981
+ "“": '"',
982
+ "”": '"',
983
+ "„": '"',
984
+ "‘": "'",
985
+ "’": "'",
986
+ "‚": "'",
987
+ }
988
+ return value.translate(str.maketrans(quote_map))
883
989
 
884
990
 
885
991
  def delete_workspace_file(path: str, approval: dict[str, Any] | None = None) -> dict[str, Any]:
886
992
  """Delete a file or empty directory inside the AgentEngine workspace."""
887
993
 
888
- return _gateway().invoke("delete_workspace_file", _delete_workspace_file_impl, path, approval=approval)
994
+ return _dict_result(
995
+ _gateway().invoke(
996
+ "delete_workspace_file", _delete_workspace_file_impl, path, approval=approval
997
+ ),
998
+ tool_name="delete_workspace_file",
999
+ )
889
1000
 
890
1001
 
891
1002
  def _delete_workspace_file_impl(path: str) -> dict[str, Any]: