agentengine-sdk-python 0.6.2__py3-none-any.whl → 0.6.9__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 (490) hide show
  1. agentengine_sdk_python-0.6.9.dist-info/METADATA +179 -0
  2. agentengine_sdk_python-0.6.9.dist-info/RECORD +487 -0
  3. {agentengine_sdk_python-0.6.2.dist-info → agentengine_sdk_python-0.6.9.dist-info}/WHEEL +1 -1
  4. agentengine_sdk_python-0.6.9.dist-info/entry_points.txt +3 -0
  5. agentengine_sdk_python-0.6.9.dist-info/licenses/LICENSE +175 -0
  6. agentengine_sdk_python-0.6.9.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 +2227 -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 +2277 -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 +1259 -0
  46. ksadk/cli/cmd_invoke.py +1336 -0
  47. ksadk/cli/cmd_launch.py +564 -0
  48. ksadk/cli/cmd_mcp.py +1174 -0
  49. ksadk/cli/cmd_model.py +302 -0
  50. ksadk/cli/cmd_openclaw.py +3918 -0
  51. ksadk/cli/cmd_run.py +232 -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 +410 -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 +342 -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/model_context.py +360 -0
  83. ksadk/conversations/model_options.py +136 -0
  84. ksadk/conversations/normalize.py +446 -0
  85. ksadk/conversations/reasoning_markup.py +91 -0
  86. ksadk/conversations/run_kinds.py +61 -0
  87. ksadk/conversations/run_status.py +53 -0
  88. ksadk/conversations/runtime.py +5208 -0
  89. ksadk/conversations/semantic_summary.py +359 -0
  90. ksadk/conversations/session_title.py +254 -0
  91. ksadk/deployment/__init__.py +83 -0
  92. ksadk/deployment/agent_access.py +226 -0
  93. ksadk/deployment/base.py +229 -0
  94. ksadk/deployment/manager.py +332 -0
  95. ksadk/deployment/providers/__init__.py +10 -0
  96. ksadk/deployment/providers/serverless.py +1105 -0
  97. ksadk/deployment/registry.py +120 -0
  98. ksadk/deployment/state.py +78 -0
  99. ksadk/deployment/ui_config.py +21 -0
  100. ksadk/detection/__init__.py +7 -0
  101. ksadk/detection/detector.py +431 -0
  102. ksadk/detection/mcp_detector.py +250 -0
  103. ksadk/hermes_terminal.py +467 -0
  104. ksadk/identity/__init__.py +17 -0
  105. ksadk/identity/resolver.py +385 -0
  106. ksadk/knowledge_base/__init__.py +62 -0
  107. ksadk/knowledge_base/adk_tool.py +47 -0
  108. ksadk/knowledge_base/client.py +297 -0
  109. ksadk/knowledge_base/langchain_tool.py +55 -0
  110. ksadk/knowledge_base/service.py +66 -0
  111. ksadk/knowledge_base/tool.py +50 -0
  112. ksadk/markdown.py +169 -0
  113. ksadk/mcp_runtime/__init__.py +231 -0
  114. ksadk/memory/__init__.py +57 -0
  115. ksadk/memory/adk/__init__.py +51 -0
  116. ksadk/memory/adk/backends/__init__.py +5 -0
  117. ksadk/memory/adk/backends/base_ltm_backend.py +52 -0
  118. ksadk/memory/adk/backends/http_ltm_backend.py +183 -0
  119. ksadk/memory/adk/backends/inmemory_ltm_backend.py +96 -0
  120. ksadk/memory/adk/backends/sdk_ltm_backend.py +456 -0
  121. ksadk/memory/adk/long_term_memory.py +273 -0
  122. ksadk/memory/adk/short_term_memory.py +289 -0
  123. ksadk/memory/adk_tool.py +31 -0
  124. ksadk/memory/backends/__init__.py +6 -0
  125. ksadk/memory/backends/base.py +103 -0
  126. ksadk/memory/backends/memory.py +112 -0
  127. ksadk/memory/backends/redis.py +146 -0
  128. ksadk/memory/langchain_tool.py +39 -0
  129. ksadk/memory/ltm_backend_factory.py +24 -0
  130. ksadk/memory/manager.py +215 -0
  131. ksadk/memory/service.py +172 -0
  132. ksadk/memory/tool.py +96 -0
  133. ksadk/model_policy.py +223 -0
  134. ksadk/openclaw_gateway.py +378 -0
  135. ksadk/runners/__init__.py +8 -0
  136. ksadk/runners/adk_runner.py +1135 -0
  137. ksadk/runners/base_runner.py +305 -0
  138. ksadk/runners/deepagents_runner.py +13 -0
  139. ksadk/runners/factory.py +73 -0
  140. ksadk/runners/langchain_runner.py +539 -0
  141. ksadk/runners/langgraph_runner.py +852 -0
  142. ksadk/runners/patch_langchain.py +187 -0
  143. ksadk/runners/remote_runner.py +667 -0
  144. ksadk/runners/usage_accumulator.py +38 -0
  145. ksadk/runners/utils/__init__.py +19 -0
  146. ksadk/runners/utils/langfuse.py +230 -0
  147. ksadk/runners/utils/loader.py +62 -0
  148. ksadk/runtime_context.py +166 -0
  149. ksadk/runtime_state.py +25 -0
  150. ksadk/sandbox/__init__.py +28 -0
  151. ksadk/sandbox/backends/__init__.py +9 -0
  152. ksadk/sandbox/backends/e2b.py +154 -0
  153. ksadk/sandbox/backends/local_process.py +131 -0
  154. ksadk/sandbox/base.py +101 -0
  155. ksadk/sandbox/factory.py +53 -0
  156. ksadk/sandbox/registry.py +187 -0
  157. ksadk/server/__init__.py +7 -0
  158. ksadk/server/api_models.py +73 -0
  159. ksadk/server/app.py +3789 -0
  160. ksadk/server/static/assets/ArtifactsPanel-C0meuOdi.js +1 -0
  161. ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +9 -0
  162. ksadk/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  163. ksadk/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  164. ksadk/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  165. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  166. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  167. ksadk/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  168. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  169. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  170. ksadk/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  171. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  172. ksadk/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  173. ksadk/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  174. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  175. ksadk/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  176. ksadk/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  177. ksadk/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  178. ksadk/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  179. ksadk/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  180. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  181. ksadk/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  182. ksadk/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  183. ksadk/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  184. ksadk/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  185. ksadk/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  186. ksadk/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  187. ksadk/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  188. ksadk/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  189. ksadk/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  190. ksadk/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  191. ksadk/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  192. ksadk/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  193. ksadk/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  194. ksadk/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  195. ksadk/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  196. ksadk/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  197. ksadk/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  198. ksadk/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  199. ksadk/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  200. ksadk/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  201. ksadk/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  202. ksadk/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  203. ksadk/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  204. ksadk/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  205. ksadk/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  206. ksadk/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  207. ksadk/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  208. ksadk/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  209. ksadk/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  210. ksadk/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  211. ksadk/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  212. ksadk/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  213. ksadk/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  214. ksadk/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  215. ksadk/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  216. ksadk/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  217. ksadk/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  218. ksadk/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  219. ksadk/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  220. ksadk/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  221. ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +8 -0
  222. ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
  223. ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +303 -0
  224. ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
  225. ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +1 -0
  226. ksadk/server/static/assets/addon-fit-DthTIhi3.js +1 -0
  227. ksadk/server/static/assets/apl-CnwPGSsG.js +1 -0
  228. ksadk/server/static/assets/arc-bj2rZnP5.js +1 -0
  229. ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +1 -0
  230. ksadk/server/static/assets/architectureDiagram-3BPJPVTR-2u1ltDIj.js +36 -0
  231. ksadk/server/static/assets/asciiarmor-qTkVPQu6.js +1 -0
  232. ksadk/server/static/assets/asn1-Dr8qZg38.js +1 -0
  233. ksadk/server/static/assets/asterisk-Bja0s6e1.js +1 -0
  234. ksadk/server/static/assets/blockDiagram-GPEHLZMM-D6fvdK20.js +132 -0
  235. ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
  236. ksadk/server/static/assets/c4Diagram-AAUBKEIU-BK82L5n5.js +10 -0
  237. ksadk/server/static/assets/channel-BSSOwFIb.js +1 -0
  238. ksadk/server/static/assets/chunk-2J33WTMH-DLVdkeyQ.js +1 -0
  239. ksadk/server/static/assets/chunk-4BX2VUAB-BbwsYcbW.js +1 -0
  240. ksadk/server/static/assets/chunk-55IACEB6-DOairxzw.js +1 -0
  241. ksadk/server/static/assets/chunk-727SXJPM-hCO487gs.js +206 -0
  242. ksadk/server/static/assets/chunk-AQP2D5EJ-XU8vDOuG.js +231 -0
  243. ksadk/server/static/assets/chunk-FMBD7UC4-PrapyfMu.js +15 -0
  244. ksadk/server/static/assets/chunk-ND2GUHAM-CboKhTZ3.js +1 -0
  245. ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +1 -0
  246. ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +1 -0
  247. ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +1 -0
  248. ksadk/server/static/assets/clike-DHH8Ad3s.js +1 -0
  249. ksadk/server/static/assets/clojure-BflJGmDX.js +1 -0
  250. ksadk/server/static/assets/cmake-CyVbuzPu.js +1 -0
  251. ksadk/server/static/assets/cobol-B_OZ4V-R.js +1 -0
  252. ksadk/server/static/assets/coffeescript-B2pKbFk8.js +1 -0
  253. ksadk/server/static/assets/commonlisp-CcllspGY.js +1 -0
  254. ksadk/server/static/assets/cose-bilkent-S5V4N54A-_N8bJ-EU.js +1 -0
  255. ksadk/server/static/assets/crystal-M5-qzICs.js +1 -0
  256. ksadk/server/static/assets/css-CYpP4FRV.js +1 -0
  257. ksadk/server/static/assets/cypher-p9eYesGn.js +1 -0
  258. ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +321 -0
  259. ksadk/server/static/assets/d-BhMjBjQP.js +1 -0
  260. ksadk/server/static/assets/dagre-BM42HDAG-FoDlo5J2.js +4 -0
  261. ksadk/server/static/assets/dagre-Bx709z4p.js +1 -0
  262. ksadk/server/static/assets/defaultLocale-C8Fc0cco.js +1 -0
  263. ksadk/server/static/assets/diagram-2AECGRRQ-BBp6ebBw.js +43 -0
  264. ksadk/server/static/assets/diagram-5GNKFQAL-CqOvG1PR.js +10 -0
  265. ksadk/server/static/assets/diagram-KO2AKTUF-O9T3t6ba.js +3 -0
  266. ksadk/server/static/assets/diagram-LMA3HP47-CGG8ekBO.js +24 -0
  267. ksadk/server/static/assets/diagram-OG6HWLK6-4BmH1EEg.js +24 -0
  268. ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
  269. ksadk/server/static/assets/dist-6kSZvCZh.js +1 -0
  270. ksadk/server/static/assets/dist-B67uF2uK.js +1 -0
  271. ksadk/server/static/assets/dist-BMKM66B4.js +1 -0
  272. ksadk/server/static/assets/dist-BVzcWa6D.js +1 -0
  273. ksadk/server/static/assets/dist-Bk1l05Ni.js +1 -0
  274. ksadk/server/static/assets/dist-BkJjNih3.js +1 -0
  275. ksadk/server/static/assets/dist-BmuTWcm7.js +9 -0
  276. ksadk/server/static/assets/dist-C2DKRFVK.js +1 -0
  277. ksadk/server/static/assets/dist-CWiTDN_V.js +6 -0
  278. ksadk/server/static/assets/dist-CZ6C3x8B.js +23 -0
  279. ksadk/server/static/assets/dist-CiZHB6ZW.js +1 -0
  280. ksadk/server/static/assets/dist-Cp1_jKwf.js +1 -0
  281. ksadk/server/static/assets/dist-Cwhk4lwI.js +2 -0
  282. ksadk/server/static/assets/dist-D5JGcxBx.js +11 -0
  283. ksadk/server/static/assets/dist-D99wf6_X.js +1 -0
  284. ksadk/server/static/assets/dist-DCpZrjaK.js +1 -0
  285. ksadk/server/static/assets/dist-DI-oVAXw.js +1 -0
  286. ksadk/server/static/assets/dist-DLMjL01k.js +1 -0
  287. ksadk/server/static/assets/dist-DLeM1OCK.js +1 -0
  288. ksadk/server/static/assets/dist-DM0rEQPk.js +1 -0
  289. ksadk/server/static/assets/dist-DbaH3p5h.js +1 -0
  290. ksadk/server/static/assets/dist-S4klkK5W.js +1 -0
  291. ksadk/server/static/assets/dockerfile-BLkNEvjs.js +1 -0
  292. ksadk/server/static/assets/dtd-DTF72YNO.js +1 -0
  293. ksadk/server/static/assets/dylan-C6jEEEk-.js +1 -0
  294. ksadk/server/static/assets/ebnf-D4c0_ac3.js +1 -0
  295. ksadk/server/static/assets/ecl-BSZaIHnp.js +1 -0
  296. ksadk/server/static/assets/eiffel-BEjRio4Q.js +1 -0
  297. ksadk/server/static/assets/elm-Cshzl8qu.js +1 -0
  298. ksadk/server/static/assets/erDiagram-TEJ5UH35-oJhaci7S.js +85 -0
  299. ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
  300. ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +1 -0
  301. ksadk/server/static/assets/factor-D7LVTn2l.js +1 -0
  302. ksadk/server/static/assets/fcl-ClOhbFR7.js +1 -0
  303. ksadk/server/static/assets/flowDiagram-I6XJVG4X-DtTmUan-.js +162 -0
  304. ksadk/server/static/assets/forth-Cezjo90N.js +1 -0
  305. ksadk/server/static/assets/fortran-Bt6PBEDR.js +1 -0
  306. ksadk/server/static/assets/ganttDiagram-6RSMTGT7-BSsb_eij.js +292 -0
  307. ksadk/server/static/assets/gas-BHEdbvp9.js +1 -0
  308. ksadk/server/static/assets/gherkin-oBAE_ms0.js +1 -0
  309. ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +1 -0
  310. ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-BR5s6Pws.js +106 -0
  311. ksadk/server/static/assets/graphlib-B8gBHxth.js +1 -0
  312. ksadk/server/static/assets/groovy-BC3IOsC8.js +1 -0
  313. ksadk/server/static/assets/haskell-BRsoo5mP.js +1 -0
  314. ksadk/server/static/assets/haxe-DIz0ZZqd.js +1 -0
  315. ksadk/server/static/assets/http-CLVgA2GD.js +1 -0
  316. ksadk/server/static/assets/idl-BUZw3wgd.js +1 -0
  317. ksadk/server/static/assets/index-BH7-pC0B.js +165 -0
  318. ksadk/server/static/assets/index-DAURbCsP.css +1 -0
  319. ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +1 -0
  320. ksadk/server/static/assets/infoDiagram-5YYISTIA-DYPc5cvh.js +2 -0
  321. ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
  322. ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-MoBdALDg.js +70 -0
  323. ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
  324. ksadk/server/static/assets/journeyDiagram-JHISSGLW-DgLiQT8l.js +139 -0
  325. ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
  326. ksadk/server/static/assets/kanban-definition-UN3LZRKU-CsFx112F.js +89 -0
  327. ksadk/server/static/assets/katex-DRsiwpM2.js +265 -0
  328. ksadk/server/static/assets/linear-TNRQ5Orv.js +1 -0
  329. ksadk/server/static/assets/livescript-BXxG0Yva.js +1 -0
  330. ksadk/server/static/assets/lua-CiA1ziua.js +1 -0
  331. ksadk/server/static/assets/mathematica-u8YMmbU0.js +1 -0
  332. ksadk/server/static/assets/mbox-BEMVcqjs.js +1 -0
  333. ksadk/server/static/assets/mermaid-parser.core-D2eMVOgo.js +161 -0
  334. ksadk/server/static/assets/mindmap-definition-RKZ34NQL-BtByYFhL.js +96 -0
  335. ksadk/server/static/assets/mirc-C9zpzAZU.js +1 -0
  336. ksadk/server/static/assets/mllike-B45xgp2S.js +1 -0
  337. ksadk/server/static/assets/modelica-CqHI_q-D.js +1 -0
  338. ksadk/server/static/assets/mscgen-qgSLujhx.js +1 -0
  339. ksadk/server/static/assets/mumps-CW_TBmxz.js +1 -0
  340. ksadk/server/static/assets/nginx-BMaDbqW3.js +1 -0
  341. ksadk/server/static/assets/nsis-AQ_alPln.js +1 -0
  342. ksadk/server/static/assets/ntriples-d28e9m0E.js +1 -0
  343. ksadk/server/static/assets/octave-D2Q8cUp1.js +1 -0
  344. ksadk/server/static/assets/ordinal-hYBb2elL.js +1 -0
  345. ksadk/server/static/assets/oz-BwTct_5T.js +1 -0
  346. ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +1 -0
  347. ksadk/server/static/assets/pascal-Dp_KdFgX.js +1 -0
  348. ksadk/server/static/assets/perl-CdEHsPfU.js +1 -0
  349. ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +1 -0
  350. ksadk/server/static/assets/pieDiagram-4H26LBE5-DPnuCB8c.js +30 -0
  351. ksadk/server/static/assets/pig-AF4Hwhju.js +1 -0
  352. ksadk/server/static/assets/powershell-CzG71I4L.js +1 -0
  353. ksadk/server/static/assets/properties-C357ku5U.js +1 -0
  354. ksadk/server/static/assets/protobuf-D1ij_kNL.js +1 -0
  355. ksadk/server/static/assets/pug-Bugr-47h.js +1 -0
  356. ksadk/server/static/assets/puppet-B4hC2X4m.js +1 -0
  357. ksadk/server/static/assets/python-BqYw9LYJ.js +1 -0
  358. ksadk/server/static/assets/q-B9NhS7L_.js +1 -0
  359. ksadk/server/static/assets/quadrantDiagram-W4KKPZXB-miFpCPv4.js +7 -0
  360. ksadk/server/static/assets/r-DADKenSm.js +1 -0
  361. ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +1 -0
  362. ksadk/server/static/assets/requirementDiagram-4Y6WPE33-mjB_yYkW.js +84 -0
  363. ksadk/server/static/assets/rpm-gpDK5sbt.js +1 -0
  364. ksadk/server/static/assets/ruby-DsYpTuWg.js +1 -0
  365. ksadk/server/static/assets/sankeyDiagram-5OEKKPKP-D7hSlZZZ.js +40 -0
  366. ksadk/server/static/assets/sas-C2OyD2Y6.js +1 -0
  367. ksadk/server/static/assets/scheme-CyDdOh7e.js +1 -0
  368. ksadk/server/static/assets/sequenceDiagram-3UESZ5HK-D9Cx6hC3.js +162 -0
  369. ksadk/server/static/assets/shell-Du5Qg9im.js +1 -0
  370. ksadk/server/static/assets/sieve-BAxa3IjF.js +1 -0
  371. ksadk/server/static/assets/simple-mode-DRpGK0lJ.js +1 -0
  372. ksadk/server/static/assets/smalltalk-BLp5-jwC.js +1 -0
  373. ksadk/server/static/assets/solr-BBopId9w.js +1 -0
  374. ksadk/server/static/assets/sparql-Dz-mlCAC.js +1 -0
  375. ksadk/server/static/assets/spreadsheet-CTIncYxj.js +1 -0
  376. ksadk/server/static/assets/sql-DcCJ9jop.js +1 -0
  377. ksadk/server/static/assets/stateDiagram-AJRCARHV-D_zrg47o.js +1 -0
  378. ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +1 -0
  379. ksadk/server/static/assets/stex-sDrdk2BW.js +1 -0
  380. ksadk/server/static/assets/stylus-DLLZ8dgm.js +1 -0
  381. ksadk/server/static/assets/swift-DKB6_1j6.js +1 -0
  382. ksadk/server/static/assets/tcl-BGfruO1u.js +1 -0
  383. ksadk/server/static/assets/textile-DWBqthVk.js +1 -0
  384. ksadk/server/static/assets/tiddlywiki-VlUiK86J.js +1 -0
  385. ksadk/server/static/assets/tiki-CxVlf5KZ.js +1 -0
  386. ksadk/server/static/assets/timeline-definition-PNZ67QCA-CwSec0Wa.js +120 -0
  387. ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
  388. ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +1 -0
  389. ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +1 -0
  390. ksadk/server/static/assets/troff-C2dAgh7P.js +1 -0
  391. ksadk/server/static/assets/ttcn-BePYh-hG.js +1 -0
  392. ksadk/server/static/assets/ttcn-cfg-CY0aot7Q.js +1 -0
  393. ksadk/server/static/assets/turtle-BDLWE2cD.js +1 -0
  394. ksadk/server/static/assets/vb-BthdM_4N.js +1 -0
  395. ksadk/server/static/assets/vbscript-D9f6rSsU.js +1 -0
  396. ksadk/server/static/assets/velocity-CqftRsjg.js +1 -0
  397. ksadk/server/static/assets/vennDiagram-CIIHVFJN-agCVobiF.js +34 -0
  398. ksadk/server/static/assets/verilog-D-x6ne0Z.js +1 -0
  399. ksadk/server/static/assets/vhdl-CMrOq2q1.js +1 -0
  400. ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +1 -0
  401. ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-TmrlhWNt.js +78 -0
  402. ksadk/server/static/assets/webidl-D5jiJvOU.js +1 -0
  403. ksadk/server/static/assets/xquery-fj_R-kMw.js +1 -0
  404. ksadk/server/static/assets/xterm-DooSxjI5.js +36 -0
  405. ksadk/server/static/assets/xychartDiagram-2RQKCTM6-DV71V-ah.js +7 -0
  406. ksadk/server/static/assets/yacas-CXXgtw0p.js +1 -0
  407. ksadk/server/static/assets/z80-CL1naaMV.js +1 -0
  408. ksadk/server/static/favicon.svg +1 -0
  409. ksadk/server/static/icons.svg +24 -0
  410. ksadk/server/static/index.html +14 -0
  411. ksadk/server/terminal_sessions.py +551 -0
  412. ksadk/sessions/__init__.py +283 -0
  413. ksadk/sessions/base.py +354 -0
  414. ksadk/sessions/continuity.py +313 -0
  415. ksadk/sessions/errors.py +7 -0
  416. ksadk/sessions/in_memory.py +273 -0
  417. ksadk/sessions/local_service.py +949 -0
  418. ksadk/sessions/postgres_service.py +838 -0
  419. ksadk/sessions/sqlite_service.py +13 -0
  420. ksadk/skills/__init__.py +9 -0
  421. ksadk/skills/loader.py +46 -0
  422. ksadk/skills/models.py +120 -0
  423. ksadk/skills/package_store.py +104 -0
  424. ksadk/skills/runtime/__init__.py +17 -0
  425. ksadk/skills/runtime/agent.py +183 -0
  426. ksadk/skills/runtime/artifacts.py +39 -0
  427. ksadk/skills/runtime/backends/__init__.py +1 -0
  428. ksadk/skills/runtime/backends/disabled.py +8 -0
  429. ksadk/skills/runtime/backends/e2b.py +168 -0
  430. ksadk/skills/runtime/backends/local.py +95 -0
  431. ksadk/skills/runtime/base.py +103 -0
  432. ksadk/skills/runtime/executor.py +219 -0
  433. ksadk/skills/runtime/factory.py +37 -0
  434. ksadk/skills/runtime/loader.py +131 -0
  435. ksadk/skills/runtime/registry.py +150 -0
  436. ksadk/skills/runtime/request.py +67 -0
  437. ksadk/skills/service_client.py +239 -0
  438. ksadk/skills/service_env.py +58 -0
  439. ksadk/skills/tool_defs.py +221 -0
  440. ksadk/terminal_client.py +69 -0
  441. ksadk/terminal_exec_policy.py +229 -0
  442. ksadk/tools/__init__.py +17 -0
  443. ksadk/tools/gateway.py +230 -0
  444. ksadk/tools/result_budget.py +154 -0
  445. ksadk/toolsets/__init__.py +852 -0
  446. ksadk/toolsets/_langchain.py +11 -0
  447. ksadk/toolsets/platform.py +93 -0
  448. ksadk/toolsets/sandbox.py +310 -0
  449. ksadk/toolsets/skills.py +217 -0
  450. ksadk/toolsets/web.py +266 -0
  451. ksadk/toolsets/workspace.py +878 -0
  452. ksadk/toolsets/workspace_state.py +44 -0
  453. ksadk/tracing/__init__.py +37 -0
  454. ksadk/tracing/exporters/__init__.py +1 -0
  455. ksadk/tracing/exporters/inmemory_exporter.py +116 -0
  456. ksadk/tracing/exporters/langfuse_exporter.py +445 -0
  457. ksadk/tracing/setup.py +829 -0
  458. ksadk/tracing/span_utils.py +114 -0
  459. ksadk/tui/__init__.py +12 -0
  460. ksadk/tui/app.py +400 -0
  461. ksadk/tui/clipboard.py +100 -0
  462. ksadk/tui/widgets/__init__.py +22 -0
  463. ksadk/tui/widgets/assistant.py +89 -0
  464. ksadk/tui/widgets/base.py +54 -0
  465. ksadk/tui/widgets/chat_input.py +246 -0
  466. ksadk/tui/widgets/history.py +156 -0
  467. ksadk/tui/widgets/system.py +87 -0
  468. ksadk/tui/widgets/thinking.py +110 -0
  469. ksadk/tui/widgets/tool_call.py +161 -0
  470. ksadk/tui/widgets/user.py +37 -0
  471. ksadk/ui_config.py +168 -0
  472. ksadk/version.py +4 -0
  473. ksadk_runtime_common/__init__.py +20 -0
  474. ksadk_runtime_common/memory_backend/__init__.py +29 -0
  475. ksadk_runtime_common/memory_backend/manifest.py +79 -0
  476. ksadk_runtime_common/memory_backend/providers/__init__.py +6 -0
  477. ksadk_runtime_common/memory_backend/providers/lancedb.py +151 -0
  478. ksadk_runtime_common/memory_backend/providers/mem0.py +74 -0
  479. ksadk_runtime_common/memory_backend/registry.py +56 -0
  480. ksadk_runtime_common/memory_backend/render.py +71 -0
  481. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -0
  482. ksadk_runtime_common/workspace_files/__init__.py +29 -0
  483. ksadk_runtime_common/workspace_files/bootstrap.py +56 -0
  484. ksadk_runtime_common/workspace_files/constants.py +9 -0
  485. ksadk_runtime_common/workspace_files/path_utils.py +71 -0
  486. ksadk_runtime_common/workspace_files/preview.py +96 -0
  487. ksadk_runtime_common/workspace_files/router.py +254 -0
  488. agentengine_sdk_python-0.6.2.dist-info/METADATA +0 -46
  489. agentengine_sdk_python-0.6.2.dist-info/RECORD +0 -4
  490. agentengine_sdk_python-0.6.2.dist-info/top_level.txt +0 -1
