agentengine-sdk-python 0.6.4__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. agentengine_sdk_python-0.7.0.dist-info/METADATA +181 -0
  2. agentengine_sdk_python-0.7.0.dist-info/RECORD +482 -0
  3. {agentengine_sdk_python-0.6.4.dist-info → agentengine_sdk_python-0.7.0.dist-info}/WHEEL +1 -1
  4. agentengine_sdk_python-0.7.0.dist-info/entry_points.txt +3 -0
  5. agentengine_sdk_python-0.7.0.dist-info/licenses/LICENSE +175 -0
  6. agentengine_sdk_python-0.7.0.dist-info/top_level.txt +2 -0
  7. ksadk/__init__.py +13 -0
  8. ksadk/__main__.py +4 -0
  9. ksadk/a2a/__init__.py +15 -0
  10. ksadk/a2a/card_builder.py +64 -0
  11. ksadk/a2a/client.py +309 -0
  12. ksadk/a2a/executor.py +201 -0
  13. ksadk/a2a/server.py +79 -0
  14. ksadk/agents/__init__.py +20 -0
  15. ksadk/agents/base.py +370 -0
  16. ksadk/agents/context.py +38 -0
  17. ksadk/agents/event.py +35 -0
  18. ksadk/agents/loop_agent.py +71 -0
  19. ksadk/agents/parallel_agent.py +109 -0
  20. ksadk/agents/runner_adapter.py +24 -0
  21. ksadk/agents/sequential_agent.py +34 -0
  22. ksadk/api/__init__.py +3 -0
  23. ksadk/api/client.py +2246 -0
  24. ksadk/builders/__init__.py +20 -0
  25. ksadk/builders/base.py +66 -0
  26. ksadk/builders/code_builder.py +1990 -0
  27. ksadk/builders/container_builder.py +786 -0
  28. ksadk/builders/framework_requirements.py +59 -0
  29. ksadk/builders/ks3_uploader.py +389 -0
  30. ksadk/builders/mcp_builder.py +476 -0
  31. ksadk/builders/requirements_utils.py +75 -0
  32. ksadk/cli/__init__.py +531 -0
  33. ksadk/cli/__main__.py +4 -0
  34. ksadk/cli/agent_ref.py +204 -0
  35. ksadk/cli/cmd_a2a.py +167 -0
  36. ksadk/cli/cmd_agent.py +201 -0
  37. ksadk/cli/cmd_build.py +270 -0
  38. ksadk/cli/cmd_completion.py +304 -0
  39. ksadk/cli/cmd_config.py +758 -0
  40. ksadk/cli/cmd_create.py +2304 -0
  41. ksadk/cli/cmd_dashboard.py +900 -0
  42. ksadk/cli/cmd_deploy.py +704 -0
  43. ksadk/cli/cmd_destroy.py +345 -0
  44. ksadk/cli/cmd_files.py +1227 -0
  45. ksadk/cli/cmd_hermes.py +1263 -0
  46. ksadk/cli/cmd_invoke.py +1503 -0
  47. ksadk/cli/cmd_launch.py +564 -0
  48. ksadk/cli/cmd_mcp.py +1179 -0
  49. ksadk/cli/cmd_model.py +302 -0
  50. ksadk/cli/cmd_openclaw.py +3922 -0
  51. ksadk/cli/cmd_run.py +239 -0
  52. ksadk/cli/cmd_status.py +588 -0
  53. ksadk/cli/cmd_version.py +522 -0
  54. ksadk/cli/cmd_web.py +288 -0
  55. ksadk/cli/deploy_utils.py +87 -0
  56. ksadk/cli/dry_run.py +214 -0
  57. ksadk/cli/env_options.py +82 -0
  58. ksadk/cli/error_utils.py +525 -0
  59. ksadk/cli/global_options.py +31 -0
  60. ksadk/cli/local_runtime.py +97 -0
  61. ksadk/cli/model_catalog.py +136 -0
  62. ksadk/cli/network_options.py +412 -0
  63. ksadk/cli/resource_common.py +621 -0
  64. ksadk/cli/storage.py +84 -0
  65. ksadk/cli/ui.py +431 -0
  66. ksadk/cli/workflow_common.py +552 -0
  67. ksadk/common/__init__.py +14 -0
  68. ksadk/common/aicp_env.py +128 -0
  69. ksadk/common/auth.py +190 -0
  70. ksadk/common/constants.py +84 -0
  71. ksadk/common/llm_utils.py +61 -0
  72. ksadk/configs/__init__.py +61 -0
  73. ksadk/configs/env_registry.py +343 -0
  74. ksadk/configs/global_config.py +200 -0
  75. ksadk/configs/settings.py +706 -0
  76. ksadk/conversations/__init__.py +95 -0
  77. ksadk/conversations/attachment_storage.py +379 -0
  78. ksadk/conversations/attachments.py +774 -0
  79. ksadk/conversations/compaction_pipeline.py +387 -0
  80. ksadk/conversations/compaction_prompt.py +128 -0
  81. ksadk/conversations/context.py +303 -0
  82. ksadk/conversations/message_projection.py +269 -0
  83. ksadk/conversations/model_context.py +370 -0
  84. ksadk/conversations/model_options.py +136 -0
  85. ksadk/conversations/normalize.py +446 -0
  86. ksadk/conversations/reasoning_markup.py +91 -0
  87. ksadk/conversations/run_kinds.py +61 -0
  88. ksadk/conversations/run_status.py +53 -0
  89. ksadk/conversations/runtime.py +5276 -0
  90. ksadk/conversations/semantic_summary.py +359 -0
  91. ksadk/conversations/session_title.py +254 -0
  92. ksadk/deployment/__init__.py +83 -0
  93. ksadk/deployment/agent_access.py +226 -0
  94. ksadk/deployment/base.py +229 -0
  95. ksadk/deployment/manager.py +332 -0
  96. ksadk/deployment/providers/__init__.py +10 -0
  97. ksadk/deployment/providers/serverless.py +1115 -0
  98. ksadk/deployment/registry.py +120 -0
  99. ksadk/deployment/state.py +78 -0
  100. ksadk/deployment/ui_config.py +21 -0
  101. ksadk/detection/__init__.py +7 -0
  102. ksadk/detection/detector.py +431 -0
  103. ksadk/detection/mcp_detector.py +250 -0
  104. ksadk/hermes_terminal.py +467 -0
  105. ksadk/identity/__init__.py +17 -0
  106. ksadk/identity/resolver.py +385 -0
  107. ksadk/knowledge_base/__init__.py +62 -0
  108. ksadk/knowledge_base/adk_tool.py +47 -0
  109. ksadk/knowledge_base/client.py +297 -0
  110. ksadk/knowledge_base/langchain_tool.py +55 -0
  111. ksadk/knowledge_base/service.py +66 -0
  112. ksadk/knowledge_base/tool.py +50 -0
  113. ksadk/markdown.py +169 -0
  114. ksadk/mcp_runtime/__init__.py +231 -0
  115. ksadk/memory/__init__.py +57 -0
  116. ksadk/memory/adk/__init__.py +51 -0
  117. ksadk/memory/adk/backends/__init__.py +5 -0
  118. ksadk/memory/adk/backends/base_ltm_backend.py +52 -0
  119. ksadk/memory/adk/backends/http_ltm_backend.py +183 -0
  120. ksadk/memory/adk/backends/inmemory_ltm_backend.py +96 -0
  121. ksadk/memory/adk/backends/sdk_ltm_backend.py +456 -0
  122. ksadk/memory/adk/long_term_memory.py +273 -0
  123. ksadk/memory/adk/resilient_session_service.py +268 -0
  124. ksadk/memory/adk/short_term_memory.py +304 -0
  125. ksadk/memory/adk_tool.py +31 -0
  126. ksadk/memory/backends/__init__.py +6 -0
  127. ksadk/memory/backends/base.py +103 -0
  128. ksadk/memory/backends/memory.py +112 -0
  129. ksadk/memory/backends/redis.py +146 -0
  130. ksadk/memory/langchain_tool.py +39 -0
  131. ksadk/memory/ltm_backend_factory.py +24 -0
  132. ksadk/memory/manager.py +215 -0
  133. ksadk/memory/service.py +172 -0
  134. ksadk/memory/tool.py +96 -0
  135. ksadk/model_policy.py +223 -0
  136. ksadk/openclaw_gateway.py +378 -0
  137. ksadk/runners/__init__.py +8 -0
  138. ksadk/runners/adk_runner.py +1994 -0
  139. ksadk/runners/base_runner.py +305 -0
  140. ksadk/runners/deepagents_runner.py +13 -0
  141. ksadk/runners/factory.py +73 -0
  142. ksadk/runners/langchain_runner.py +751 -0
  143. ksadk/runners/langgraph_runner.py +985 -0
  144. ksadk/runners/patch_langchain.py +187 -0
  145. ksadk/runners/remote_runner.py +792 -0
  146. ksadk/runners/usage_accumulator.py +38 -0
  147. ksadk/runners/utils/__init__.py +19 -0
  148. ksadk/runners/utils/langfuse.py +230 -0
  149. ksadk/runners/utils/loader.py +62 -0
  150. ksadk/runtime_context.py +166 -0
  151. ksadk/runtime_state.py +25 -0
  152. ksadk/sandbox/__init__.py +28 -0
  153. ksadk/sandbox/backends/__init__.py +9 -0
  154. ksadk/sandbox/backends/e2b.py +154 -0
  155. ksadk/sandbox/backends/local_process.py +131 -0
  156. ksadk/sandbox/base.py +101 -0
  157. ksadk/sandbox/factory.py +53 -0
  158. ksadk/sandbox/registry.py +187 -0
  159. ksadk/server/__init__.py +7 -0
  160. ksadk/server/api_models.py +73 -0
  161. ksadk/server/app.py +3931 -0
  162. ksadk/server/static/assets/ArtifactsPanel-D-SSn2ee.js +1 -0
  163. ksadk/server/static/assets/CodeBlock-P16VOLYi.js +9 -0
  164. ksadk/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  165. ksadk/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  166. ksadk/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  167. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  168. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  169. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  170. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  171. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  172. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  173. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  174. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  175. ksadk/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  176. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  177. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  178. ksadk/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  179. ksadk/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  180. ksadk/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  181. ksadk/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  182. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  183. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  184. ksadk/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  185. ksadk/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  186. ksadk/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  187. ksadk/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  188. ksadk/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  189. ksadk/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  190. ksadk/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  191. ksadk/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  192. ksadk/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  193. ksadk/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  194. ksadk/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  195. ksadk/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  196. ksadk/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  197. ksadk/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  198. ksadk/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  199. ksadk/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  200. ksadk/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  201. ksadk/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  202. ksadk/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  203. ksadk/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  204. ksadk/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  205. ksadk/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  206. ksadk/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  207. ksadk/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  208. ksadk/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  209. ksadk/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  210. ksadk/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  211. ksadk/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  212. ksadk/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  213. ksadk/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  214. ksadk/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  215. ksadk/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  216. ksadk/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  217. ksadk/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  218. ksadk/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  219. ksadk/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  220. ksadk/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  221. ksadk/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  222. ksadk/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  223. ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +8 -0
  224. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
  225. ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +303 -0
  226. ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
  227. ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +1 -0
  228. ksadk/server/static/assets/addon-fit-DthTIhi3.js +1 -0
  229. ksadk/server/static/assets/apl-CnwPGSsG.js +1 -0
  230. ksadk/server/static/assets/arc-BA13sHc9.js +1 -0
  231. ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +1 -0
  232. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-DzJzgVoL.js +36 -0
  233. ksadk/server/static/assets/asciiarmor-qTkVPQu6.js +1 -0
  234. ksadk/server/static/assets/asn1-Dr8qZg38.js +1 -0
  235. ksadk/server/static/assets/asterisk-Bja0s6e1.js +1 -0
  236. ksadk/server/static/assets/blockDiagram-GPEHLZMM-UTdVcZhn.js +132 -0
  237. ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
  238. ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dix0GD4m.js +10 -0
  239. ksadk/server/static/assets/channel-CTuydARX.js +1 -0
  240. ksadk/server/static/assets/chunk-2J33WTMH-C2JxuZ42.js +1 -0
  241. ksadk/server/static/assets/chunk-4BX2VUAB-Be57QPgD.js +1 -0
  242. ksadk/server/static/assets/chunk-55IACEB6-WjSuy4nv.js +1 -0
  243. ksadk/server/static/assets/chunk-727SXJPM-BOovP-b5.js +206 -0
  244. ksadk/server/static/assets/chunk-AQP2D5EJ-DOmZNmWj.js +231 -0
  245. ksadk/server/static/assets/chunk-FMBD7UC4-DzwlodkU.js +15 -0
  246. ksadk/server/static/assets/chunk-ND2GUHAM-DMqAikEU.js +1 -0
  247. ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +1 -0
  248. ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +1 -0
  249. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +1 -0
  250. ksadk/server/static/assets/clike-DHH8Ad3s.js +1 -0
  251. ksadk/server/static/assets/clojure-BflJGmDX.js +1 -0
  252. ksadk/server/static/assets/cmake-CyVbuzPu.js +1 -0
  253. ksadk/server/static/assets/cobol-B_OZ4V-R.js +1 -0
  254. ksadk/server/static/assets/coffeescript-B2pKbFk8.js +1 -0
  255. ksadk/server/static/assets/commonlisp-CcllspGY.js +1 -0
  256. ksadk/server/static/assets/cose-bilkent-S5V4N54A-Zhy2GBnP.js +1 -0
  257. ksadk/server/static/assets/crystal-M5-qzICs.js +1 -0
  258. ksadk/server/static/assets/css-CYpP4FRV.js +1 -0
  259. ksadk/server/static/assets/cypher-p9eYesGn.js +1 -0
  260. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +321 -0
  261. ksadk/server/static/assets/d-BhMjBjQP.js +1 -0
  262. ksadk/server/static/assets/dagre-BM42HDAG-CbKrtIUz.js +4 -0
  263. ksadk/server/static/assets/dagre-Bx709z4p.js +1 -0
  264. ksadk/server/static/assets/defaultLocale-C8Fc0cco.js +1 -0
  265. ksadk/server/static/assets/diagram-2AECGRRQ-BRApgQRK.js +43 -0
  266. ksadk/server/static/assets/diagram-5GNKFQAL-D0xbnDiK.js +10 -0
  267. ksadk/server/static/assets/diagram-KO2AKTUF-CVugVI9L.js +3 -0
  268. ksadk/server/static/assets/diagram-LMA3HP47-DozUGgee.js +24 -0
  269. ksadk/server/static/assets/diagram-OG6HWLK6-ZOYsKlru.js +24 -0
  270. ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
  271. ksadk/server/static/assets/dist-2hInLS_J.js +9 -0
  272. ksadk/server/static/assets/dist-8EEyGgDx.js +1 -0
  273. ksadk/server/static/assets/dist-8_SfK1IP.js +1 -0
  274. ksadk/server/static/assets/dist-B0NP_Z0z.js +23 -0
  275. ksadk/server/static/assets/dist-BIJVDMuB.js +1 -0
  276. ksadk/server/static/assets/dist-BmlMPsCc.js +2 -0
  277. ksadk/server/static/assets/dist-BrCcQ47T.js +1 -0
  278. ksadk/server/static/assets/dist-BssVmjIo.js +6 -0
  279. ksadk/server/static/assets/dist-C3HIIaN5.js +1 -0
  280. ksadk/server/static/assets/dist-CPBtqRTW.js +1 -0
  281. ksadk/server/static/assets/dist-CkEKJFtk.js +1 -0
  282. ksadk/server/static/assets/dist-D-JMdWPQ.js +1 -0
  283. ksadk/server/static/assets/dist-D-xOD048.js +1 -0
  284. ksadk/server/static/assets/dist-D57wnGWd.js +1 -0
  285. ksadk/server/static/assets/dist-DL_NKc_z.js +1 -0
  286. ksadk/server/static/assets/dist-DMezvBGJ.js +1 -0
  287. ksadk/server/static/assets/dist-DmFaq_Iy.js +1 -0
  288. ksadk/server/static/assets/dist-Dp0k7bWI.js +1 -0
  289. ksadk/server/static/assets/dist-DpKtt4Bo.js +1 -0
  290. ksadk/server/static/assets/dist-DyOkZmze.js +11 -0
  291. ksadk/server/static/assets/dist-DyWsb78Q.js +1 -0
  292. ksadk/server/static/assets/dist-gX6GOLKq.js +1 -0
  293. ksadk/server/static/assets/dockerfile-BLkNEvjs.js +1 -0
  294. ksadk/server/static/assets/dtd-DTF72YNO.js +1 -0
  295. ksadk/server/static/assets/dylan-C6jEEEk-.js +1 -0
  296. ksadk/server/static/assets/ebnf-D4c0_ac3.js +1 -0
  297. ksadk/server/static/assets/ecl-BSZaIHnp.js +1 -0
  298. ksadk/server/static/assets/eiffel-BEjRio4Q.js +1 -0
  299. ksadk/server/static/assets/elm-Cshzl8qu.js +1 -0
  300. ksadk/server/static/assets/erDiagram-TEJ5UH35-Bk-9bgE5.js +85 -0
  301. ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
  302. ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +1 -0
  303. ksadk/server/static/assets/factor-D7LVTn2l.js +1 -0
  304. ksadk/server/static/assets/fcl-ClOhbFR7.js +1 -0
  305. ksadk/server/static/assets/flowDiagram-I6XJVG4X-Dn9kZVuZ.js +162 -0
  306. ksadk/server/static/assets/forth-Cezjo90N.js +1 -0
  307. ksadk/server/static/assets/fortran-Bt6PBEDR.js +1 -0
  308. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-BGxXlJqm.js +292 -0
  309. ksadk/server/static/assets/gas-BHEdbvp9.js +1 -0
  310. ksadk/server/static/assets/gherkin-oBAE_ms0.js +1 -0
  311. ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +1 -0
  312. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-C7Q0X-wi.js +106 -0
  313. ksadk/server/static/assets/graphlib-B8gBHxth.js +1 -0
  314. ksadk/server/static/assets/groovy-BC3IOsC8.js +1 -0
  315. ksadk/server/static/assets/haskell-BRsoo5mP.js +1 -0
  316. ksadk/server/static/assets/haxe-DIz0ZZqd.js +1 -0
  317. ksadk/server/static/assets/http-CLVgA2GD.js +1 -0
  318. ksadk/server/static/assets/idl-BUZw3wgd.js +1 -0
  319. ksadk/server/static/assets/index-C00Lwg3L.js +165 -0
  320. ksadk/server/static/assets/index-DAURbCsP.css +1 -0
  321. ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +1 -0
  322. ksadk/server/static/assets/infoDiagram-5YYISTIA-BO_CSqq5.js +2 -0
  323. ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
  324. ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-eYLPLd46.js +70 -0
  325. ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
  326. ksadk/server/static/assets/journeyDiagram-JHISSGLW-De9geSb0.js +139 -0
  327. ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
  328. ksadk/server/static/assets/kanban-definition-UN3LZRKU-Cs80kQto.js +89 -0
  329. ksadk/server/static/assets/katex-DSrCFD8n.js +265 -0
  330. ksadk/server/static/assets/linear-CN9sbKTF.js +1 -0
  331. ksadk/server/static/assets/livescript-BXxG0Yva.js +1 -0
  332. ksadk/server/static/assets/lua-CiA1ziua.js +1 -0
  333. ksadk/server/static/assets/mathematica-u8YMmbU0.js +1 -0
  334. ksadk/server/static/assets/mbox-BEMVcqjs.js +1 -0
  335. ksadk/server/static/assets/mermaid-parser.core-DlgSBU8l.js +161 -0
  336. ksadk/server/static/assets/mindmap-definition-RKZ34NQL-9afz7Oug.js +96 -0
  337. ksadk/server/static/assets/mirc-C9zpzAZU.js +1 -0
  338. ksadk/server/static/assets/mllike-B45xgp2S.js +1 -0
  339. ksadk/server/static/assets/modelica-CqHI_q-D.js +1 -0
  340. ksadk/server/static/assets/mscgen-qgSLujhx.js +1 -0
  341. ksadk/server/static/assets/mumps-CW_TBmxz.js +1 -0
  342. ksadk/server/static/assets/nginx-BMaDbqW3.js +1 -0
  343. ksadk/server/static/assets/nsis-AQ_alPln.js +1 -0
  344. ksadk/server/static/assets/ntriples-d28e9m0E.js +1 -0
  345. ksadk/server/static/assets/octave-D2Q8cUp1.js +1 -0
  346. ksadk/server/static/assets/ordinal-hYBb2elL.js +1 -0
  347. ksadk/server/static/assets/oz-BwTct_5T.js +1 -0
  348. ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +1 -0
  349. ksadk/server/static/assets/pascal-Dp_KdFgX.js +1 -0
  350. ksadk/server/static/assets/perl-CdEHsPfU.js +1 -0
  351. ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +1 -0
  352. ksadk/server/static/assets/pieDiagram-4H26LBE5-DPv_VstN.js +30 -0
  353. ksadk/server/static/assets/pig-AF4Hwhju.js +1 -0
  354. ksadk/server/static/assets/powershell-CzG71I4L.js +1 -0
  355. ksadk/server/static/assets/properties-C357ku5U.js +1 -0
  356. ksadk/server/static/assets/protobuf-D1ij_kNL.js +1 -0
  357. ksadk/server/static/assets/pug-Bugr-47h.js +1 -0
  358. ksadk/server/static/assets/puppet-B4hC2X4m.js +1 -0
  359. ksadk/server/static/assets/python-BqYw9LYJ.js +1 -0
  360. ksadk/server/static/assets/q-B9NhS7L_.js +1 -0
  361. ksadk/server/static/assets/quadrantDiagram-W4KKPZXB-o77wZ1XK.js +7 -0
  362. ksadk/server/static/assets/r-DADKenSm.js +1 -0
  363. ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +1 -0
  364. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-BYVw81VC.js +84 -0
  365. ksadk/server/static/assets/rpm-gpDK5sbt.js +1 -0
  366. ksadk/server/static/assets/ruby-DsYpTuWg.js +1 -0
  367. ksadk/server/static/assets/sankeyDiagram-5OEKKPKP-B7nZFMKT.js +40 -0
  368. ksadk/server/static/assets/sas-C2OyD2Y6.js +1 -0
  369. ksadk/server/static/assets/scheme-CyDdOh7e.js +1 -0
  370. ksadk/server/static/assets/sequenceDiagram-3UESZ5HK-BGRRrFw5.js +162 -0
  371. ksadk/server/static/assets/shell-Du5Qg9im.js +1 -0
  372. ksadk/server/static/assets/sieve-BAxa3IjF.js +1 -0
  373. ksadk/server/static/assets/simple-mode-DRpGK0lJ.js +1 -0
  374. ksadk/server/static/assets/smalltalk-BLp5-jwC.js +1 -0
  375. ksadk/server/static/assets/solr-BBopId9w.js +1 -0
  376. ksadk/server/static/assets/sparql-Dz-mlCAC.js +1 -0
  377. ksadk/server/static/assets/spreadsheet-CTIncYxj.js +1 -0
  378. ksadk/server/static/assets/sql-DcCJ9jop.js +1 -0
  379. ksadk/server/static/assets/stateDiagram-AJRCARHV-BUfHCoPs.js +1 -0
  380. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +1 -0
  381. ksadk/server/static/assets/stex-sDrdk2BW.js +1 -0
  382. ksadk/server/static/assets/stylus-DLLZ8dgm.js +1 -0
  383. ksadk/server/static/assets/swift-DKB6_1j6.js +1 -0
  384. ksadk/server/static/assets/tcl-BGfruO1u.js +1 -0
  385. ksadk/server/static/assets/textile-DWBqthVk.js +1 -0
  386. ksadk/server/static/assets/tiddlywiki-VlUiK86J.js +1 -0
  387. ksadk/server/static/assets/tiki-CxVlf5KZ.js +1 -0
  388. ksadk/server/static/assets/timeline-definition-PNZ67QCA-FbCTGrf9.js +120 -0
  389. ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
  390. ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +1 -0
  391. ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +1 -0
  392. ksadk/server/static/assets/troff-C2dAgh7P.js +1 -0
  393. ksadk/server/static/assets/ttcn-BePYh-hG.js +1 -0
  394. ksadk/server/static/assets/ttcn-cfg-CY0aot7Q.js +1 -0
  395. ksadk/server/static/assets/turtle-BDLWE2cD.js +1 -0
  396. ksadk/server/static/assets/vb-BthdM_4N.js +1 -0
  397. ksadk/server/static/assets/vbscript-D9f6rSsU.js +1 -0
  398. ksadk/server/static/assets/velocity-CqftRsjg.js +1 -0
  399. ksadk/server/static/assets/vennDiagram-CIIHVFJN-DWgwtPsJ.js +34 -0
  400. ksadk/server/static/assets/verilog-D-x6ne0Z.js +1 -0
  401. ksadk/server/static/assets/vhdl-CMrOq2q1.js +1 -0
  402. ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +1 -0
  403. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-2x8G-tTM.js +78 -0
  404. ksadk/server/static/assets/webidl-D5jiJvOU.js +1 -0
  405. ksadk/server/static/assets/xquery-fj_R-kMw.js +1 -0
  406. ksadk/server/static/assets/xterm-DooSxjI5.js +36 -0
  407. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-Drma3AYl.js +7 -0
  408. ksadk/server/static/assets/yacas-CXXgtw0p.js +1 -0
  409. ksadk/server/static/assets/z80-CL1naaMV.js +1 -0
  410. ksadk/server/static/favicon.svg +1 -0
  411. ksadk/server/static/icons.svg +24 -0
  412. ksadk/server/static/index.html +14 -0
  413. ksadk/server/terminal_sessions.py +551 -0
  414. ksadk/sessions/__init__.py +279 -0
  415. ksadk/sessions/base.py +354 -0
  416. ksadk/sessions/continuity.py +337 -0
  417. ksadk/sessions/errors.py +7 -0
  418. ksadk/sessions/in_memory.py +273 -0
  419. ksadk/sessions/local_service.py +949 -0
  420. ksadk/sessions/postgres_service.py +901 -0
  421. ksadk/sessions/resilience.py +52 -0
  422. ksadk/sessions/resilient.py +360 -0
  423. ksadk/sessions/sqlite_service.py +13 -0
  424. ksadk/skills/__init__.py +9 -0
  425. ksadk/skills/loader.py +46 -0
  426. ksadk/skills/models.py +120 -0
  427. ksadk/skills/package_store.py +104 -0
  428. ksadk/skills/runtime/__init__.py +17 -0
  429. ksadk/skills/runtime/agent.py +183 -0
  430. ksadk/skills/runtime/artifacts.py +39 -0
  431. ksadk/skills/runtime/backends/__init__.py +1 -0
  432. ksadk/skills/runtime/backends/disabled.py +8 -0
  433. ksadk/skills/runtime/backends/e2b.py +168 -0
  434. ksadk/skills/runtime/backends/local.py +95 -0
  435. ksadk/skills/runtime/base.py +103 -0
  436. ksadk/skills/runtime/executor.py +219 -0
  437. ksadk/skills/runtime/factory.py +37 -0
  438. ksadk/skills/runtime/loader.py +131 -0
  439. ksadk/skills/runtime/registry.py +150 -0
  440. ksadk/skills/runtime/request.py +67 -0
  441. ksadk/skills/service_client.py +239 -0
  442. ksadk/skills/service_env.py +58 -0
  443. ksadk/skills/tool_defs.py +221 -0
  444. ksadk/terminal_client.py +69 -0
  445. ksadk/terminal_exec_policy.py +229 -0
  446. ksadk/tools/__init__.py +17 -0
  447. ksadk/tools/gateway.py +230 -0
  448. ksadk/tools/result_budget.py +154 -0
  449. ksadk/toolsets/__init__.py +854 -0
  450. ksadk/toolsets/_langchain.py +11 -0
  451. ksadk/toolsets/platform.py +93 -0
  452. ksadk/toolsets/sandbox.py +310 -0
  453. ksadk/toolsets/skills.py +217 -0
  454. ksadk/toolsets/web.py +266 -0
  455. ksadk/toolsets/workspace.py +917 -0
  456. ksadk/toolsets/workspace_state.py +44 -0
  457. ksadk/tracing/__init__.py +37 -0
  458. ksadk/tracing/exporters/__init__.py +1 -0
  459. ksadk/tracing/exporters/inmemory_exporter.py +116 -0
  460. ksadk/tracing/exporters/langfuse_exporter.py +445 -0
  461. ksadk/tracing/setup.py +892 -0
  462. ksadk/tracing/span_utils.py +114 -0
  463. ksadk/tui/__init__.py +27 -0
  464. ksadk/tui/loop.py +1877 -0
  465. ksadk/tui/stream_render.py +68 -0
  466. ksadk/ui_config.py +168 -0
  467. ksadk/version.py +4 -0
  468. ksadk_runtime_common/__init__.py +20 -0
  469. ksadk_runtime_common/memory_backend/__init__.py +29 -0
  470. ksadk_runtime_common/memory_backend/manifest.py +79 -0
  471. ksadk_runtime_common/memory_backend/providers/__init__.py +6 -0
  472. ksadk_runtime_common/memory_backend/providers/lancedb.py +151 -0
  473. ksadk_runtime_common/memory_backend/providers/mem0.py +74 -0
  474. ksadk_runtime_common/memory_backend/registry.py +56 -0
  475. ksadk_runtime_common/memory_backend/render.py +71 -0
  476. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -0
  477. ksadk_runtime_common/workspace_files/__init__.py +29 -0
  478. ksadk_runtime_common/workspace_files/bootstrap.py +56 -0
  479. ksadk_runtime_common/workspace_files/constants.py +9 -0
  480. ksadk_runtime_common/workspace_files/path_utils.py +71 -0
  481. ksadk_runtime_common/workspace_files/preview.py +96 -0
  482. ksadk_runtime_common/workspace_files/router.py +254 -0
  483. agentengine_sdk_python/__init__.py +0 -3
  484. agentengine_sdk_python-0.6.4.dist-info/METADATA +0 -48
  485. agentengine_sdk_python-0.6.4.dist-info/RECORD +0 -5
  486. agentengine_sdk_python-0.6.4.dist-info/top_level.txt +0 -1
