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,751 @@
1
+ """LangChain runner with session continuity aware input preparation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ import logging
7
+ import os
8
+ import uuid
9
+ from typing import Any, AsyncIterator, Dict, Optional
10
+
11
+ from ksadk.runners.base_runner import BaseRunner
12
+ from ksadk.runners.utils import (
13
+ get_langfuse_callbacks,
14
+ get_langfuse_metadata,
15
+ load_agent_module,
16
+ prepare_trace_metadata,
17
+ )
18
+ from ksadk.sessions.continuity import LangChainSessionAdapter
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class LangChainRunner(BaseRunner):
24
+ """LangChain framework runner."""
25
+
26
+ def load_agent(self) -> None:
27
+ self._load_agent(force_reload=False)
28
+
29
+ def _load_agent(self, *, force_reload: bool) -> None:
30
+ self._agent, self._module = load_agent_module(
31
+ self.project_dir,
32
+ self.detection_result.entry_point,
33
+ self.detection_result.agent_variable,
34
+ force_reload=force_reload,
35
+ )
36
+ self._loaded_model_name = self.normalize_requested_model(
37
+ os.getenv("OPENAI_MODEL_NAME") or os.getenv("MODEL_NAME")
38
+ )
39
+
40
+ def prepare_for_request(self, model: Optional[str]) -> None:
41
+ normalized = self.sync_process_model_env(model)
42
+ if normalized is None or self._agent is None:
43
+ return
44
+ if normalized == getattr(self, "_loaded_model_name", None):
45
+ return
46
+ self._load_agent(force_reload=True)
47
+
48
+ def get_session_adapter(self):
49
+ return LangChainSessionAdapter()
50
+
51
+ def _get_config(self, session_id: Optional[str] = None) -> Optional[dict[str, Any]]:
52
+ config: dict[str, Any] = {}
53
+
54
+ langfuse_callbacks = get_langfuse_callbacks()
55
+ if langfuse_callbacks:
56
+ config["callbacks"] = langfuse_callbacks
57
+
58
+ metadata = get_langfuse_metadata(session_id)
59
+ user_id, tags, _, _ = prepare_trace_metadata(session_id)
60
+ if user_id:
61
+ metadata["langfuse_user_id"] = user_id
62
+ if tags:
63
+ metadata["langfuse_tags"] = tags
64
+ config["metadata"] = metadata
65
+
66
+ return config or None
67
+
68
+ async def invoke(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
69
+ session_id = input_data.get("session_id") or str(uuid.uuid4())[:8]
70
+ path = self._resolve_request_path()
71
+ config = self._get_config(session_id)
72
+ native_context = self.build_native_context(input_data.get("platform_context"))
73
+
74
+ if path == "standard_hook":
75
+ payload = self._prepare_with_standard_hook(input_data, session_id)
76
+ result = await self._invoke_agent(payload, config=config, context=native_context)
77
+ elif path == "runnable_with_message_history":
78
+ result = await self._invoke_with_message_history(
79
+ input_data,
80
+ session_id,
81
+ config=config,
82
+ context=native_context,
83
+ )
84
+ else:
85
+ payload = self._prepare_with_replay(input_data)
86
+ result = await self._invoke_agent(payload, config=config, context=native_context)
87
+
88
+ output = {"output": self._extract_output(result)}
89
+ usage = self._extract_usage(result)
90
+ if usage:
91
+ output["usage"] = usage
92
+ last_usage = self._extract_last_usage(result)
93
+ if last_usage:
94
+ output.setdefault("metadata", {})["last_usage"] = last_usage
95
+ return output
96
+
97
+ async def stream(self, input_data: Dict[str, Any]) -> AsyncIterator[Dict[str, Any]]:
98
+ session_id = input_data.get("session_id") or str(uuid.uuid4())[:8]
99
+ path = self._resolve_request_path()
100
+ config = self._get_config(session_id)
101
+ native_context = self.build_native_context(input_data.get("platform_context"))
102
+
103
+ if path == "standard_hook":
104
+ payload = self._prepare_with_standard_hook(input_data, session_id)
105
+ elif path == "runnable_with_message_history":
106
+ payload = {"input": self._prepare_message_history_input(input_data)}
107
+ config = self._with_session_config(config, session_id)
108
+ else:
109
+ payload = self._prepare_with_replay(input_data)
110
+
111
+ accumulated_text = ""
112
+ last_chunk: Any = None
113
+ final_output_text = ""
114
+ emitted_non_text_event = False
115
+ message_snapshots: dict[str, str] = {}
116
+
117
+ try:
118
+ if self._should_stream_events(payload):
119
+ kwargs = self._build_optional_call_kwargs(
120
+ self._agent.astream_events,
121
+ config=config,
122
+ context=native_context,
123
+ )
124
+ kwargs["version"] = "v2"
125
+ async for event in self._agent.astream_events(payload, **kwargs):
126
+ if not isinstance(event, dict):
127
+ continue
128
+ event_kind = event.get("event", "")
129
+ data = event.get("data") or {}
130
+
131
+ if event_kind == "on_chat_model_stream":
132
+ chunk = data.get("chunk") if isinstance(data, dict) else None
133
+ if chunk is None:
134
+ continue
135
+ last_chunk = chunk
136
+ delta, chunk_type = self._extract_chunk(chunk)
137
+ if delta:
138
+ if chunk_type == "text":
139
+ accumulated_text += delta
140
+ else:
141
+ emitted_non_text_event = True
142
+ yield {"delta": delta, "type": chunk_type}
143
+ elif event_kind == "on_tool_start":
144
+ emitted_non_text_event = True
145
+ yield {
146
+ "type": "tool_call",
147
+ "tool_name": event.get("name", "unknown"),
148
+ "tool_args": data.get("input", {}) if isinstance(data, dict) else {},
149
+ "run_id": event.get("run_id"),
150
+ }
151
+ elif event_kind == "on_tool_end":
152
+ emitted_non_text_event = True
153
+ tool_output = data.get("output", "") if isinstance(data, dict) else ""
154
+ yield {
155
+ "type": "tool_result",
156
+ "tool_name": event.get("name", "unknown"),
157
+ "tool_args": data.get("input", {}) if isinstance(data, dict) else {},
158
+ "tool_output": (
159
+ tool_output
160
+ if isinstance(tool_output, dict)
161
+ else (str(tool_output) if tool_output else "")
162
+ ),
163
+ "run_id": event.get("run_id"),
164
+ }
165
+ elif event_kind == "on_chain_end":
166
+ output = data.get("output") if isinstance(data, dict) else None
167
+ extracted_output = self._extract_recognized_output(output)
168
+ if extracted_output:
169
+ final_output_text = extracted_output
170
+ if self._extract_usage(output):
171
+ last_chunk = output
172
+ elif hasattr(self._agent, "astream"):
173
+ kwargs = self._build_optional_call_kwargs(
174
+ self._agent.astream,
175
+ config=config,
176
+ context=native_context,
177
+ )
178
+ async for chunk in self._agent.astream(payload, **kwargs):
179
+ last_chunk = chunk
180
+ message_state = self._extract_message_state(chunk)
181
+ if message_state:
182
+ content, message_key = message_state
183
+ previous = message_snapshots.get(message_key, "")
184
+ delta = self._snapshot_delta(content, previous)
185
+ message_snapshots[message_key] = content
186
+ chunk_type = "text"
187
+ else:
188
+ delta, chunk_type = self._extract_chunk(chunk)
189
+ if delta:
190
+ accumulated_text += delta
191
+ yield {"delta": delta, "type": chunk_type}
192
+ elif hasattr(self._agent, "stream"):
193
+ kwargs = self._build_optional_call_kwargs(
194
+ self._agent.stream,
195
+ config=config,
196
+ context=native_context,
197
+ )
198
+ for chunk in self._agent.stream(payload, **kwargs):
199
+ last_chunk = chunk
200
+ message_state = self._extract_message_state(chunk)
201
+ if message_state:
202
+ content, message_key = message_state
203
+ previous = message_snapshots.get(message_key, "")
204
+ delta = self._snapshot_delta(content, previous)
205
+ message_snapshots[message_key] = content
206
+ chunk_type = "text"
207
+ else:
208
+ delta, chunk_type = self._extract_chunk(chunk)
209
+ if delta:
210
+ accumulated_text += delta
211
+ yield {"delta": delta, "type": chunk_type}
212
+ except Exception as exc:
213
+ logger.warning("LangChain stream failed: %s", exc)
214
+
215
+ if not accumulated_text:
216
+ if final_output_text or emitted_non_text_event:
217
+ final_chunk = {"output": final_output_text, "type": "final"}
218
+ usage = self._extract_usage(last_chunk)
219
+ if usage:
220
+ final_chunk["usage"] = usage
221
+ last_usage = self._extract_last_usage(last_chunk)
222
+ if last_usage:
223
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
224
+ yield final_chunk
225
+ return
226
+ result = await self.invoke(input_data)
227
+ final_chunk = {"output": result.get("output", ""), "type": "final"}
228
+ usage = self._extract_usage(result)
229
+ if usage:
230
+ final_chunk["usage"] = usage
231
+ last_usage = self._extract_last_usage(result)
232
+ if last_usage:
233
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
234
+ yield final_chunk
235
+ return
236
+
237
+ final_chunk = {"output": accumulated_text, "type": "final"}
238
+ usage = self._extract_usage(last_chunk)
239
+ if usage:
240
+ final_chunk["usage"] = usage
241
+ last_usage = self._extract_last_usage(last_chunk)
242
+ if last_usage:
243
+ final_chunk.setdefault("metadata", {})["last_usage"] = last_usage
244
+ yield final_chunk
245
+
246
+ def _should_stream_events(self, payload: dict[str, Any]) -> bool:
247
+ """Use LangGraph events for LangChain create_agent message-state agents."""
248
+ return isinstance(payload.get("messages"), list) and hasattr(
249
+ self._agent, "astream_events"
250
+ )
251
+
252
+ def _resolve_request_path(self) -> str:
253
+ module = getattr(self, "_module", None)
254
+ if callable(getattr(module, "ksadk_prepare_input", None)):
255
+ return "standard_hook"
256
+ if self._is_runnable_with_message_history():
257
+ return "runnable_with_message_history"
258
+ return "replay"
259
+
260
+ def _prepare_with_standard_hook(
261
+ self, input_data: Dict[str, Any], session_id: str
262
+ ) -> dict[str, Any]:
263
+ module = getattr(self, "_module", None)
264
+ prepare_input = getattr(module, "ksadk_prepare_input", None)
265
+ if not callable(prepare_input):
266
+ return {"input": input_data.get("input", "")}
267
+
268
+ payload = {"input": input_data.get("input", "")}
269
+ session_context = {
270
+ "session_id": session_id,
271
+ "history": list(input_data.get("history") or []),
272
+ "input_parts": list(input_data.get("input_parts") or []),
273
+ "attachments": list(input_data.get("attachments") or []),
274
+ "attachment_results": list(input_data.get("attachment_results") or []),
275
+ "instructions": input_data.get("instructions"),
276
+ "platform_context": input_data.get("platform_context"),
277
+ "kb_context": input_data.get("kb_context"),
278
+ "memory_context": input_data.get("memory_context"),
279
+ }
280
+ builtin_context = self._ksadk_builtin_tool_context()
281
+ if builtin_context:
282
+ session_context.update(builtin_context)
283
+ prepared = prepare_input(payload, session_context)
284
+ return prepared if isinstance(prepared, dict) else payload
285
+
286
+ @staticmethod
287
+ def _ksadk_builtin_tool_context() -> dict[str, Any]:
288
+ try:
289
+ from ksadk.toolsets import (
290
+ builtin_tool_descriptors_for_runtime,
291
+ builtin_tools_mode,
292
+ builtin_tools_profile,
293
+ )
294
+
295
+ mode = builtin_tools_mode(default="off")
296
+ descriptors = builtin_tool_descriptors_for_runtime(mode=mode)
297
+ if not descriptors:
298
+ return {}
299
+ return {
300
+ "ksadk_tools": descriptors,
301
+ "ksadk_builtin_tools_mode": mode,
302
+ "ksadk_builtin_tools_profile": builtin_tools_profile("default"),
303
+ "deferred_direct_injection_supported": False,
304
+ }
305
+ except Exception as exc:
306
+ logger.warning("Failed to prepare ksadk built-in tool descriptors: %s", exc)
307
+ return {}
308
+
309
+ def _prepare_with_replay(self, input_data: Dict[str, Any]) -> dict[str, Any]:
310
+ user_input = str(input_data.get("input", "") or "")
311
+ history = list(input_data.get("history") or [])
312
+ ambient_text = self._ambient_context_text(input_data)
313
+ instructions = str(input_data.get("instructions") or "").strip()
314
+ if not history and not ambient_text and not instructions:
315
+ return {"input": user_input}
316
+ return {
317
+ "input": self._format_replay_prompt(
318
+ user_input,
319
+ history,
320
+ ambient_text=ambient_text,
321
+ instructions=instructions,
322
+ )
323
+ }
324
+
325
+ @staticmethod
326
+ def _ambient_context_text(input_data: Dict[str, Any]) -> str:
327
+ sections: list[str] = []
328
+ kb_context = input_data.get("kb_context") or {}
329
+ kb_text = (
330
+ str(kb_context.get("formatted_text") or "").strip()
331
+ if isinstance(kb_context, dict)
332
+ else ""
333
+ )
334
+ if kb_text:
335
+ sections.append(f"Knowledge base context:\n{kb_text}")
336
+
337
+ memory_context = input_data.get("memory_context") or {}
338
+ memory_text = (
339
+ str(memory_context.get("formatted_text") or "").strip()
340
+ if isinstance(memory_context, dict)
341
+ else ""
342
+ )
343
+ if memory_text:
344
+ sections.append(f"Long-term memory context:\n{memory_text}")
345
+
346
+ return "\n\n".join(section for section in sections if section)
347
+
348
+ def _prepare_message_history_input(self, input_data: Dict[str, Any]) -> str:
349
+ user_input = str(input_data.get("input", "") or "")
350
+ context_text = self._request_context_text(input_data)
351
+ if not context_text:
352
+ return user_input
353
+ current_input = user_input.strip() or "[empty message]"
354
+ return f"{context_text}\n\nCurrent user input:\n{current_input}"
355
+
356
+ def _request_context_text(self, input_data: Dict[str, Any]) -> str:
357
+ ambient_text = self._ambient_context_text(input_data)
358
+ instructions = str(input_data.get("instructions") or "").strip()
359
+ return "\n\n".join(section for section in (instructions, ambient_text) if section)
360
+
361
+ def _format_replay_prompt(
362
+ self,
363
+ user_input: str,
364
+ history: list[dict[str, Any]],
365
+ *,
366
+ ambient_text: str = "",
367
+ instructions: str = "",
368
+ ) -> str:
369
+ lines: list[str] = []
370
+ if instructions:
371
+ lines.append(instructions)
372
+ if ambient_text:
373
+ lines.append(ambient_text)
374
+ if history:
375
+ lines.append("Conversation history:")
376
+ normalized_history: list[tuple[str, str]] = []
377
+ for item in history:
378
+ role = self._normalize_history_role(item.get("role"))
379
+ content = str(item.get("content", "") or "").strip()
380
+ if not role or not content:
381
+ continue
382
+ normalized_history.append((role, content))
383
+ lines.append(f"{role}: {content}")
384
+
385
+ if user_input.strip():
386
+ if not normalized_history or normalized_history[-1] != ("user", user_input.strip()):
387
+ lines.append(f"user: {user_input.strip()}")
388
+ elif ambient_text and not history:
389
+ lines.append("Current user input:\n[empty message]")
390
+
391
+ return "\n".join(lines)
392
+
393
+ @staticmethod
394
+ def _normalize_history_role(role: Any) -> str:
395
+ normalized = str(role or "").strip().lower()
396
+ if normalized in {"assistant", "model"}:
397
+ return "assistant"
398
+ if normalized == "user":
399
+ return "user"
400
+ return normalized
401
+
402
+ @staticmethod
403
+ def _with_session_config(
404
+ config: Optional[dict[str, Any]],
405
+ session_id: str,
406
+ ) -> dict[str, Any]:
407
+ merged = dict(config or {})
408
+ configurable = dict(merged.get("configurable") or {})
409
+ configurable["session_id"] = session_id
410
+ merged["configurable"] = configurable
411
+ return merged
412
+
413
+ async def _invoke_agent(
414
+ self,
415
+ payload: Any,
416
+ *,
417
+ config: Optional[dict[str, Any]],
418
+ context: Optional[dict[str, Any]],
419
+ ) -> Any:
420
+ if hasattr(self._agent, "ainvoke"):
421
+ kwargs = self._build_optional_call_kwargs(
422
+ self._agent.ainvoke,
423
+ config=config,
424
+ context=context,
425
+ )
426
+ return await self._agent.ainvoke(payload, **kwargs)
427
+ if hasattr(self._agent, "invoke"):
428
+ kwargs = self._build_optional_call_kwargs(
429
+ self._agent.invoke,
430
+ config=config,
431
+ context=context,
432
+ )
433
+ return self._agent.invoke(payload, **kwargs)
434
+ if callable(self._agent):
435
+ return self._agent(payload)
436
+ raise TypeError("Agent 不支持 invoke 调用")
437
+
438
+ def _is_runnable_with_message_history(self) -> bool:
439
+ try:
440
+ from langchain_core.runnables.history import RunnableWithMessageHistory
441
+
442
+ return isinstance(self._agent, RunnableWithMessageHistory)
443
+ except Exception:
444
+ return False
445
+
446
+ async def _invoke_with_message_history(
447
+ self,
448
+ input_data: Dict[str, Any],
449
+ session_id: str,
450
+ *,
451
+ config: Optional[dict[str, Any]],
452
+ context: Optional[dict[str, Any]],
453
+ ) -> Any:
454
+ context_text = self._request_context_text(input_data)
455
+ payload = {"input": self._prepare_message_history_input(input_data)}
456
+ session_config = self._with_session_config(config, session_id)
457
+ wrapped_runnable = self._extract_wrapped_history_runnable()
458
+ message_history = self._get_message_history_store(session_id)
459
+
460
+ if context_text and wrapped_runnable is not None and message_history is not None:
461
+ return await self._invoke_wrapped_history_with_ambient_context(
462
+ input_data=input_data,
463
+ wrapped_runnable=wrapped_runnable,
464
+ message_history=message_history,
465
+ session_config=session_config,
466
+ context=context,
467
+ ambient_text=context_text,
468
+ )
469
+
470
+ try:
471
+ return await self._invoke_agent(payload, config=session_config, context=context)
472
+ except Exception:
473
+ if wrapped_runnable is None or message_history is None:
474
+ raise
475
+ return await self._invoke_wrapped_history_with_ambient_context(
476
+ input_data=input_data,
477
+ wrapped_runnable=wrapped_runnable,
478
+ message_history=message_history,
479
+ session_config=session_config,
480
+ context=context,
481
+ ambient_text=context_text,
482
+ )
483
+
484
+ async def _invoke_wrapped_runnable(
485
+ self,
486
+ runnable: Any,
487
+ payload: Any,
488
+ config: Optional[dict[str, Any]],
489
+ context: Optional[dict[str, Any]],
490
+ ) -> Any:
491
+ if hasattr(runnable, "ainvoke"):
492
+ kwargs = self._build_optional_call_kwargs(
493
+ runnable.ainvoke,
494
+ config=config,
495
+ context=context,
496
+ )
497
+ return await runnable.ainvoke(payload, **kwargs)
498
+ if hasattr(runnable, "invoke"):
499
+ kwargs = self._build_optional_call_kwargs(
500
+ runnable.invoke,
501
+ config=config,
502
+ context=context,
503
+ )
504
+ return runnable.invoke(payload, **kwargs)
505
+ raise TypeError("Wrapped runnable does not support invoke")
506
+
507
+ async def _invoke_wrapped_history_with_ambient_context(
508
+ self,
509
+ *,
510
+ input_data: Dict[str, Any],
511
+ wrapped_runnable: Any,
512
+ message_history: Any,
513
+ session_config: Optional[dict[str, Any]],
514
+ context: Optional[dict[str, Any]],
515
+ ambient_text: str,
516
+ ) -> Any:
517
+ from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
518
+
519
+ user_input = str(input_data.get("input", "") or "")
520
+ prompt_messages = list(getattr(message_history, "messages", []))
521
+ if ambient_text:
522
+ prompt_messages = [SystemMessage(content=ambient_text), *prompt_messages]
523
+ prompt_messages.append(HumanMessage(content=user_input or "[empty message]"))
524
+ result = await self._invoke_wrapped_runnable(
525
+ wrapped_runnable,
526
+ {"input": prompt_messages},
527
+ session_config,
528
+ context,
529
+ )
530
+ output_text = self._extract_output(result)
531
+ await self._append_message_history(
532
+ message_history,
533
+ [
534
+ HumanMessage(content=user_input or "[empty message]"),
535
+ AIMessage(content=output_text),
536
+ ],
537
+ )
538
+ return result
539
+
540
+ def _extract_wrapped_history_runnable(self) -> Any | None:
541
+ runnable_lambda = self._get_nested_attr(
542
+ self._agent,
543
+ ("bound", "bound", "last", "bound"),
544
+ )
545
+ if runnable_lambda is None:
546
+ logger.debug(
547
+ "Unable to inspect RunnableWithMessageHistory wrapper: "
548
+ "missing bound.bound.last.bound"
549
+ )
550
+ return None
551
+
552
+ func = getattr(runnable_lambda, "func", None)
553
+ if func is None:
554
+ logger.debug(
555
+ "Unable to inspect RunnableWithMessageHistory wrapper: missing lambda func"
556
+ )
557
+ return None
558
+
559
+ try:
560
+ closure = inspect.getclosurevars(func).nonlocals
561
+ except Exception as exc:
562
+ logger.debug(
563
+ "Unable to inspect RunnableWithMessageHistory wrapper: %s",
564
+ exc,
565
+ )
566
+ return None
567
+ return closure.get("runnable_async") or closure.get("runnable_sync")
568
+
569
+ @staticmethod
570
+ def _get_nested_attr(obj: Any, path: tuple[str, ...]) -> Any | None:
571
+ current = obj
572
+ for name in path:
573
+ current = getattr(current, name, None)
574
+ if current is None:
575
+ return None
576
+ return current
577
+
578
+ def _get_message_history_store(self, session_id: str) -> Any | None:
579
+ get_session_history = getattr(self._agent, "get_session_history", None)
580
+ if not callable(get_session_history):
581
+ return None
582
+ return get_session_history(session_id)
583
+
584
+ async def _append_message_history(self, history_store: Any, messages: list[Any]) -> None:
585
+ if hasattr(history_store, "aadd_messages"):
586
+ await history_store.aadd_messages(messages)
587
+ return
588
+ if hasattr(history_store, "add_messages"):
589
+ history_store.add_messages(messages)
590
+ return
591
+ for message in messages:
592
+ role = getattr(message, "type", "")
593
+ content = getattr(message, "content", "")
594
+ if role == "human" and hasattr(history_store, "add_user_message"):
595
+ history_store.add_user_message(content)
596
+ elif role == "ai" and hasattr(history_store, "add_ai_message"):
597
+ history_store.add_ai_message(content)
598
+
599
+ @staticmethod
600
+ def _extract_output(result: Any) -> str:
601
+ if isinstance(result, dict):
602
+ if "output" in result:
603
+ return result["output"]
604
+ if "text" in result:
605
+ return result["text"]
606
+ messages = result.get("messages")
607
+ if isinstance(messages, list) and messages:
608
+ last = messages[-1]
609
+ if isinstance(last, dict):
610
+ return str(last.get("content", str(last)))
611
+ content = getattr(last, "content", None)
612
+ if content is not None:
613
+ return str(content)
614
+ return str(result)
615
+ content = getattr(result, "content", None)
616
+ if content is not None:
617
+ return str(content)
618
+ return str(result)
619
+
620
+ @classmethod
621
+ def _extract_recognized_output(cls, result: Any) -> str:
622
+ if result is None:
623
+ return ""
624
+ if isinstance(result, str):
625
+ return result
626
+
627
+ if isinstance(result, dict):
628
+ for key in ("output", "text"):
629
+ if key not in result:
630
+ continue
631
+ value = result[key]
632
+ if isinstance(value, str):
633
+ return value
634
+ extracted = cls._extract_recognized_output(value)
635
+ if extracted:
636
+ return extracted
637
+ if value is not None and not isinstance(value, (dict, list, tuple)):
638
+ return str(value)
639
+
640
+ message_state = cls._extract_message_state(result)
641
+ return message_state[0] if message_state else ""
642
+
643
+ if isinstance(result, (list, tuple)):
644
+ for item in reversed(result):
645
+ extracted = cls._extract_recognized_output(item)
646
+ if extracted:
647
+ return extracted
648
+ return ""
649
+
650
+ command_update = getattr(result, "update", None)
651
+ if isinstance(command_update, dict):
652
+ return cls._extract_recognized_output(command_update)
653
+
654
+ content = cls._ai_message_content(result)
655
+ return content if content is not None else ""
656
+
657
+ @classmethod
658
+ def _extract_message_state(cls, chunk: Any) -> tuple[str, str] | None:
659
+ """Extract the newest AI message from LangGraph values/updates snapshots."""
660
+
661
+ def visit(value: Any, path: tuple[str, ...]) -> tuple[str, str] | None:
662
+ if not isinstance(value, dict):
663
+ return None
664
+
665
+ messages = value.get("messages")
666
+ if isinstance(messages, list):
667
+ for index in range(len(messages) - 1, -1, -1):
668
+ message = messages[index]
669
+ content = cls._ai_message_content(message)
670
+ if content is None:
671
+ continue
672
+ message_id = (
673
+ message.get("id")
674
+ if isinstance(message, dict)
675
+ else getattr(message, "id", None)
676
+ )
677
+ fallback_key = "/".join((*path, "messages", str(index)))
678
+ return content, str(message_id or fallback_key)
679
+
680
+ for key, nested in value.items():
681
+ if key == "messages" or not isinstance(nested, dict):
682
+ continue
683
+ result = visit(nested, (*path, str(key)))
684
+ if result:
685
+ return result
686
+ return None
687
+
688
+ return visit(chunk, ())
689
+
690
+ @staticmethod
691
+ def _ai_message_content(message: Any) -> str | None:
692
+ if isinstance(message, dict):
693
+ role = str(message.get("role") or message.get("type") or "").lower()
694
+ if role not in {"ai", "assistant", "model", "aimessage", "aimessagechunk"}:
695
+ return None
696
+ content = message.get("content")
697
+ else:
698
+ role = str(getattr(message, "type", "") or "").lower()
699
+ class_name = type(message).__name__.lower()
700
+ if role not in {
701
+ "ai",
702
+ "assistant",
703
+ "model",
704
+ "aimessage",
705
+ "aimessagechunk",
706
+ } and not class_name.startswith("aimessage"):
707
+ return None
708
+ content = getattr(message, "content", None)
709
+
710
+ if isinstance(content, str):
711
+ return content
712
+ if not isinstance(content, list):
713
+ return None
714
+
715
+ parts: list[str] = []
716
+ for part in content:
717
+ if isinstance(part, str):
718
+ parts.append(part)
719
+ elif isinstance(part, dict):
720
+ text = part.get("text")
721
+ if isinstance(text, str):
722
+ parts.append(text)
723
+ return "".join(parts)
724
+
725
+ @staticmethod
726
+ def _snapshot_delta(content: str, previous: str) -> str:
727
+ if content.startswith(previous):
728
+ return content[len(previous) :]
729
+ if previous.startswith(content):
730
+ return ""
731
+ return content
732
+
733
+ def _extract_chunk(self, chunk: Any) -> tuple[Optional[str], Optional[str]]:
734
+ if isinstance(chunk, dict):
735
+ if "output" in chunk:
736
+ return chunk["output"], "text"
737
+ if "text" in chunk:
738
+ return chunk["text"], "text"
739
+ return None, None
740
+
741
+ reasoning = None
742
+ if hasattr(chunk, "reasoning_content") and chunk.reasoning_content:
743
+ reasoning = chunk.reasoning_content
744
+ elif hasattr(chunk, "additional_kwargs"):
745
+ reasoning = chunk.additional_kwargs.get("reasoning_content")
746
+
747
+ if reasoning:
748
+ return reasoning, "thinking"
749
+
750
+ content = chunk.content if hasattr(chunk, "content") else str(chunk)
751
+ return content if content else None, "text"