@@ -0,0 +1,838 @@
1
+ """PostgreSQL shared session backend for production multi-pod runtimes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import json
7
+ import time
8
+ from typing import Any, Optional
9
+ from urllib.parse import urlsplit, urlunsplit
10
+
11
+ from ksadk.sessions.base import (
12
+ BaseSessionService,
13
+ Session,
14
+ SessionEvent,
15
+ SessionState,
16
+ generate_id,
17
+ )
18
+ from ksadk.sessions.errors import SessionBackendUnavailable
19
+
20
+ KSADK_PG_SESSIONS_TABLE = "ksadk_sessions"
21
+ KSADK_PG_EVENTS_TABLE = "ksadk_events"
22
+ KSADK_PG_STATES_TABLE = "ksadk_states"
23
+
24
+
25
+ class PostgresSessionService(BaseSessionService):
26
+ def __init__(
27
+ self,
28
+ *,
29
+ dsn: str,
30
+ namespace: str = "default",
31
+ tenant_id: str = "default",
32
+ workspace_id: str = "default",
33
+ min_size: int = 1,
34
+ max_size: int = 10,
35
+ connect_timeout: float = 5.0,
36
+ ):
37
+ if not dsn.strip():
38
+ raise ValueError("KSADK_SESSION_DSN is required when KSADK_SESSION_BACKEND=postgres")
39
+ self.dsn = dsn.strip()
40
+ self.namespace = namespace.strip() or "default"
41
+ self.tenant_id = tenant_id.strip() or "default"
42
+ self.workspace_id = workspace_id.strip() or "default"
43
+ self.min_size = min_size
44
+ self.max_size = max_size
45
+ self.connect_timeout = connect_timeout
46
+ self._pool: Any = None
47
+ self._pool_lock = asyncio.Lock()
48
+ self._schema_ready = False
49
+ self._schema_lock = asyncio.Lock()
50
+
51
+ async def create_session(
52
+ self,
53
+ agent_id: str,
54
+ user_id: str,
55
+ session_id: Optional[str] = None,
56
+ ) -> Session:
57
+ await self._ensure_schema()
58
+ session_key = session_id or generate_id()
59
+ async with self._pool.acquire() as connection:
60
+ async with connection.transaction():
61
+ existing = await self._get_session_with_connection(connection, session_key)
62
+ if existing is not None:
63
+ return existing
64
+
65
+ now = time.time()
66
+ await connection.execute(
67
+ f"""
68
+ INSERT INTO {KSADK_PG_SESSIONS_TABLE} (
69
+ namespace, tenant_id, workspace_id, id, agent_id, user_id, title, title_source, summary,
70
+ first_prompt, last_prompt, state_json, created_at, updated_at, version
71
+ )
72
+ VALUES ($1, $2, $3, $4, $5, $6, '', '', '', '', '', $7::jsonb, $8, $9, 0)
73
+ """,
74
+ self.namespace,
75
+ self.tenant_id,
76
+ self.workspace_id,
77
+ session_key,
78
+ agent_id,
79
+ user_id,
80
+ "{}",
81
+ now,
82
+ now,
83
+ )
84
+ await connection.execute(
85
+ f"""
86
+ INSERT INTO {KSADK_PG_STATES_TABLE} (
87
+ namespace, tenant_id, workspace_id, scope, agent_id, user_id, session_id, state_json, version, updated_at
88
+ )
89
+ VALUES ($1, $2, $3, 'session', $4, $5, $6, $7::jsonb, 0, $8)
90
+ ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
91
+ DO NOTHING
92
+ """,
93
+ self.namespace,
94
+ self.tenant_id,
95
+ self.workspace_id,
96
+ agent_id,
97
+ user_id,
98
+ session_key,
99
+ "{}",
100
+ now,
101
+ )
102
+ return Session(
103
+ id=session_key,
104
+ agent_id=agent_id,
105
+ user_id=user_id,
106
+ created_at=now,
107
+ updated_at=now,
108
+ )
109
+
110
+ async def get_session(self, session_id: str) -> Optional[Session]:
111
+ await self._ensure_schema()
112
+ async with self._pool.acquire() as connection:
113
+ return await self._get_session_with_connection(connection, session_id)
114
+
115
+ async def list_sessions(
116
+ self,
117
+ agent_id: str,
118
+ user_id: Optional[str] = None,
119
+ offset: Optional[int] = None,
120
+ limit: Optional[int] = None,
121
+ ) -> list[Session]:
122
+ await self._ensure_schema()
123
+ async with self._pool.acquire() as connection:
124
+ query = f"""
125
+ SELECT id, agent_id, user_id, title, title_source, summary, first_prompt, last_prompt,
126
+ state_json, created_at, updated_at, version
127
+ FROM {KSADK_PG_SESSIONS_TABLE}
128
+ WHERE namespace = $1 AND agent_id = $2
129
+ """
130
+ params: list[Any] = [self.namespace, agent_id]
131
+ if user_id is not None:
132
+ params.append(user_id)
133
+ query += f" AND user_id = ${len(params)}"
134
+ query += " ORDER BY updated_at DESC, created_at DESC"
135
+ if limit is not None:
136
+ params.append(limit)
137
+ query += f" LIMIT ${len(params)}"
138
+ if offset is not None:
139
+ params.append(offset)
140
+ query += f" OFFSET ${len(params)}"
141
+ elif offset is not None:
142
+ params.append(offset)
143
+ query += f" OFFSET ${len(params)}"
144
+ rows = await connection.fetch(query, *params)
145
+ return [self._session_from_row(row, events=[]) for row in rows]
146
+
147
+ async def count_sessions(
148
+ self,
149
+ agent_id: str,
150
+ user_id: Optional[str] = None,
151
+ ) -> int:
152
+ await self._ensure_schema()
153
+ async with self._pool.acquire() as connection:
154
+ query = f"""
155
+ SELECT COUNT(*) AS total
156
+ FROM {KSADK_PG_SESSIONS_TABLE}
157
+ WHERE namespace = $1 AND agent_id = $2
158
+ """
159
+ params: list[Any] = [self.namespace, agent_id]
160
+ if user_id is not None:
161
+ params.append(user_id)
162
+ query += f" AND user_id = ${len(params)}"
163
+ return int(await connection.fetchval(query, *params) or 0)
164
+
165
+ async def delete_session(self, session_id: str) -> bool:
166
+ await self._ensure_schema()
167
+ async with self._pool.acquire() as connection:
168
+ async with connection.transaction():
169
+ await connection.execute(
170
+ f"""
171
+ DELETE FROM {KSADK_PG_STATES_TABLE}
172
+ WHERE namespace = $1 AND session_id = $2
173
+ """,
174
+ self.namespace,
175
+ session_id,
176
+ )
177
+ result = await connection.execute(
178
+ f"""
179
+ DELETE FROM {KSADK_PG_SESSIONS_TABLE}
180
+ WHERE namespace = $1 AND id = $2
181
+ """,
182
+ self.namespace,
183
+ session_id,
184
+ )
185
+ return not result.endswith(" 0")
186
+
187
+ async def update_session_metadata(
188
+ self,
189
+ session_id: str,
190
+ *,
191
+ title: Optional[str] = None,
192
+ title_source: Optional[str] = None,
193
+ summary: Optional[str] = None,
194
+ first_prompt: Optional[str] = None,
195
+ last_prompt: Optional[str] = None,
196
+ ) -> Session:
197
+ await self._ensure_schema()
198
+ async with self._pool.acquire() as connection:
199
+ async with connection.transaction():
200
+ row = await connection.fetchrow(
201
+ f"""
202
+ SELECT id, agent_id, user_id, title, title_source, summary, first_prompt, last_prompt,
203
+ state_json, created_at, updated_at, version
204
+ FROM {KSADK_PG_SESSIONS_TABLE}
205
+ WHERE namespace = $1 AND id = $2
206
+ FOR UPDATE
207
+ """,
208
+ self.namespace,
209
+ session_id,
210
+ )
211
+ if row is None:
212
+ raise ValueError(f"Session {session_id} not found")
213
+ updated_at = time.time()
214
+ next_title = row["title"] if title is None else title
215
+ next_title_source = row["title_source"] if title_source is None else title_source
216
+ next_summary = row["summary"] if summary is None else summary
217
+ next_first_prompt = row["first_prompt"] if first_prompt is None else first_prompt
218
+ next_last_prompt = row["last_prompt"] if last_prompt is None else last_prompt
219
+ await connection.execute(
220
+ f"""
221
+ UPDATE {KSADK_PG_SESSIONS_TABLE}
222
+ SET title = $1, title_source = $2, summary = $3, first_prompt = $4,
223
+ last_prompt = $5, updated_at = $6
224
+ WHERE namespace = $7 AND id = $8
225
+ """,
226
+ next_title,
227
+ next_title_source,
228
+ next_summary,
229
+ next_first_prompt,
230
+ next_last_prompt,
231
+ updated_at,
232
+ self.namespace,
233
+ session_id,
234
+ )
235
+ return Session(
236
+ id=row["id"],
237
+ agent_id=row["agent_id"],
238
+ user_id=row["user_id"],
239
+ title=next_title,
240
+ title_source=next_title_source,
241
+ summary=next_summary,
242
+ first_prompt=next_first_prompt,
243
+ last_prompt=next_last_prompt,
244
+ state=self._json_to_dict(row["state_json"]),
245
+ created_at=row["created_at"],
246
+ updated_at=updated_at,
247
+ version=row["version"],
248
+ )
249
+
250
+ async def append_event(self, session_id: str, event: SessionEvent) -> SessionEvent:
251
+ await self._ensure_schema()
252
+ async with self._pool.acquire() as connection:
253
+ async with connection.transaction():
254
+ session_row = await connection.fetchrow(
255
+ f"""
256
+ SELECT agent_id, user_id, state_json, version
257
+ FROM {KSADK_PG_SESSIONS_TABLE}
258
+ WHERE namespace = $1 AND id = $2
259
+ FOR UPDATE
260
+ """,
261
+ self.namespace,
262
+ session_id,
263
+ )
264
+ if session_row is None:
265
+ raise ValueError(f"Session {session_id} not found")
266
+
267
+ next_seq = await connection.fetchval(
268
+ f"""
269
+ SELECT COALESCE(MAX(seq_id), 0) + 1
270
+ FROM {KSADK_PG_EVENTS_TABLE}
271
+ WHERE namespace = $1 AND session_id = $2
272
+ """,
273
+ self.namespace,
274
+ session_id,
275
+ )
276
+ stored = SessionEvent(
277
+ id=event.id or generate_id(),
278
+ session_id=session_id,
279
+ author=event.author,
280
+ event_type=event.event_type,
281
+ content=dict(event.content),
282
+ timestamp=event.timestamp,
283
+ state_delta=dict(event.state_delta),
284
+ seq_id=int(next_seq or 1),
285
+ invocation_id=event.invocation_id,
286
+ metadata=dict(event.metadata),
287
+ )
288
+ await connection.execute(
289
+ f"""
290
+ INSERT INTO {KSADK_PG_EVENTS_TABLE} (
291
+ namespace, tenant_id, workspace_id, id, session_id, author, event_type, content_json, timestamp,
292
+ state_delta_json, seq_id, invocation_id, metadata_json
293
+ )
294
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10::jsonb, $11, $12, $13::jsonb)
295
+ """,
296
+ self.namespace,
297
+ self.tenant_id,
298
+ self.workspace_id,
299
+ stored.id,
300
+ stored.session_id,
301
+ stored.author,
302
+ stored.event_type,
303
+ json.dumps(stored.content),
304
+ stored.timestamp,
305
+ json.dumps(stored.state_delta),
306
+ stored.seq_id,
307
+ stored.invocation_id,
308
+ json.dumps(stored.metadata),
309
+ )
310
+
311
+ updated_at = time.time()
312
+ state = self._json_to_dict(session_row["state_json"])
313
+ version = int(session_row["version"] or 0)
314
+ if stored.state_delta:
315
+ state.update(stored.state_delta)
316
+ version += 1
317
+ await self._write_session_state(
318
+ connection,
319
+ session_id=session_id,
320
+ agent_id=session_row["agent_id"],
321
+ user_id=session_row["user_id"],
322
+ state=state,
323
+ version=version,
324
+ updated_at=updated_at,
325
+ )
326
+ return stored
327
+
328
+ async def get_events(
329
+ self,
330
+ session_id: str,
331
+ offset: Optional[int] = None,
332
+ limit: Optional[int] = None,
333
+ after_seq_id: Optional[int] = None,
334
+ before_seq_id: Optional[int] = None,
335
+ ) -> list[SessionEvent]:
336
+ await self._ensure_schema()
337
+ # seq 过滤先应用,再对结果集应用"最新 N 条" offset/limit 语义。
338
+ conditions = ["namespace = $1", "session_id = $2"]
339
+ params: list[Any] = [self.namespace, session_id]
340
+ if after_seq_id is not None:
341
+ params.append(after_seq_id)
342
+ conditions.append(f"seq_id > ${len(params)}")
343
+ if before_seq_id is not None:
344
+ params.append(before_seq_id)
345
+ conditions.append(f"seq_id < ${len(params)}")
346
+ where_clause = " AND ".join(conditions)
347
+ async with self._pool.acquire() as connection:
348
+ if limit is not None:
349
+ params.extend([limit, offset or 0])
350
+ limit_param = len(params) - 1
351
+ offset_param = len(params)
352
+ query = f"""
353
+ SELECT id, session_id, author, event_type, content_json, timestamp,
354
+ state_delta_json, seq_id, invocation_id, metadata_json
355
+ FROM (
356
+ SELECT id, session_id, author, event_type, content_json, timestamp,
357
+ state_delta_json, seq_id, invocation_id, metadata_json
358
+ FROM {KSADK_PG_EVENTS_TABLE}
359
+ WHERE {where_clause}
360
+ ORDER BY seq_id DESC
361
+ LIMIT ${limit_param} OFFSET ${offset_param}
362
+ ) AS latest_events
363
+ ORDER BY seq_id ASC
364
+ """
365
+ elif offset is not None:
366
+ params.append(offset)
367
+ offset_param = len(params)
368
+ query = f"""
369
+ SELECT id, session_id, author, event_type, content_json, timestamp,
370
+ state_delta_json, seq_id, invocation_id, metadata_json
371
+ FROM (
372
+ SELECT id, session_id, author, event_type, content_json, timestamp,
373
+ state_delta_json, seq_id, invocation_id, metadata_json
374
+ FROM {KSADK_PG_EVENTS_TABLE}
375
+ WHERE {where_clause}
376
+ ORDER BY seq_id DESC
377
+ OFFSET ${offset_param}
378
+ ) AS latest_events
379
+ ORDER BY seq_id ASC
380
+ """
381
+ else:
382
+ query = f"""
383
+ SELECT id, session_id, author, event_type, content_json, timestamp,
384
+ state_delta_json, seq_id, invocation_id, metadata_json
385
+ FROM {KSADK_PG_EVENTS_TABLE}
386
+ WHERE {where_clause}
387
+ ORDER BY seq_id ASC
388
+ """
389
+ rows = await connection.fetch(query, *params)
390
+ return [self._event_from_row(row) for row in rows]
391
+
392
+ async def count_events(
393
+ self,
394
+ session_id: str,
395
+ after_seq_id: Optional[int] = None,
396
+ before_seq_id: Optional[int] = None,
397
+ ) -> int:
398
+ await self._ensure_schema()
399
+ conditions = ["namespace = $1", "session_id = $2"]
400
+ params: list[Any] = [self.namespace, session_id]
401
+ if after_seq_id is not None:
402
+ params.append(after_seq_id)
403
+ conditions.append(f"seq_id > ${len(params)}")
404
+ if before_seq_id is not None:
405
+ params.append(before_seq_id)
406
+ conditions.append(f"seq_id < ${len(params)}")
407
+ where_clause = " AND ".join(conditions)
408
+ async with self._pool.acquire() as connection:
409
+ query = f"""
410
+ SELECT COUNT(*) AS total
411
+ FROM {KSADK_PG_EVENTS_TABLE}
412
+ WHERE {where_clause}
413
+ """
414
+ return int(await connection.fetchval(query, *params) or 0)
415
+
416
+ async def get_state(
417
+ self,
418
+ agent_id: str,
419
+ user_id: Optional[str],
420
+ session_id: Optional[str],
421
+ scope: str = "session",
422
+ ) -> Optional[SessionState]:
423
+ await self._ensure_schema()
424
+ async with self._pool.acquire() as connection:
425
+ if scope == "session" and session_id:
426
+ session = await self._get_session_with_connection(connection, session_id)
427
+ if session is None:
428
+ return None
429
+ return SessionState(
430
+ scope="session",
431
+ agent_id=session.agent_id,
432
+ user_id=session.user_id,
433
+ session_id=session.id,
434
+ state=dict(session.state),
435
+ version=session.version,
436
+ updated_at=session.updated_at,
437
+ )
438
+ row = await connection.fetchrow(
439
+ f"""
440
+ SELECT scope, agent_id, user_id, session_id, state_json, version, updated_at
441
+ FROM {KSADK_PG_STATES_TABLE}
442
+ WHERE namespace = $1 AND scope = $2 AND agent_id = $3 AND user_id = $4 AND session_id = $5
443
+ """,
444
+ self.namespace,
445
+ scope,
446
+ agent_id,
447
+ user_id or "",
448
+ session_id or "",
449
+ )
450
+ if row is None:
451
+ return None
452
+ return self._state_from_row(row)
453
+
454
+ async def update_state(
455
+ self,
456
+ *,
457
+ agent_id: str,
458
+ user_id: Optional[str],
459
+ session_id: Optional[str],
460
+ scope: str,
461
+ state_delta: dict[str, Any],
462
+ ) -> SessionState:
463
+ await self._ensure_schema()
464
+ async with self._pool.acquire() as connection:
465
+ async with connection.transaction():
466
+ updated_at = time.time()
467
+ if scope == "session":
468
+ if not session_id:
469
+ raise ValueError("session_id is required for session scope")
470
+ session = await self._get_session_with_connection(
471
+ connection,
472
+ session_id,
473
+ for_update=True,
474
+ )
475
+ if session is None:
476
+ raise ValueError(f"Session {session_id} not found")
477
+ next_state = dict(session.state)
478
+ next_state.update(state_delta)
479
+ next_version = session.version + 1
480
+ await self._write_session_state(
481
+ connection,
482
+ session_id=session.id,
483
+ agent_id=session.agent_id,
484
+ user_id=session.user_id,
485
+ state=next_state,
486
+ version=next_version,
487
+ updated_at=updated_at,
488
+ )
489
+ return SessionState(
490
+ scope="session",
491
+ agent_id=session.agent_id,
492
+ user_id=session.user_id,
493
+ session_id=session.id,
494
+ state=next_state,
495
+ version=next_version,
496
+ updated_at=updated_at,
497
+ )
498
+
499
+ row = await connection.fetchrow(
500
+ f"""
501
+ SELECT state_json, version
502
+ FROM {KSADK_PG_STATES_TABLE}
503
+ WHERE namespace = $1 AND scope = $2 AND agent_id = $3 AND user_id = $4 AND session_id = $5
504
+ FOR UPDATE
505
+ """,
506
+ self.namespace,
507
+ scope,
508
+ agent_id,
509
+ user_id or "",
510
+ session_id or "",
511
+ )
512
+ next_state = self._json_to_dict(row["state_json"]) if row else {}
513
+ next_state.update(state_delta)
514
+ next_version = (int(row["version"] or 0) + 1) if row else 1
515
+ await connection.execute(
516
+ f"""
517
+ INSERT INTO {KSADK_PG_STATES_TABLE} (
518
+ namespace, tenant_id, workspace_id, scope, agent_id, user_id, session_id, state_json, version, updated_at
519
+ )
520
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10)
521
+ ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
522
+ DO UPDATE SET state_json = EXCLUDED.state_json,
523
+ version = EXCLUDED.version,
524
+ updated_at = EXCLUDED.updated_at
525
+ """,
526
+ self.namespace,
527
+ self.tenant_id,
528
+ self.workspace_id,
529
+ scope,
530
+ agent_id,
531
+ user_id or "",
532
+ session_id or "",
533
+ json.dumps(next_state),
534
+ next_version,
535
+ updated_at,
536
+ )
537
+ return SessionState(
538
+ scope=scope,
539
+ agent_id=agent_id,
540
+ user_id=user_id or "",
541
+ session_id=session_id or "",
542
+ state=next_state,
543
+ version=next_version,
544
+ updated_at=updated_at,
545
+ )
546
+
547
+ async def aclose(self) -> None:
548
+ if self._pool is not None:
549
+ await self._pool.close()
550
+ self._pool = None
551
+ self._schema_ready = False
552
+
553
+ async def _ensure_pool(self) -> None:
554
+ if self._pool is not None:
555
+ return
556
+ async with self._pool_lock:
557
+ if self._pool is not None:
558
+ return
559
+ try:
560
+ import asyncpg
561
+ except ImportError as exc:
562
+ raise RuntimeError(
563
+ "asyncpg is required for KSADK_SESSION_BACKEND=postgres"
564
+ ) from exc
565
+ try:
566
+ self._pool = await asyncpg.create_pool(
567
+ dsn=self.dsn,
568
+ min_size=self.min_size,
569
+ max_size=self.max_size,
570
+ timeout=self.connect_timeout,
571
+ )
572
+ except (TimeoutError, OSError, ConnectionError, asyncio.TimeoutError) as exc:
573
+ raise SessionBackendUnavailable(
574
+ "Postgres session backend unavailable: "
575
+ f"could not connect to {mask_postgres_session_dsn(self.dsn)}"
576
+ ) from exc
577
+
578
+ async def _ensure_schema(self) -> None:
579
+ if self._schema_ready:
580
+ return
581
+ async with self._schema_lock:
582
+ if self._schema_ready:
583
+ return
584
+ await self._ensure_pool()
585
+ async with self._pool.acquire() as connection:
586
+ await connection.execute(
587
+ f"""
588
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_SESSIONS_TABLE} (
589
+ namespace TEXT NOT NULL,
590
+ tenant_id TEXT NOT NULL DEFAULT 'default',
591
+ workspace_id TEXT NOT NULL DEFAULT 'default',
592
+ id TEXT NOT NULL,
593
+ agent_id TEXT NOT NULL,
594
+ user_id TEXT NOT NULL,
595
+ title TEXT NOT NULL DEFAULT '',
596
+ title_source TEXT NOT NULL DEFAULT '',
597
+ summary TEXT NOT NULL DEFAULT '',
598
+ first_prompt TEXT NOT NULL DEFAULT '',
599
+ last_prompt TEXT NOT NULL DEFAULT '',
600
+ state_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
601
+ created_at DOUBLE PRECISION NOT NULL,
602
+ updated_at DOUBLE PRECISION NOT NULL,
603
+ version INTEGER NOT NULL DEFAULT 0,
604
+ PRIMARY KEY (namespace, id)
605
+ );
606
+
607
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_EVENTS_TABLE} (
608
+ namespace TEXT NOT NULL,
609
+ tenant_id TEXT NOT NULL DEFAULT 'default',
610
+ workspace_id TEXT NOT NULL DEFAULT 'default',
611
+ id TEXT NOT NULL,
612
+ session_id TEXT NOT NULL,
613
+ author TEXT NOT NULL,
614
+ event_type TEXT NOT NULL,
615
+ content_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
616
+ timestamp DOUBLE PRECISION NOT NULL,
617
+ state_delta_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
618
+ seq_id INTEGER NOT NULL,
619
+ invocation_id TEXT,
620
+ metadata_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
621
+ PRIMARY KEY (namespace, id),
622
+ UNIQUE (namespace, session_id, seq_id),
623
+ FOREIGN KEY (namespace, session_id)
624
+ REFERENCES {KSADK_PG_SESSIONS_TABLE}(namespace, id)
625
+ ON DELETE CASCADE
626
+ );
627
+
628
+ CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_seq
629
+ ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, seq_id);
630
+
631
+ CREATE TABLE IF NOT EXISTS {KSADK_PG_STATES_TABLE} (
632
+ namespace TEXT NOT NULL,
633
+ tenant_id TEXT NOT NULL DEFAULT 'default',
634
+ workspace_id TEXT NOT NULL DEFAULT 'default',
635
+ scope TEXT NOT NULL,
636
+ agent_id TEXT NOT NULL,
637
+ user_id TEXT NOT NULL DEFAULT '',
638
+ session_id TEXT NOT NULL DEFAULT '',
639
+ state_json JSONB NOT NULL DEFAULT '{{}}'::jsonb,
640
+ version INTEGER NOT NULL DEFAULT 0,
641
+ updated_at DOUBLE PRECISION NOT NULL,
642
+ PRIMARY KEY (namespace, scope, agent_id, user_id, session_id)
643
+ );
644
+
645
+ ALTER TABLE {KSADK_PG_SESSIONS_TABLE}
646
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
647
+ ALTER TABLE {KSADK_PG_SESSIONS_TABLE}
648
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
649
+ ALTER TABLE {KSADK_PG_EVENTS_TABLE}
650
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
651
+ ALTER TABLE {KSADK_PG_EVENTS_TABLE}
652
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
653
+ ALTER TABLE {KSADK_PG_STATES_TABLE}
654
+ ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
655
+ ALTER TABLE {KSADK_PG_STATES_TABLE}
656
+ ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
657
+ """
658
+ )
659
+ self._schema_ready = True
660
+
661
+ async def _get_session_with_connection(
662
+ self,
663
+ connection: Any,
664
+ session_id: str,
665
+ *,
666
+ for_update: bool = False,
667
+ ) -> Optional[Session]:
668
+ lock_clause = " FOR UPDATE" if for_update else ""
669
+ row = await connection.fetchrow(
670
+ f"""
671
+ SELECT id, agent_id, user_id, title, title_source, summary, first_prompt, last_prompt,
672
+ state_json, created_at, updated_at, version
673
+ FROM {KSADK_PG_SESSIONS_TABLE}
674
+ WHERE namespace = $1 AND id = $2
675
+ {lock_clause}
676
+ """,
677
+ self.namespace,
678
+ session_id,
679
+ )
680
+ if row is None:
681
+ return None
682
+ events = [] if for_update else await self._get_events_with_connection(connection, session_id)
683
+ return self._session_from_row(row, events=events)
684
+
685
+ async def _get_events_with_connection(self, connection: Any, session_id: str) -> list[SessionEvent]:
686
+ rows = await connection.fetch(
687
+ f"""
688
+ SELECT id, session_id, author, event_type, content_json, timestamp,
689
+ state_delta_json, seq_id, invocation_id, metadata_json
690
+ FROM {KSADK_PG_EVENTS_TABLE}
691
+ WHERE namespace = $1 AND session_id = $2
692
+ ORDER BY seq_id ASC
693
+ """,
694
+ self.namespace,
695
+ session_id,
696
+ )
697
+ return [self._event_from_row(row) for row in rows]
698
+
699
+ async def _write_session_state(
700
+ self,
701
+ connection: Any,
702
+ *,
703
+ session_id: str,
704
+ agent_id: str,
705
+ user_id: str,
706
+ state: dict[str, Any],
707
+ version: int,
708
+ updated_at: float,
709
+ ) -> None:
710
+ await connection.execute(
711
+ f"""
712
+ UPDATE {KSADK_PG_SESSIONS_TABLE}
713
+ SET state_json = $1::jsonb, updated_at = $2, version = $3
714
+ WHERE namespace = $4 AND id = $5
715
+ """,
716
+ json.dumps(state),
717
+ updated_at,
718
+ version,
719
+ self.namespace,
720
+ session_id,
721
+ )
722
+ await connection.execute(
723
+ f"""
724
+ INSERT INTO {KSADK_PG_STATES_TABLE} (
725
+ namespace, tenant_id, workspace_id, scope, agent_id, user_id, session_id, state_json, version, updated_at
726
+ )
727
+ VALUES ($1, $2, $3, 'session', $4, $5, $6, $7::jsonb, $8, $9)
728
+ ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
729
+ DO UPDATE SET state_json = EXCLUDED.state_json,
730
+ version = EXCLUDED.version,
731
+ updated_at = EXCLUDED.updated_at
732
+ """,
733
+ self.namespace,
734
+ self.tenant_id,
735
+ self.workspace_id,
736
+ agent_id,
737
+ user_id,
738
+ session_id,
739
+ json.dumps(state),
740
+ version,
741
+ updated_at,
742
+ )
743
+
744
+ @classmethod
745
+ def _session_from_row(cls, row: Any, *, events: list[SessionEvent]) -> Session:
746
+ return Session(
747
+ id=row["id"],
748
+ agent_id=row["agent_id"],
749
+ user_id=row["user_id"],
750
+ title=row["title"],
751
+ title_source=row["title_source"],
752
+ summary=row["summary"],
753
+ first_prompt=row["first_prompt"],
754
+ last_prompt=row["last_prompt"],
755
+ state=cls._json_to_dict(row["state_json"]),
756
+ events=events,
757
+ created_at=float(row["created_at"]),
758
+ updated_at=float(row["updated_at"]),
759
+ version=int(row["version"] or 0),
760
+ )
761
+
762
+ @classmethod
763
+ def _event_from_row(cls, row: Any) -> SessionEvent:
764
+ return SessionEvent(
765
+ id=row["id"],
766
+ session_id=row["session_id"],
767
+ author=row["author"],
768
+ event_type=row["event_type"],
769
+ content=cls._json_to_dict(row["content_json"]),
770
+ timestamp=float(row["timestamp"]),
771
+ state_delta=cls._json_to_dict(row["state_delta_json"]),
772
+ seq_id=int(row["seq_id"] or 0),
773
+ invocation_id=row["invocation_id"],
774
+ metadata=cls._json_to_dict(row["metadata_json"]),
775
+ )
776
+
777
+ @classmethod
778
+ def _state_from_row(cls, row: Any) -> SessionState:
779
+ return SessionState(
780
+ scope=row["scope"],
781
+ agent_id=row["agent_id"],
782
+ user_id=row["user_id"],
783
+ session_id=row["session_id"],
784
+ state=cls._json_to_dict(row["state_json"]),
785
+ version=int(row["version"] or 0),
786
+ updated_at=float(row["updated_at"]),
787
+ )
788
+
789
+ @staticmethod
790
+ def _json_to_dict(value: Any) -> dict[str, Any]:
791
+ if value is None:
792
+ return {}
793
+ if isinstance(value, dict):
794
+ return dict(value)
795
+ if isinstance(value, str):
796
+ return dict(json.loads(value or "{}"))
797
+ return dict(value)
798
+
799
+
800
+ def create_postgres_session_service(
801
+ *,
802
+ dsn: str,
803
+ namespace: str = "default",
804
+ tenant_id: str = "default",
805
+ workspace_id: str = "default",
806
+ ) -> PostgresSessionService:
807
+ return PostgresSessionService(
808
+ dsn=dsn,
809
+ namespace=namespace,
810
+ tenant_id=tenant_id,
811
+ workspace_id=workspace_id,
812
+ )
813
+
814
+
815
+ def mask_postgres_session_dsn(dsn: str) -> str:
816
+ if not dsn:
817
+ return ""
818
+ try:
819
+ parts = urlsplit(dsn)
820
+ except ValueError:
821
+ return "***"
822
+ if not parts.password:
823
+ return dsn
824
+ username = parts.username or ""
825
+ host = parts.hostname or ""
826
+ port = f":{parts.port}" if parts.port else ""
827
+ auth = f"{username}:***@" if username else "***@"
828
+ return urlunsplit((parts.scheme, f"{auth}{host}{port}", parts.path, parts.query, parts.fragment))
829
+
830
+
831
+ __all__ = [
832
+ "KSADK_PG_EVENTS_TABLE",
833
+ "KSADK_PG_SESSIONS_TABLE",
834
+ "KSADK_PG_STATES_TABLE",
835
+ "PostgresSessionService",
836
+ "create_postgres_session_service",
837
+ "mask_postgres_session_dsn",
838
+ ]