@@ -0,0 +1,273 @@
1
+ """LongTermMemory - 长期记忆服务
2
+
3
+ 实现 Google ADK 的 BaseMemoryService 接口,提供跨 session 的记忆存储和检索。
4
+ 通过环境变量配置后端类型和参数,由 ADKRunner 自动注入。
5
+
6
+ 参考 VeADK: veadk/memory/long_term_memory.py
7
+
8
+ 环境变量:
9
+ KSADK_LTM_BACKEND: 后端类型 (local / http)
10
+ KSADK_LTM_HTTP_URL: HTTP 记忆服务地址
11
+ KSADK_LTM_HTTP_TOKEN: HTTP 认证 Token
12
+ KSADK_LTM_TOP_K: 检索数量 (默认 5)
13
+
14
+ 使用示例:
15
+ # 通过环境变量自动配置 (推荐)
16
+ # 设置 KSADK_LTM_BACKEND=local 即可
17
+
18
+ # 手动创建
19
+ from ksadk.memory.adk import LongTermMemory
20
+ ltm = LongTermMemory(backend="local", app_name="my_app")
21
+ """
22
+
23
+ import json
24
+ import logging
25
+ import os
26
+ from typing import Any, List, Literal
27
+
28
+ from google.adk.events.event import Event
29
+ from google.adk.memory.base_memory_service import (
30
+ BaseMemoryService,
31
+ SearchMemoryResponse,
32
+ )
33
+ from google.adk.memory.memory_entry import MemoryEntry
34
+ from google.adk.sessions import Session
35
+ from google.genai import types
36
+ from pydantic import BaseModel, ConfigDict, Field
37
+ from typing_extensions import Union, override
38
+
39
+ from ksadk.memory.adk.backends.base_ltm_backend import BaseLongTermMemoryBackend
40
+ from ksadk.memory.service import LongTermMemoryService
41
+
42
+ logger = logging.getLogger(__name__)
43
+
44
+
45
+ class LongTermMemory(BaseMemoryService, BaseModel):
46
+ """长期记忆服务 - 跨 session 的记忆管理
47
+
48
+ 实现 Google ADK 的 BaseMemoryService 接口,支持:
49
+ - 将 session 中的用户消息持久化到记忆后端
50
+ - 通过语义/关键词检索历史记忆
51
+
52
+ Attributes:
53
+ backend: 后端类型或实例 ("local" / "http" / BaseLongTermMemoryBackend)
54
+ backend_config: 后端配置参数
55
+ top_k: 检索返回的最大记忆条数
56
+ index: 索引名称 (用于隔离不同应用的数据)
57
+ app_name: 应用名称 (备选 index)
58
+
59
+ Examples:
60
+ ```python
61
+ # 本地开发
62
+ ltm = LongTermMemory(backend="local", app_name="my_app")
63
+
64
+ # 远程服务
65
+ ltm = LongTermMemory(
66
+ backend="http",
67
+ backend_config={
68
+ "base_url": "https://memory.ksyun.com/api/v1",
69
+ "token": "sk-xxx",
70
+ },
71
+ app_name="my_app"
72
+ )
73
+ ```
74
+ """
75
+
76
+ backend: Union[
77
+ Literal["local", "http", "sdk"],
78
+ BaseLongTermMemoryBackend,
79
+ ] = "local"
80
+
81
+ backend_config: dict = Field(default_factory=dict)
82
+ top_k: int = 5
83
+ index: str = ""
84
+ app_name: str = ""
85
+
86
+ _backend: BaseLongTermMemoryBackend = None
87
+ _service: LongTermMemoryService = None
88
+
89
+ model_config = ConfigDict(arbitrary_types_allowed=True)
90
+
91
+ def model_post_init(self, __context: Any) -> None:
92
+ self._service = LongTermMemoryService(
93
+ backend=self.backend,
94
+ backend_config=self.backend_config,
95
+ top_k=self.top_k,
96
+ index=self.index,
97
+ app_name=self.app_name,
98
+ )
99
+ self._backend = self._service._backend
100
+ self.index = self._service.index
101
+ logger.info(
102
+ "LongTermMemory initialized: backend=%s, index=%s",
103
+ self.backend,
104
+ self.index,
105
+ )
106
+
107
+ def _get_service(self) -> LongTermMemoryService:
108
+ if self._service is None:
109
+ self.model_post_init(None)
110
+ if self._backend is not None and self._service._backend is not self._backend:
111
+ self._service.backend = self._backend
112
+ self._service._backend = self._backend
113
+ self._service.index = getattr(self._backend, "index", self._service.index)
114
+ self.index = self._service.index
115
+ return self._service
116
+
117
+ def _filter_and_convert_events(self, events: List[Event]) -> List[str]:
118
+ """过滤并序列化 session 事件
119
+
120
+ 参考 VeADK 的逻辑:
121
+ - 只保留用户消息 (author == "user")
122
+ - 过滤掉空内容、function call、function response
123
+ - 序列化为 JSON 字符串
124
+ """
125
+ final_events = []
126
+ for event in events:
127
+ # 过滤: 无内容的事件
128
+ if not event.content or not event.content.parts:
129
+ continue
130
+
131
+ # 过滤: 只保留用户事件
132
+ if event.author != "user":
133
+ continue
134
+
135
+ # 过滤: 去除 function call / function response (无 text)
136
+ if not event.content.parts[0].text:
137
+ continue
138
+
139
+ # 转换: 序列化为 JSON
140
+ message = event.content.model_dump(exclude_none=True, mode="json")
141
+ final_events.append(json.dumps(message, ensure_ascii=False))
142
+
143
+ return final_events
144
+
145
+ @override
146
+ async def add_session_to_memory(
147
+ self,
148
+ session: Session,
149
+ **kwargs,
150
+ ):
151
+ """将 session 中的用户消息保存到长期记忆
152
+
153
+ Args:
154
+ session: Google ADK Session 对象
155
+ """
156
+ user_id = session.user_id
157
+ event_strings = self._filter_and_convert_events(session.events)
158
+
159
+ if not event_strings:
160
+ logger.info(
161
+ f"No user events to save for session={session.id}"
162
+ )
163
+ return
164
+
165
+ logger.info(
166
+ f"Saving {len(event_strings)} events to long term memory: "
167
+ f"index={self.index}, user_id={user_id}"
168
+ )
169
+
170
+ self._get_service().save_event_strings(
171
+ user_id=user_id,
172
+ event_strings=event_strings,
173
+ metadata=kwargs.get("metadata"),
174
+ )
175
+
176
+ logger.info(
177
+ f"Saved {len(event_strings)} events to long term memory: "
178
+ f"index={self.index}, user_id={user_id}"
179
+ )
180
+
181
+ @override
182
+ async def search_memory(
183
+ self, *, app_name: str, user_id: str, query: str
184
+ ) -> SearchMemoryResponse:
185
+ """检索长期记忆
186
+
187
+ Args:
188
+ app_name: 应用名称
189
+ user_id: 用户 ID
190
+ query: 查询文本
191
+
192
+ Returns:
193
+ SearchMemoryResponse: 包含匹配记忆条目的响应
194
+ """
195
+ logger.info(f"Searching memory: query='{query[:50]}' user_id={user_id}")
196
+
197
+ memory_chunks = []
198
+ try:
199
+ memory_chunks = self._get_service().search_entries(
200
+ query=query, top_k=self.top_k, user_id=user_id
201
+ )
202
+ except Exception as e:
203
+ logger.error(
204
+ f"Error during memory search: {e}. Returning empty results."
205
+ )
206
+
207
+ # 转换为 MemoryEntry 格式
208
+ memory_events = []
209
+ for memory in memory_chunks:
210
+ try:
211
+ memory_dict = json.loads(memory)
212
+ try:
213
+ text = memory_dict["parts"][0]["text"]
214
+ role = memory_dict.get("role", "user")
215
+ except (KeyError, IndexError):
216
+ logger.warning(
217
+ f"Non-standard memory format: {memory[:100]}. Skipping."
218
+ )
219
+ continue
220
+ except json.JSONDecodeError:
221
+ # 非 JSON 格式的记忆字符串,直接作为 text
222
+ text = memory
223
+ role = "user"
224
+
225
+ memory_events.append(
226
+ MemoryEntry(
227
+ author="user",
228
+ content=types.Content(
229
+ parts=[types.Part(text=text)], role=role
230
+ ),
231
+ )
232
+ )
233
+
234
+ logger.info(
235
+ f"Found {len(memory_events)} memory entries for "
236
+ f"query='{query[:50]}' index={self.index} user_id={user_id}"
237
+ )
238
+ return SearchMemoryResponse(memories=memory_events)
239
+
240
+ @classmethod
241
+ def from_env(
242
+ cls,
243
+ *,
244
+ app_name: str = "",
245
+ backend: str | None = None,
246
+ ) -> "LongTermMemory":
247
+ """从环境变量创建 LongTermMemory
248
+
249
+ 环境变量:
250
+ KSADK_LTM_BACKEND: local / http / sdk
251
+ KSADK_LTM_HTTP_URL: HTTP 记忆服务地址
252
+ KSADK_LTM_HTTP_TOKEN: HTTP 认证 Token
253
+ KSADK_LTM_ACCESS_KEY: SDK AK (fallback to KSYUN_ACCESS_KEY)
254
+ KSADK_LTM_SECRET_KEY: SDK SK (fallback to KSYUN_SECRET_KEY)
255
+ KSADK_LTM_TOP_K: 检索数量 (默认 5)
256
+ KSADK_LTM_INDEX: 索引名称
257
+ """
258
+ service = LongTermMemoryService.from_env(app_name=app_name, backend=backend)
259
+ backend_name = (
260
+ backend
261
+ or os.environ.get("KSADK_LTM_BACKEND", "local")
262
+ )
263
+ backend_config = dict(service.backend_config)
264
+ if "index" in backend_config and backend_name != "local":
265
+ backend_config.pop("index", None)
266
+
267
+ return cls(
268
+ backend=backend_name,
269
+ backend_config=backend_config,
270
+ top_k=service.top_k,
271
+ index=service.index,
272
+ app_name=service.app_name,
273
+ )
@@ -0,0 +1,268 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ from typing import Any, Optional
6
+
7
+ from google.adk.events.event import Event
8
+ from google.adk.sessions import InMemorySessionService
9
+ from google.adk.sessions.base_session_service import (
10
+ BaseSessionService,
11
+ GetSessionConfig,
12
+ ListSessionsResponse,
13
+ )
14
+ from google.adk.sessions.session import Session
15
+
16
+ from ksadk.sessions.resilience import is_session_backend_failure
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class ResilientADKSessionService(BaseSessionService):
22
+ """Run ADK sessions locally while mirroring them to durable storage."""
23
+
24
+ _probe_interval_seconds: float = 30.0
25
+
26
+ def __init__(self, primary: BaseSessionService) -> None:
27
+ self.primary = primary
28
+ self.live = InMemorySessionService()
29
+ self._primary_sessions: dict[tuple[str, str, str], Session] = {}
30
+ self._primary_enabled = True
31
+ self._probe_task: asyncio.Task[None] | None = None
32
+
33
+ @property
34
+ def degraded(self) -> bool:
35
+ return not self._primary_enabled
36
+
37
+ def _degrade(self, exc: Exception) -> None:
38
+ if not self._primary_enabled:
39
+ return
40
+ self._primary_enabled = False
41
+ logger.error(
42
+ "ADK session persistence degraded; using in-memory live session: %s",
43
+ exc,
44
+ extra={
45
+ "session_backend_state": "degraded",
46
+ "session_backend": type(self.primary).__name__,
47
+ },
48
+ )
49
+ self._start_probe()
50
+
51
+ def _handle_primary_failure(self, exc: Exception) -> bool:
52
+ if not is_session_backend_failure(exc):
53
+ return False
54
+ self._degrade(exc)
55
+ return True
56
+
57
+ def _start_probe(self) -> None:
58
+ if self._probe_task is not None and not self._probe_task.done():
59
+ return
60
+ self._probe_task = asyncio.create_task(self._probe_loop())
61
+
62
+ async def _probe_loop(self) -> None:
63
+ while not self._primary_enabled:
64
+ await asyncio.sleep(self._probe_interval_seconds)
65
+ if self._primary_enabled:
66
+ break
67
+ try:
68
+ await self.primary.get_session(
69
+ app_name="__ksadk_probe__",
70
+ user_id="__ksadk_probe__",
71
+ session_id="__ksadk_probe__",
72
+ )
73
+ except Exception:
74
+ continue
75
+ self._primary_enabled = True
76
+ logger.info(
77
+ "ADK session persistence recovered; durable backend re-enabled",
78
+ extra={
79
+ "session_backend_state": "recovered",
80
+ "session_backend": type(self.primary).__name__,
81
+ },
82
+ )
83
+
84
+ @staticmethod
85
+ def _key(app_name: str, user_id: str, session_id: str) -> tuple[str, str, str]:
86
+ return app_name, user_id, session_id
87
+
88
+ async def _hydrate(self, durable: Session) -> Session:
89
+ existing = await self.live.get_session(
90
+ app_name=durable.app_name,
91
+ user_id=durable.user_id,
92
+ session_id=durable.id,
93
+ )
94
+ if existing is None:
95
+ existing = await self.live.create_session(
96
+ app_name=durable.app_name,
97
+ user_id=durable.user_id,
98
+ state=durable.state,
99
+ session_id=durable.id,
100
+ )
101
+ existing_ids = {event.id for event in existing.events}
102
+ for event in durable.events:
103
+ if event.id not in existing_ids:
104
+ await self.live.append_event(existing, event)
105
+ self._primary_sessions[self._key(durable.app_name, durable.user_id, durable.id)] = durable
106
+ hydrated = await self.live.get_session(
107
+ app_name=durable.app_name,
108
+ user_id=durable.user_id,
109
+ session_id=durable.id,
110
+ )
111
+ if hydrated is None:
112
+ raise RuntimeError(f"Failed to hydrate ADK live session {durable.id}")
113
+ return hydrated
114
+
115
+ async def create_session(
116
+ self,
117
+ *,
118
+ app_name: str,
119
+ user_id: str,
120
+ state: Optional[dict[str, Any]] = None,
121
+ session_id: Optional[str] = None,
122
+ ) -> Session:
123
+ if session_id:
124
+ existing = await self.live.get_session(
125
+ app_name=app_name,
126
+ user_id=user_id,
127
+ session_id=session_id,
128
+ )
129
+ if self._primary_enabled:
130
+ try:
131
+ durable = await self.primary.get_session(
132
+ app_name=app_name,
133
+ user_id=user_id,
134
+ session_id=session_id,
135
+ )
136
+ if durable is not None:
137
+ return await self._hydrate(durable)
138
+ except Exception as exc:
139
+ if not self._handle_primary_failure(exc):
140
+ raise
141
+ if existing is not None:
142
+ return existing
143
+
144
+ live = await self.live.create_session(
145
+ app_name=app_name,
146
+ user_id=user_id,
147
+ state=state,
148
+ session_id=session_id,
149
+ )
150
+ if self._primary_enabled:
151
+ try:
152
+ durable = await self.primary.create_session(
153
+ app_name=app_name,
154
+ user_id=user_id,
155
+ state=state,
156
+ session_id=live.id,
157
+ )
158
+ self._primary_sessions[self._key(app_name, user_id, live.id)] = durable
159
+ except Exception as exc:
160
+ if not self._handle_primary_failure(exc):
161
+ raise
162
+ return live
163
+
164
+ async def get_session(
165
+ self,
166
+ *,
167
+ app_name: str,
168
+ user_id: str,
169
+ session_id: str,
170
+ config: Optional[GetSessionConfig] = None,
171
+ ) -> Optional[Session]:
172
+ live = await self.live.get_session(
173
+ app_name=app_name,
174
+ user_id=user_id,
175
+ session_id=session_id,
176
+ config=config,
177
+ )
178
+ if not self._primary_enabled:
179
+ return live
180
+ try:
181
+ durable = await self.primary.get_session(
182
+ app_name=app_name,
183
+ user_id=user_id,
184
+ session_id=session_id,
185
+ config=config,
186
+ )
187
+ return await self._hydrate(durable) if durable is not None else live
188
+ except Exception as exc:
189
+ if not self._handle_primary_failure(exc):
190
+ raise
191
+ return live
192
+
193
+ async def list_sessions(
194
+ self,
195
+ *,
196
+ app_name: str,
197
+ user_id: Optional[str] = None,
198
+ ) -> ListSessionsResponse:
199
+ if self._primary_enabled:
200
+ try:
201
+ durable = await self.primary.list_sessions(app_name=app_name, user_id=user_id)
202
+ for session in durable.sessions:
203
+ await self._hydrate(session)
204
+ except Exception as exc:
205
+ if not self._handle_primary_failure(exc):
206
+ raise
207
+ return await self.live.list_sessions(app_name=app_name, user_id=user_id)
208
+
209
+ async def delete_session(self, *, app_name: str, user_id: str, session_id: str) -> None:
210
+ await self.live.delete_session(app_name=app_name, user_id=user_id, session_id=session_id)
211
+ self._primary_sessions.pop(self._key(app_name, user_id, session_id), None)
212
+ if self._primary_enabled:
213
+ try:
214
+ await self.primary.delete_session(
215
+ app_name=app_name,
216
+ user_id=user_id,
217
+ session_id=session_id,
218
+ )
219
+ except Exception as exc:
220
+ if not self._handle_primary_failure(exc):
221
+ raise
222
+
223
+ async def append_event(self, session: Session, event: Event) -> Event:
224
+ stored = await self.live.append_event(session, event)
225
+ if not self._primary_enabled:
226
+ return stored
227
+ key = self._key(session.app_name, session.user_id, session.id)
228
+ durable_session = self._primary_sessions.get(key)
229
+ try:
230
+ if durable_session is None:
231
+ durable_session = await self.primary.get_session(
232
+ app_name=session.app_name,
233
+ user_id=session.user_id,
234
+ session_id=session.id,
235
+ )
236
+ if durable_session is None:
237
+ durable_session = await self.primary.create_session(
238
+ app_name=session.app_name,
239
+ user_id=session.user_id,
240
+ state=session.state,
241
+ session_id=session.id,
242
+ )
243
+ self._primary_sessions[key] = durable_session
244
+ await self.primary.append_event(durable_session, event)
245
+ except Exception as exc:
246
+ if not self._handle_primary_failure(exc):
247
+ raise
248
+ return stored
249
+
250
+ async def flush(self) -> None:
251
+ await self.live.flush()
252
+ if self._primary_enabled:
253
+ try:
254
+ await self.primary.flush()
255
+ except Exception as exc:
256
+ if not self._handle_primary_failure(exc):
257
+ raise
258
+
259
+ async def close(self) -> None:
260
+ if self._probe_task is not None and not self._probe_task.done():
261
+ self._probe_task.cancel()
262
+ try:
263
+ await self._probe_task
264
+ except asyncio.CancelledError:
265
+ pass
266
+ close = getattr(self.primary, "close", None)
267
+ if close is not None:
268
+ await close()