agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.1__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 (450) hide show
  1. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/METADATA +52 -20
  2. agentengine_sdk_python-0.8.1.dist-info/RECORD +644 -0
  3. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/WHEEL +1 -1
  4. ksadk/a2a/__init__.py +180 -11
  5. ksadk/a2a/bootstrap.py +332 -0
  6. ksadk/a2a/card.py +15 -0
  7. ksadk/a2a/context_store.py +203 -0
  8. ksadk/a2a/control_plane.py +1056 -0
  9. ksadk/a2a/credential.py +99 -0
  10. ksadk/a2a/event_adapter.py +149 -0
  11. ksadk/a2a/executor.py +361 -137
  12. ksadk/a2a/external_transport.py +516 -0
  13. ksadk/a2a/identity.py +304 -0
  14. ksadk/a2a/ids.py +22 -0
  15. ksadk/a2a/langgraph.py +285 -0
  16. ksadk/a2a/resume_store.py +201 -0
  17. ksadk/a2a/routes.py +112 -0
  18. ksadk/a2a/server.py +102 -62
  19. ksadk/a2a/service_env.py +33 -0
  20. ksadk/a2a/space_client.py +1122 -0
  21. ksadk/a2a/task_adapter.py +423 -0
  22. ksadk/a2a/task_event_dispatcher.py +167 -0
  23. ksadk/a2a/task_event_outbox.py +326 -0
  24. ksadk/a2a/task_store.py +206 -0
  25. ksadk/a2a_card.py +101 -0
  26. ksadk/a2ui/__init__.py +27 -0
  27. ksadk/a2ui/core.py +186 -0
  28. ksadk/a2ui/models.py +166 -0
  29. ksadk/a2ui/renderer.py +198 -0
  30. ksadk/agui/__init__.py +9 -0
  31. ksadk/agui/a2ui_projection.py +92 -0
  32. ksadk/agui/agent.py +872 -0
  33. ksadk/agui/config.py +92 -0
  34. ksadk/agui/routes.py +47 -0
  35. ksadk/api/client.py +238 -204
  36. ksadk/api/environment.py +27 -0
  37. ksadk/builders/__init__.py +2 -0
  38. ksadk/builders/base.py +16 -14
  39. ksadk/builders/code_builder.py +375 -270
  40. ksadk/builders/container_builder.py +240 -200
  41. ksadk/builders/framework_requirements.py +31 -12
  42. ksadk/builders/ks3_uploader.py +60 -29
  43. ksadk/builders/managed_runtime_builder.py +173 -0
  44. ksadk/builders/mcp_builder.py +91 -92
  45. ksadk/builders/requirements_utils.py +1 -5
  46. ksadk/cli/__init__.py +97 -171
  47. ksadk/cli/cmd_a2a.py +255 -84
  48. ksadk/cli/cmd_agent.py +19 -5
  49. ksadk/cli/cmd_build.py +158 -29
  50. ksadk/cli/cmd_completion.py +47 -35
  51. ksadk/cli/cmd_config.py +267 -198
  52. ksadk/cli/cmd_create.py +507 -740
  53. ksadk/cli/cmd_dashboard.py +120 -45
  54. ksadk/cli/cmd_deploy.py +135 -59
  55. ksadk/cli/cmd_destroy.py +44 -14
  56. ksadk/cli/cmd_eval.py +386 -0
  57. ksadk/cli/cmd_files.py +63 -24
  58. ksadk/cli/cmd_hermes.py +313 -135
  59. ksadk/cli/cmd_invoke.py +184 -122
  60. ksadk/cli/cmd_launch.py +76 -28
  61. ksadk/cli/cmd_mcp.py +98 -64
  62. ksadk/cli/cmd_model.py +14 -5
  63. ksadk/cli/cmd_openclaw.py +564 -268
  64. ksadk/cli/cmd_replay.py +71 -0
  65. ksadk/cli/cmd_run.py +58 -73
  66. ksadk/cli/cmd_status.py +80 -31
  67. ksadk/cli/cmd_studio.py +110 -0
  68. ksadk/cli/cmd_version.py +20 -13
  69. ksadk/cli/cmd_web.py +95 -18
  70. ksadk/cli/deploy_utils.py +20 -20
  71. ksadk/cli/dry_run.py +7 -4
  72. ksadk/cli/env_options.py +83 -0
  73. ksadk/cli/error_utils.py +37 -12
  74. ksadk/cli/global_options.py +4 -3
  75. ksadk/cli/local_runtime.py +1 -2
  76. ksadk/cli/model_catalog.py +6 -2
  77. ksadk/cli/network_options.py +41 -19
  78. ksadk/cli/resource_common.py +6 -2
  79. ksadk/cli/runtime_bootstrap.py +51 -0
  80. ksadk/cli/storage.py +0 -1
  81. ksadk/cli/ui.py +11 -3
  82. ksadk/cli/workflow_common.py +52 -18
  83. ksadk/codex/__init__.py +12 -0
  84. ksadk/codex/client.py +1042 -0
  85. ksadk/codex/phase.py +143 -0
  86. ksadk/codex/runtime.py +940 -0
  87. ksadk/common/aicp_env.py +0 -1
  88. ksadk/common/auth.py +2 -2
  89. ksadk/common/constants.py +1 -3
  90. ksadk/common/kop_client.py +232 -0
  91. ksadk/common/llm_utils.py +17 -13
  92. ksadk/compat/__init__.py +5 -0
  93. ksadk/compat/adk_compat.py +200 -0
  94. ksadk/compat/copilotkit_a2ui.py +330 -0
  95. ksadk/configs/__init__.py +12 -14
  96. ksadk/configs/env_registry.py +661 -116
  97. ksadk/configs/global_config.py +3 -2
  98. ksadk/configs/settings.py +133 -209
  99. ksadk/conversations/__init__.py +85 -92
  100. ksadk/conversations/attachment_storage.py +16 -11
  101. ksadk/conversations/attachments.py +44 -36
  102. ksadk/conversations/compaction_pipeline.py +12 -12
  103. ksadk/conversations/compaction_prompt.py +9 -5
  104. ksadk/conversations/context.py +221 -6
  105. ksadk/conversations/message_projection.py +438 -51
  106. ksadk/conversations/model_context.py +12 -6
  107. ksadk/conversations/model_options.py +0 -1
  108. ksadk/conversations/normalize.py +20 -16
  109. ksadk/conversations/reasoning_markup.py +1 -1
  110. ksadk/conversations/runtime.py +339 -5255
  111. ksadk/conversations/runtime_compaction.py +333 -0
  112. ksadk/conversations/runtime_constants.py +27 -0
  113. ksadk/conversations/runtime_governance.py +185 -0
  114. ksadk/conversations/runtime_input.py +660 -0
  115. ksadk/conversations/runtime_invocation.py +395 -0
  116. ksadk/conversations/runtime_metadata.py +475 -0
  117. ksadk/conversations/runtime_observability.py +367 -0
  118. ksadk/conversations/runtime_payloads.py +272 -0
  119. ksadk/conversations/runtime_persistence.py +440 -0
  120. ksadk/conversations/runtime_preparation.py +426 -0
  121. ksadk/conversations/runtime_resume.py +836 -0
  122. ksadk/conversations/runtime_stream_events.py +902 -0
  123. ksadk/conversations/runtime_streaming.py +700 -0
  124. ksadk/conversations/semantic_summary.py +17 -5
  125. ksadk/conversations/session_title.py +6 -3
  126. ksadk/deployment/__init__.py +15 -16
  127. ksadk/deployment/agent_access.py +12 -23
  128. ksadk/deployment/base.py +51 -38
  129. ksadk/deployment/managed_runtime.py +33 -0
  130. ksadk/deployment/manager.py +85 -71
  131. ksadk/deployment/providers/serverless.py +379 -210
  132. ksadk/deployment/registry.py +38 -32
  133. ksadk/deployment/state.py +11 -11
  134. ksadk/deployment/ui_config.py +1 -1
  135. ksadk/detection/__init__.py +1 -1
  136. ksadk/detection/detector.py +146 -83
  137. ksadk/detection/mcp_detector.py +9 -6
  138. ksadk/evaluation/__init__.py +84 -0
  139. ksadk/evaluation/a2a_adapter.py +444 -0
  140. ksadk/evaluation/adapters.py +54 -0
  141. ksadk/evaluation/contracts.py +409 -0
  142. ksadk/evaluation/evalset.py +351 -0
  143. ksadk/evaluation/evaluators.py +461 -0
  144. ksadk/evaluation/executor.py +118 -0
  145. ksadk/evaluation/storage.py +68 -0
  146. ksadk/evaluation/target.py +73 -0
  147. ksadk/events/__init__.py +25 -0
  148. ksadk/events/parser.py +191 -0
  149. ksadk/events/replay.py +37 -0
  150. ksadk/events/runtime_event.py +273 -0
  151. ksadk/events/store.py +317 -0
  152. ksadk/harness/__init__.py +35 -0
  153. ksadk/harness/app.py +269 -0
  154. ksadk/harness/config.py +181 -0
  155. ksadk/harness/reasoner.py +105 -0
  156. ksadk/harness/runtime.py +364 -0
  157. ksadk/harness/sandbox.py +141 -0
  158. ksadk/harness/tools.py +222 -0
  159. ksadk/hermes_terminal.py +28 -12
  160. ksadk/identity/resolver.py +15 -9
  161. ksadk/ids.py +32 -0
  162. ksadk/knowledge_base/adk_tool.py +1 -1
  163. ksadk/knowledge_base/client.py +38 -33
  164. ksadk/managed_a2a_card.py +160 -0
  165. ksadk/managed_runtime.py +195 -0
  166. ksadk/markdown.py +5 -2
  167. ksadk/mcp_runtime/__init__.py +9 -6
  168. ksadk/memory/__init__.py +1 -1
  169. ksadk/memory/adk/__init__.py +2 -0
  170. ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
  171. ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
  172. ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
  173. ksadk/memory/adk/backends/sdk_ltm_backend.py +36 -36
  174. ksadk/memory/adk/long_term_memory.py +34 -37
  175. ksadk/memory/adk/resilient_session_service.py +4 -5
  176. ksadk/memory/adk/short_term_memory.py +12 -21
  177. ksadk/memory/adk_tool.py +3 -2
  178. ksadk/memory/backends/base.py +19 -19
  179. ksadk/memory/backends/memory.py +24 -25
  180. ksadk/memory/backends/redis.py +31 -30
  181. ksadk/memory/langchain_tool.py +2 -1
  182. ksadk/memory/manager.py +52 -47
  183. ksadk/memory/service.py +16 -6
  184. ksadk/memory/tool.py +4 -0
  185. ksadk/model_policy.py +15 -7
  186. ksadk/model_proxy/__init__.py +51 -0
  187. ksadk/model_proxy/bootstrap.py +80 -0
  188. ksadk/model_proxy/cache.py +165 -0
  189. ksadk/model_proxy/config.py +66 -0
  190. ksadk/model_proxy/demo_webui.py +115 -0
  191. ksadk/model_proxy/detect.py +145 -0
  192. ksadk/model_proxy/gate.py +68 -0
  193. ksadk/model_proxy/namespace.py +201 -0
  194. ksadk/model_proxy/protocol_proxy.py +22 -0
  195. ksadk/model_proxy/server.py +443 -0
  196. ksadk/model_proxy/transform.py +735 -0
  197. ksadk/openclaw_gateway.py +29 -14
  198. ksadk/runners/adk_runner.py +354 -146
  199. ksadk/runners/base_runner.py +71 -29
  200. ksadk/runners/deepagents_runner.py +0 -1
  201. ksadk/runners/factory.py +18 -5
  202. ksadk/runners/langchain_runner.py +29 -742
  203. ksadk/runners/langgraph_runner.py +417 -97
  204. ksadk/runners/patch_langchain.py +16 -16
  205. ksadk/runners/remote_runner.py +134 -33
  206. ksadk/runners/usage_accumulator.py +1 -0
  207. ksadk/runners/utils/__init__.py +0 -10
  208. ksadk/runners/utils/loader.py +23 -7
  209. ksadk/runtime/__init__.py +67 -0
  210. ksadk/runtime/adapter.py +412 -0
  211. ksadk/runtime/conversation_execution.py +553 -0
  212. ksadk/runtime/executor.py +251 -0
  213. ksadk/runtime/factory.py +156 -0
  214. ksadk/runtime/framework_adapters.py +118 -0
  215. ksadk/runtime/launch.py +48 -0
  216. ksadk/runtime/preprocessing.py +131 -0
  217. ksadk/runtime/runner_adapter.py +1032 -0
  218. ksadk/runtime/runner_loading.py +36 -0
  219. ksadk/runtime_context.py +18 -3
  220. ksadk/runtime_state.py +0 -1
  221. ksadk/sandbox/__init__.py +4 -1
  222. ksadk/sandbox/backends/__init__.py +4 -1
  223. ksadk/sandbox/backends/e2b.py +13 -5
  224. ksadk/sandbox/backends/local_process.py +11 -3
  225. ksadk/sandbox/base.py +10 -15
  226. ksadk/sandbox/factory.py +14 -4
  227. ksadk/sandbox/registry.py +57 -6
  228. ksadk/server/__init__.py +39 -4
  229. ksadk/server/api_models.py +15 -5
  230. ksadk/server/app.py +24 -3928
  231. ksadk/server/composition.py +47 -0
  232. ksadk/server/factory.py +622 -0
  233. ksadk/server/routes/__init__.py +1 -0
  234. ksadk/server/routes/checkpoint_resolution.py +116 -0
  235. ksadk/server/routes/common.py +682 -0
  236. ksadk/server/routes/control.py +331 -0
  237. ksadk/server/routes/dependencies.py +98 -0
  238. ksadk/server/routes/misc.py +425 -0
  239. ksadk/server/routes/models.py +451 -0
  240. ksadk/server/routes/openai_compat.py +229 -0
  241. ksadk/server/routes/projection.py +848 -0
  242. ksadk/server/routes/routers.py +52 -0
  243. ksadk/server/routes/run.py +519 -0
  244. ksadk/server/routes/sessions.py +644 -0
  245. ksadk/server/routes/streaming.py +265 -0
  246. ksadk/server/routes/workspace.py +414 -0
  247. ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-CakCqxEN.js} +1 -1
  248. ksadk/server/static/assets/CodeBlock-CynLknyO.js +9 -0
  249. ksadk/server/static/assets/MathMessageMarkdown-3sQdOysS.js +8 -0
  250. ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +303 -0
  251. ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +1 -0
  252. ksadk/server/static/assets/{arc-BA13sHc9.js → arc-DrgjcKhl.js} +1 -1
  253. ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +1 -0
  254. ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-BXoVRbQ6.js} +1 -1
  255. ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-BnaB3Ywv.js} +1 -1
  256. ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-Dw4weZcp.js} +1 -1
  257. ksadk/server/static/assets/channel-Dt3rQTFI.js +1 -0
  258. ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-ChjpLK7j.js} +1 -1
  259. ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-B9drTgOW.js} +1 -1
  260. ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-CK4ROATy.js} +1 -1
  261. ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B9KtTTgw.js} +1 -1
  262. ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-1O1mki3m.js} +1 -1
  263. ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-B_fH2YuH.js} +1 -1
  264. ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D6rFLaVV.js} +1 -1
  265. ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +1 -0
  266. ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +1 -0
  267. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +1 -0
  268. ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-ChNs_Mdk.js} +1 -1
  269. ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-D0QXg_MQ.js} +1 -1
  270. ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-DBDDKwBQ.js} +1 -1
  271. ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-BkwDOxmO.js} +1 -1
  272. ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Bv8waYvY.js} +1 -1
  273. ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-e1VECDdu.js} +1 -1
  274. ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-Ds9adfRl.js} +1 -1
  275. ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-4N2NMVYg.js} +1 -1
  276. ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-B-jNR6Vn.js} +1 -1
  277. ksadk/server/static/assets/{dist-D57wnGWd.js → dist-B5J2uhNk.js} +1 -1
  278. ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-B5oS1zcj.js} +1 -1
  279. ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BB3-OwTQ.js} +1 -1
  280. ksadk/server/static/assets/{dist-2hInLS_J.js → dist-BIlKoW0k.js} +1 -1
  281. ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-BjOdlDjj.js} +1 -1
  282. ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-C1sz5Eo3.js} +1 -1
  283. ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-CWV4lDr1.js} +1 -1
  284. ksadk/server/static/assets/{dist-D-xOD048.js → dist-CmZHzlwZ.js} +1 -1
  285. ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-D6MpCZtz.js} +1 -1
  286. ksadk/server/static/assets/{dist-DyOkZmze.js → dist-DJN_6Y39.js} +1 -1
  287. ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-DQU9EWw-.js} +1 -1
  288. ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-DWKByxWV.js} +1 -1
  289. ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-Dli7qW-B.js} +1 -1
  290. ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-DsHPdk3W.js} +1 -1
  291. ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-X4TnqwOK.js} +1 -1
  292. ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-_pHPTyZ-.js} +1 -1
  293. ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-fhOuWds5.js} +1 -1
  294. ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-gLnrGsoU.js} +1 -1
  295. ksadk/server/static/assets/{dist-BssVmjIo.js → dist-j6Dxmf_j.js} +1 -1
  296. ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-o2OVmKvt.js} +1 -1
  297. ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-BPItFKH6.js} +1 -1
  298. ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +1 -0
  299. ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-BbYB9w5Y.js} +1 -1
  300. ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-TQXa0KXv.js} +1 -1
  301. ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +1 -0
  302. ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-bKblCnpa.js} +1 -1
  303. ksadk/server/static/assets/index-R52pJJvg.js +177 -0
  304. ksadk/server/static/assets/index-jJr3_955.css +2 -0
  305. ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +1 -0
  306. ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-BGVT7J_i.js} +1 -1
  307. ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-K0OOfVna.js} +1 -1
  308. ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-8LeOJaZp.js} +1 -1
  309. ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-C6uCgZrW.js} +1 -1
  310. ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-CYWseY5E.js} +1 -1
  311. ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-hdBcYzM8.js} +1 -1
  312. ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-BWrDjSZM.js} +2 -2
  313. ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-Bjy_2v4_.js} +1 -1
  314. ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +1 -0
  315. ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +1 -0
  316. ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-GmmqNiVH.js} +1 -1
  317. ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-BmkRbwCg.js} +1 -1
  318. ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +1 -0
  319. ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DSWFqL7c.js} +1 -1
  320. ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-l6iXmU65.js} +1 -1
  321. ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-Cq6UBeQB.js} +1 -1
  322. ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-qzTQpg3Y.js} +1 -1
  323. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +1 -0
  324. ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-DEz24vV0.js} +1 -1
  325. ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +1 -0
  326. ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +1 -0
  327. ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-CMCixki2.js} +1 -1
  328. ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +1 -0
  329. ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-CVzB8F9K.js} +1 -1
  330. ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-BFBqBLc1.js} +1 -1
  331. ksadk/server/static/index.html +2 -2
  332. ksadk/server/terminal_sessions.py +111 -58
  333. ksadk/sessions/__init__.py +69 -19
  334. ksadk/sessions/base.py +31 -11
  335. ksadk/sessions/continuity.py +2 -3
  336. ksadk/sessions/in_memory.py +46 -2
  337. ksadk/sessions/local_service.py +148 -17
  338. ksadk/sessions/postgres_service.py +143 -25
  339. ksadk/sessions/resilient.py +36 -8
  340. ksadk/skills/models.py +17 -5
  341. ksadk/skills/package_store.py +5 -2
  342. ksadk/skills/runtime/agent.py +20 -5
  343. ksadk/skills/runtime/artifacts.py +1 -5
  344. ksadk/skills/runtime/backends/e2b.py +10 -4
  345. ksadk/skills/runtime/backends/local.py +15 -3
  346. ksadk/skills/runtime/base.py +1 -2
  347. ksadk/skills/runtime/executor.py +10 -3
  348. ksadk/skills/runtime/factory.py +4 -2
  349. ksadk/skills/runtime/loader.py +1 -2
  350. ksadk/skills/runtime/registry.py +15 -10
  351. ksadk/skills/runtime/request.py +3 -1
  352. ksadk/skills/service_client.py +47 -16
  353. ksadk/skills/tool_defs.py +15 -10
  354. ksadk/studio/__init__.py +5 -0
  355. ksadk/studio/agent_avatar_assets.py +120 -0
  356. ksadk/studio/agent_lifecycle.py +51 -0
  357. ksadk/studio/api.py +1046 -0
  358. ksadk/studio/api_catalog_routes.py +324 -0
  359. ksadk/studio/api_contracts.py +177 -0
  360. ksadk/studio/api_helpers.py +132 -0
  361. ksadk/studio/authoring.py +524 -0
  362. ksadk/studio/authoring_coordinator.py +285 -0
  363. ksadk/studio/builder.py +320 -0
  364. ksadk/studio/capabilities.py +351 -0
  365. ksadk/studio/cloud.py +278 -0
  366. ksadk/studio/codex_agent_service.py +583 -0
  367. ksadk/studio/codex_builder.py +324 -0
  368. ksadk/studio/codex_manifest.py +278 -0
  369. ksadk/studio/codex_run.py +352 -0
  370. ksadk/studio/compiler.py +189 -0
  371. ksadk/studio/contracts.py +644 -0
  372. ksadk/studio/errors.py +47 -0
  373. ksadk/studio/evaluation.py +192 -0
  374. ksadk/studio/event_store.py +284 -0
  375. ksadk/studio/framework_run.py +114 -0
  376. ksadk/studio/identifiers.py +33 -0
  377. ksadk/studio/mcp_runtime.py +229 -0
  378. ksadk/studio/model_client.py +543 -0
  379. ksadk/studio/model_profile_service.py +214 -0
  380. ksadk/studio/operations.py +243 -0
  381. ksadk/studio/otel_trace.py +754 -0
  382. ksadk/studio/pagination.py +182 -0
  383. ksadk/studio/python_tool_inspection.py +183 -0
  384. ksadk/studio/repository.py +306 -0
  385. ksadk/studio/resource_catalog.py +1217 -0
  386. ksadk/studio/run_service.py +707 -0
  387. ksadk/studio/runtime_catalog.py +74 -0
  388. ksadk/studio/runtime_source.py +339 -0
  389. ksadk/studio/service.py +1141 -0
  390. ksadk/studio/shared_web.py +994 -0
  391. ksadk/studio/skill_discovery.py +628 -0
  392. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
  393. ksadk/studio/static/assets/index-CaEN0eTR.css +1 -0
  394. ksadk/studio/static/assets/index-DI2eY_NH.js +252 -0
  395. ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
  396. ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  397. ksadk/studio/static/index.html +15 -0
  398. ksadk/studio/templates.py +630 -0
  399. ksadk/studio/validator.py +246 -0
  400. ksadk/studio/workspace.py +137 -0
  401. ksadk/terminal_exec_policy.py +3 -4
  402. ksadk/tools/gateway.py +101 -15
  403. ksadk/tools/result_budget.py +12 -4
  404. ksadk/toolsets/__init__.py +161 -37
  405. ksadk/toolsets/a2a.py +426 -0
  406. ksadk/toolsets/platform.py +21 -5
  407. ksadk/toolsets/sandbox.py +82 -16
  408. ksadk/toolsets/skills.py +200 -39
  409. ksadk/toolsets/web.py +123 -26
  410. ksadk/toolsets/workspace.py +212 -101
  411. ksadk/tracing/__init__.py +19 -21
  412. ksadk/tracing/exporters/inmemory_exporter.py +62 -51
  413. ksadk/tracing/setup.py +135 -506
  414. ksadk/tracing/span_utils.py +0 -41
  415. ksadk/tui/loop.py +78 -30
  416. ksadk/tui/stream_render.py +1 -0
  417. ksadk/ui_config.py +5 -3
  418. ksadk/version.py +1 -1
  419. ksadk_runtime_common/memory_backend/registry.py +56 -56
  420. ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
  421. ksadk_runtime_common/workspace_files/router.py +8 -2
  422. agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
  423. ksadk/a2a/card_builder.py +0 -64
  424. ksadk/a2a/client.py +0 -309
  425. ksadk/runners/utils/langfuse.py +0 -230
  426. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
  427. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
  428. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
  429. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
  430. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
  431. ksadk/server/static/assets/channel-CTuydARX.js +0 -1
  432. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
  433. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
  434. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
  435. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
  436. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
  437. ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
  438. ksadk/server/static/assets/index-DAURbCsP.css +0 -1
  439. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
  440. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
  441. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
  442. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
  443. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
  444. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
  445. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
  446. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
  447. ksadk/tracing/exporters/langfuse_exporter.py +0 -445
  448. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/entry_points.txt +0 -0
  449. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/licenses/LICENSE +0 -0
  450. {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,660 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ from typing import Any, Mapping, Sequence
6
+
7
+ from ksadk.conversations.reasoning_markup import strip_reasoning_markup
8
+ from ksadk.conversations.runtime_constants import (
9
+ PROMPT_TOO_LONG_MARKERS,
10
+ logger,
11
+ )
12
+ from ksadk.conversations.runtime_observability import _extract_deferred_tool_names
13
+ from ksadk.conversations.runtime_payloads import PreparedConversationTurn
14
+ from ksadk.conversations.runtime_resume import _is_checkpoint_resume_input
15
+ from ksadk.knowledge_base.service import KnowledgeBaseService
16
+ from ksadk.memory.service import LongTermMemoryService
17
+ from ksadk.runtime_context import (
18
+ PlatformInvocationContext,
19
+ )
20
+
21
+
22
+ def _is_prompt_too_long_error(exc: Exception) -> bool:
23
+ """尽量用宽松规则识别 PTL,兼容不同 runtime/模型返回格式。"""
24
+ lowered = str(exc or "").lower()
25
+ return any(marker in lowered for marker in PROMPT_TOO_LONG_MARKERS)
26
+
27
+
28
+ def _runner_name(runner: Any) -> str:
29
+ return str(getattr(getattr(runner, "detection_result", None), "name", "assistant"))
30
+
31
+
32
+ def _runner_type_name(runner: Any) -> str:
33
+ runner_type = getattr(getattr(runner, "detection_result", None), "type", None)
34
+ runner_value = getattr(runner_type, "value", runner_type)
35
+ normalized = str(runner_value or "").strip()
36
+ if normalized:
37
+ return normalized
38
+ return str(runner.__class__.__name__).lower()
39
+
40
+
41
+ def _env_flag(name: str, default: bool = True) -> bool:
42
+ raw = os.getenv(name)
43
+ if raw is None:
44
+ return default
45
+ normalized = str(raw).strip().lower()
46
+ if not normalized:
47
+ return default
48
+ return normalized not in {"0", "false", "no", "off"}
49
+
50
+
51
+ def _ltm_auto_save_enabled() -> bool:
52
+ backend = str(os.getenv("KSADK_LTM_BACKEND") or "").strip().lower()
53
+ namespace = str(os.getenv("KSADK_LTM_NAMESPACE") or "").strip()
54
+ if not backend and not namespace:
55
+ return False
56
+ default = backend == "sdk" and bool(namespace)
57
+ return _env_flag("KSADK_LTM_AUTO_SAVE", default)
58
+
59
+
60
+ def _ambient_policy(prefix: str, default: str = "on_demand") -> str:
61
+ if not _env_flag(f"{prefix}_AMBIENT_ENABLED", True):
62
+ return "disabled"
63
+
64
+ raw = str(os.getenv(f"{prefix}_AMBIENT_POLICY", default) or "").strip().lower()
65
+ if raw in {"", "on_demand", "ondemand", "heuristic", "auto"}:
66
+ return "on_demand"
67
+ if raw in {"always", "eager"}:
68
+ return "always"
69
+ if raw in {"disabled", "off", "false", "0"}:
70
+ return "disabled"
71
+ return default
72
+
73
+
74
+ def _normalize_ambient_query(text: str) -> str:
75
+ return " ".join(str(text or "").strip().lower().split())
76
+
77
+
78
+ def _contains_any_fragment(text: str, fragments: Sequence[str]) -> bool:
79
+ return any(fragment in text for fragment in fragments)
80
+
81
+
82
+ def _ambient_context_has_error(context: Any) -> bool:
83
+ if not isinstance(context, dict):
84
+ return True
85
+
86
+ formatted_text = str(context.get("formatted_text") or "").strip()
87
+ if not formatted_text:
88
+ return True
89
+
90
+ failure_prefixes = (
91
+ "知识库检索失败",
92
+ "长期记忆检索失败",
93
+ )
94
+ return formatted_text.startswith(failure_prefixes)
95
+
96
+
97
+ def _is_chitchat_query(text: str) -> bool:
98
+ normalized = _normalize_ambient_query(text)
99
+ if not normalized:
100
+ return True
101
+
102
+ exact_matches = {
103
+ "hi",
104
+ "hello",
105
+ "hey",
106
+ "你好",
107
+ "您好",
108
+ "嗨",
109
+ "在吗",
110
+ "收到",
111
+ "好的",
112
+ "ok",
113
+ "okay",
114
+ "thanks",
115
+ "thank you",
116
+ "谢谢",
117
+ "测试",
118
+ "test",
119
+ "ping",
120
+ }
121
+ if normalized in exact_matches:
122
+ return True
123
+
124
+ chatter_fragments = (
125
+ "介绍一下你自己",
126
+ "介绍你自己",
127
+ "你是谁",
128
+ "你能做什么",
129
+ "what can you do",
130
+ "who are you",
131
+ "introduce yourself",
132
+ "一句测试",
133
+ )
134
+ return any(fragment in normalized for fragment in chatter_fragments)
135
+
136
+
137
+ def _should_load_kb_ambient_context(user_input: str) -> bool:
138
+ normalized = _normalize_ambient_query(user_input)
139
+ if not normalized or _is_chitchat_query(normalized):
140
+ return False
141
+
142
+ kb_fragments = (
143
+ "知识库",
144
+ "文档",
145
+ "手册",
146
+ "说明",
147
+ "wiki",
148
+ "资料",
149
+ "教程",
150
+ "api",
151
+ "接口",
152
+ "参数",
153
+ "配置",
154
+ "规格",
155
+ "机型",
156
+ "实例",
157
+ "部署",
158
+ "步骤",
159
+ "区别",
160
+ "差异",
161
+ "原理",
162
+ "架构",
163
+ "能力",
164
+ "限制",
165
+ "最佳实践",
166
+ "价格",
167
+ "套餐",
168
+ "支持",
169
+ "有哪些",
170
+ "什么是",
171
+ "为什么",
172
+ "怎么",
173
+ "如何",
174
+ "查询",
175
+ "查一下",
176
+ "列一下",
177
+ "介绍一下",
178
+ "总结",
179
+ "概述",
180
+ "解释",
181
+ "说明一下",
182
+ "对比",
183
+ "比较",
184
+ "what",
185
+ "how",
186
+ "why",
187
+ "which",
188
+ "list",
189
+ "show me",
190
+ "tell me",
191
+ "summarize",
192
+ "summary",
193
+ "explain",
194
+ "difference",
195
+ "steps",
196
+ "deployment",
197
+ "lookup",
198
+ "look up",
199
+ "search",
200
+ "compare",
201
+ )
202
+ if _contains_any_fragment(normalized, kb_fragments):
203
+ return True
204
+
205
+ query_verbs = (
206
+ "查",
207
+ "查一下",
208
+ "查询",
209
+ "列出",
210
+ "列一下",
211
+ "总结",
212
+ "概述",
213
+ "解释",
214
+ "说明",
215
+ "介绍",
216
+ "对比",
217
+ "比较",
218
+ "看看",
219
+ "告诉我",
220
+ "what",
221
+ "how",
222
+ "why",
223
+ "which",
224
+ "list",
225
+ "show",
226
+ "tell",
227
+ "summarize",
228
+ "explain",
229
+ "compare",
230
+ )
231
+ kb_subjects = (
232
+ "知识库",
233
+ "文档",
234
+ "手册",
235
+ "教程",
236
+ "wiki",
237
+ "部署",
238
+ "步骤",
239
+ "api",
240
+ "接口",
241
+ "参数",
242
+ "配置",
243
+ "规格",
244
+ "机型",
245
+ "实例",
246
+ "价格",
247
+ "套餐",
248
+ "支持",
249
+ "区别",
250
+ "差异",
251
+ "原理",
252
+ "架构",
253
+ "能力",
254
+ "限制",
255
+ )
256
+ return _contains_any_fragment(normalized, query_verbs) and _contains_any_fragment(
257
+ normalized, kb_subjects
258
+ )
259
+
260
+
261
+ def _should_load_memory_ambient_context(user_input: str) -> bool:
262
+ normalized = _normalize_ambient_query(user_input)
263
+ if not normalized or _is_chitchat_query(normalized):
264
+ return False
265
+
266
+ explicit_memory_fragments = (
267
+ "记得",
268
+ "记住",
269
+ "记忆",
270
+ "回忆",
271
+ "历史",
272
+ "偏好",
273
+ "习惯",
274
+ "还记得",
275
+ "记得我",
276
+ "记住这个",
277
+ "remember",
278
+ "memory",
279
+ "recall",
280
+ "history",
281
+ "preference",
282
+ )
283
+ profile_fragments = (
284
+ "我的名字",
285
+ "我叫什么",
286
+ "你知道我的名字",
287
+ "我的风格",
288
+ "按我的风格",
289
+ "按照我的风格",
290
+ "我的偏好",
291
+ "我的习惯",
292
+ "我的背景",
293
+ "关于我的",
294
+ "我喜欢",
295
+ "我不喜欢",
296
+ "my name",
297
+ "my style",
298
+ "my preference",
299
+ "about me",
300
+ )
301
+ short_term_fragments = (
302
+ "前面的回答",
303
+ "前面的内容",
304
+ "上面的回答",
305
+ "上面的内容",
306
+ "刚才的回答",
307
+ "刚刚的回答",
308
+ "上一条",
309
+ "上一轮",
310
+ "继续刚才",
311
+ "继续上面",
312
+ "翻译成英文",
313
+ "翻译成中文",
314
+ )
315
+ temporal_fragments = ("上次", "之前", "以前", "earlier", "last time", "previous")
316
+ speech_fragments = ("聊过", "说过", "提过", "告诉过", "mentioned", "told")
317
+
318
+ if _contains_any_fragment(normalized, short_term_fragments) and not _contains_any_fragment(
319
+ normalized, profile_fragments
320
+ ):
321
+ return False
322
+
323
+ if _contains_any_fragment(normalized, explicit_memory_fragments) or _contains_any_fragment(
324
+ normalized, profile_fragments
325
+ ):
326
+ return True
327
+
328
+ return _contains_any_fragment(normalized, temporal_fragments) and _contains_any_fragment(
329
+ normalized, speech_fragments
330
+ )
331
+
332
+
333
+ def _should_use_platform_ambient_context(runner: Any) -> bool:
334
+ detection_type = getattr(getattr(runner, "detection_result", None), "type", None)
335
+ runner_type = str(getattr(detection_type, "value", detection_type) or "").strip().lower()
336
+ if runner_type:
337
+ return runner_type != "adk"
338
+
339
+ class_name = runner.__class__.__name__.lower()
340
+ module_name = getattr(runner.__class__, "__module__", "").lower()
341
+ return class_name != "adkrunner" and "google_adk" not in module_name
342
+
343
+
344
+ def _build_runner_ambient_contexts(
345
+ *,
346
+ runner: Any,
347
+ user_id: str,
348
+ user_input: str,
349
+ ) -> dict[str, Any]:
350
+ contexts: dict[str, Any] = {
351
+ "kb_context": None,
352
+ "memory_context": None,
353
+ }
354
+ normalized_input = str(user_input or "").strip()
355
+ if not normalized_input or not _should_use_platform_ambient_context(runner):
356
+ return contexts
357
+
358
+ kb_policy = _ambient_policy("KSADK_KB", "on_demand")
359
+ if (
360
+ kb_policy == "always"
361
+ or (kb_policy == "on_demand" and _should_load_kb_ambient_context(normalized_input))
362
+ ) and KnowledgeBaseService.is_configured():
363
+ try:
364
+ kb_context = KnowledgeBaseService.from_env().build_context(normalized_input)
365
+ if not _ambient_context_has_error(kb_context):
366
+ contexts["kb_context"] = kb_context
367
+ except Exception as exc:
368
+ logger.warning("Failed to build ambient knowledge context: %s", exc)
369
+
370
+ ltm_policy = _ambient_policy("KSADK_LTM", "on_demand")
371
+ if (
372
+ ltm_policy == "always"
373
+ or (ltm_policy == "on_demand" and _should_load_memory_ambient_context(normalized_input))
374
+ ) and LongTermMemoryService.is_configured():
375
+ try:
376
+ memory_context = LongTermMemoryService.from_env().build_context(
377
+ user_id=user_id,
378
+ query=normalized_input,
379
+ )
380
+ if not _ambient_context_has_error(memory_context):
381
+ contexts["memory_context"] = memory_context
382
+ except Exception as exc:
383
+ logger.warning("Failed to build ambient memory context: %s", exc)
384
+
385
+ return contexts
386
+
387
+
388
+ def _build_runner_request_payload(
389
+ *,
390
+ prepared: PreparedConversationTurn,
391
+ model: str | None,
392
+ runtime_context: PlatformInvocationContext,
393
+ runner: Any | None = None,
394
+ ) -> dict[str, Any]:
395
+ payload = {
396
+ "session_id": prepared.session_id,
397
+ "input": prepared.user_input,
398
+ "history": prepared.history,
399
+ "input_content": prepared.input_content,
400
+ "input_messages": prepared.input_messages,
401
+ "input_parts": prepared.user_parts,
402
+ "attachments": prepared.attachments,
403
+ "attachment_results": prepared.attachment_results,
404
+ "current_attachments": prepared.current_attachments,
405
+ "current_attachment_results": prepared.current_attachment_results,
406
+ "has_current_files": prepared.has_current_files,
407
+ "model": model,
408
+ "model_metadata": prepared.model_metadata,
409
+ "model_options": prepared.model_options,
410
+ "platform_context": runtime_context.to_payload(),
411
+ "kb_context": runtime_context.kb_context,
412
+ "memory_context": runtime_context.memory_context,
413
+ "invocation_id": prepared.invocation_id,
414
+ }
415
+ if prepared.request_metadata:
416
+ # Keep endpoint-level controls available to an application entrypoint
417
+ # (for example, its conversation approval profile) without leaking
418
+ # caller public metadata into the agent payload.
419
+ payload["request_metadata"] = dict(prepared.request_metadata)
420
+ if prepared.instructions:
421
+ payload["instructions"] = prepared.instructions
422
+ if prepared.resume_input is not None:
423
+ if _is_checkpoint_resume_input(prepared.resume_input):
424
+ payload["input"] = prepared.resume_input
425
+ payload["checkpoint_resume"] = True
426
+ payload["run_id"] = str(prepared.resume_input.get("run_id") or "")
427
+ payload["checkpoint_id"] = str(prepared.resume_input.get("checkpoint_id") or "")
428
+ payload["framework_ref"] = dict(prepared.resume_input.get("framework_ref") or {})
429
+ payload["metadata"] = dict(prepared.resume_input.get("metadata") or {})
430
+ payload["checkpoint_metadata"] = dict(
431
+ prepared.resume_input.get("checkpoint_metadata") or {}
432
+ )
433
+ else:
434
+ resume_input = dict(prepared.resume_input)
435
+ gateway_approval_resume = bool(
436
+ resume_input.pop("_ksadk_gateway_approval_resume", False)
437
+ )
438
+ if gateway_approval_resume and bool(
439
+ getattr(runner, "supports_gateway_approval_semantic_resume", False)
440
+ ):
441
+ resume_input["_ksadk_gateway_approval_resume"] = True
442
+ payload["input"] = resume_input
443
+ payload["resume"] = True
444
+ previous_response_id = prepared.request_metadata.get("previous_response_id")
445
+ if previous_response_id:
446
+ payload["previous_response_id"] = str(previous_response_id)
447
+ conversation = prepared.request_metadata.get("conversation")
448
+ if conversation:
449
+ payload["conversation"] = conversation
450
+ if prepared.request_metadata.get("responses_conversation"):
451
+ payload["responses_conversation"] = True
452
+ if getattr(runner, "api_format", "") == "responses" and prepared.responses_history:
453
+ payload["responses_history"] = list(prepared.responses_history)
454
+ deferred_tool_names = _extract_deferred_tool_names(prepared.request_metadata)
455
+ if deferred_tool_names:
456
+ payload["deferred_tool_names"] = deferred_tool_names
457
+ return payload
458
+
459
+
460
+ def _inject_runner_deferred_tools_for_request(
461
+ runner: Any, prepared: PreparedConversationTurn
462
+ ) -> None:
463
+ deferred_tool_names = _extract_deferred_tool_names(prepared.request_metadata)
464
+ if not deferred_tool_names:
465
+ return
466
+ inject = getattr(runner, "inject_deferred_tools_for_request", None)
467
+ if not callable(inject):
468
+ return
469
+ try:
470
+ inject(deferred_tool_names)
471
+ except Exception as exc:
472
+ logger.warning("Failed to inject deferred tools into runner: %s", exc)
473
+
474
+
475
+ def _attachment_summary_for_memory(
476
+ attachments: Sequence[Mapping[str, Any]],
477
+ attachment_results: Sequence[Mapping[str, Any]],
478
+ ) -> list[dict[str, Any]]:
479
+ summaries: list[dict[str, Any]] = []
480
+ for item in attachment_results:
481
+ if not isinstance(item, Mapping):
482
+ continue
483
+ summary = {
484
+ "kind": str(item.get("kind") or "file"),
485
+ "display_name": str(
486
+ item.get("display_name") or item.get("filename") or "uploaded_file"
487
+ ),
488
+ "mime_type": str(item.get("mime_type") or "application/octet-stream"),
489
+ }
490
+ summaries.append(summary)
491
+
492
+ if summaries:
493
+ return summaries
494
+
495
+ for item in attachments:
496
+ if not isinstance(item, Mapping):
497
+ continue
498
+ mime_type = str(item.get("mime_type") or "application/octet-stream")
499
+ display_name = str(item.get("display_name") or item.get("filename") or "uploaded_file")
500
+ kind = "image" if mime_type.startswith("image/") else "file"
501
+ summaries.append(
502
+ {
503
+ "kind": kind,
504
+ "display_name": display_name,
505
+ "mime_type": mime_type,
506
+ }
507
+ )
508
+ return summaries
509
+
510
+
511
+ def _memory_turn_event_strings(
512
+ *,
513
+ prepared: PreparedConversationTurn,
514
+ output_text: str,
515
+ metadata: Mapping[str, Any],
516
+ ) -> list[str]:
517
+ event_strings: list[str] = []
518
+ user_text = _input_text_for_memory(prepared)
519
+ if user_text:
520
+ user_metadata = dict(metadata)
521
+ attachment_summary = _attachment_summary_for_memory(
522
+ prepared.current_attachments,
523
+ prepared.current_attachment_results,
524
+ )
525
+ if attachment_summary:
526
+ user_metadata["attachments"] = attachment_summary
527
+ event_strings.append(
528
+ json.dumps(
529
+ {
530
+ "role": "user",
531
+ "parts": [{"text": user_text}],
532
+ "metadata": user_metadata,
533
+ },
534
+ ensure_ascii=False,
535
+ )
536
+ )
537
+
538
+ assistant_text = strip_reasoning_markup(str(output_text or "")).strip()
539
+ if assistant_text:
540
+ event_strings.append(
541
+ json.dumps(
542
+ {
543
+ "role": "assistant",
544
+ "parts": [{"text": assistant_text}],
545
+ "metadata": dict(metadata),
546
+ },
547
+ ensure_ascii=False,
548
+ )
549
+ )
550
+ return event_strings
551
+
552
+
553
+ def _input_text_for_memory(prepared: PreparedConversationTurn) -> str:
554
+ text_parts: list[str] = []
555
+ for item in prepared.input_content:
556
+ if isinstance(item, Mapping) and item.get("type") == "input_text":
557
+ text = str(item.get("text") or "").strip()
558
+ if text:
559
+ text_parts.append(text)
560
+ if text_parts:
561
+ return "\n".join(text_parts).strip()
562
+ return str(prepared.user_input or prepared.user_display_input or "").strip()
563
+
564
+
565
+ async def _auto_save_ltm_turn(
566
+ *,
567
+ agent_id: str,
568
+ user_id: str,
569
+ prepared: PreparedConversationTurn,
570
+ output_text: str,
571
+ runner_type: str,
572
+ model: str | None,
573
+ ) -> None:
574
+ if prepared.resume_input is not None or not _ltm_auto_save_enabled():
575
+ return
576
+
577
+ metadata: dict[str, Any] = {
578
+ "agent_id": str(agent_id or ""),
579
+ "session_id": prepared.session_id,
580
+ "invocation_id": prepared.invocation_id,
581
+ "runner_type": runner_type,
582
+ }
583
+ if model:
584
+ metadata["model"] = model
585
+
586
+ platform_context = prepared.request_metadata.get("platform_context")
587
+ if isinstance(platform_context, Mapping):
588
+ metadata["agent_id"] = str(platform_context.get("agent_id") or metadata["agent_id"])
589
+
590
+ if not metadata["agent_id"]:
591
+ metadata["agent_id"] = str(os.getenv("KSADK_LTM_AGENT_ID") or "")
592
+
593
+ event_strings = _memory_turn_event_strings(
594
+ prepared=prepared,
595
+ output_text=output_text,
596
+ metadata=metadata,
597
+ )
598
+ if not event_strings:
599
+ return
600
+
601
+ try:
602
+ service = LongTermMemoryService.from_env()
603
+ service.save_event_strings(
604
+ user_id=user_id,
605
+ event_strings=event_strings,
606
+ metadata=metadata,
607
+ )
608
+ except Exception as exc:
609
+ logger.warning("Failed to auto-save conversation turn to long-term memory: %s", exc)
610
+
611
+
612
+ def _merge_request_history_with_session_history(
613
+ request_history: Sequence[dict[str, str]],
614
+ session_history: Sequence[dict[str, str]],
615
+ ) -> list[dict[str, str]]:
616
+ if not request_history:
617
+ return list(session_history)
618
+ if not session_history:
619
+ return list(request_history)
620
+
621
+ normalized_request = [
622
+ {
623
+ "role": str(item.get("role") or ""),
624
+ "content": str(item.get("content") or "").strip(),
625
+ }
626
+ for item in request_history
627
+ ]
628
+ normalized_session = [
629
+ {
630
+ "role": str(item.get("role") or ""),
631
+ "content": str(item.get("content") or "").strip(),
632
+ }
633
+ for item in session_history
634
+ ]
635
+ prefix_len = min(len(normalized_request), len(normalized_session))
636
+ if normalized_request[:prefix_len] == normalized_session[:prefix_len]:
637
+ return [*list(request_history), *list(session_history)[prefix_len:]]
638
+ return [*list(request_history), *list(session_history)]
639
+
640
+
641
+ def _merge_responses_history_with_session_history(
642
+ request_history: Sequence[dict[str, Any]],
643
+ session_history: Sequence[dict[str, Any]],
644
+ ) -> list[dict[str, Any]]:
645
+ """Merge request-provided Responses items with the session projection."""
646
+ if not request_history:
647
+ return [dict(item) for item in session_history]
648
+ if not session_history:
649
+ return [dict(item) for item in request_history]
650
+
651
+ prefix_len = min(len(request_history), len(session_history))
652
+ if list(request_history[:prefix_len]) == list(session_history[:prefix_len]):
653
+ return [
654
+ *[dict(item) for item in request_history],
655
+ *[dict(item) for item in session_history[prefix_len:]],
656
+ ]
657
+ return [
658
+ *[dict(item) for item in request_history],
659
+ *[dict(item) for item in session_history],
660
+ ]