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,44 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from ksadk.runtime_context import get_current_tool_execution_context_or_default
6
+
7
+
8
+ @dataclass
9
+ class WorkspaceReadState:
10
+ path: str
11
+ mtime_ns: int
12
+ size_bytes: int
13
+ start_line: int
14
+ end_line: int
15
+ total_lines: int
16
+ partial: bool
17
+
18
+
19
+ _READ_STATE: dict[tuple[str, str], WorkspaceReadState] = {}
20
+
21
+
22
+ def _session_key(session_id: str | None = None) -> str:
23
+ if session_id is not None:
24
+ return str(session_id or "default")
25
+ context = get_current_tool_execution_context_or_default()
26
+ return str(context.session_id or "default")
27
+
28
+
29
+ def record_read_state(state: WorkspaceReadState) -> None:
30
+ _READ_STATE[(_session_key(), state.path)] = state
31
+
32
+
33
+ def get_read_state(path: str) -> WorkspaceReadState | None:
34
+ return _READ_STATE.get((_session_key(), path))
35
+
36
+
37
+ def clear_read_state(session_id: str | None = None) -> None:
38
+ if session_id is None:
39
+ _READ_STATE.clear()
40
+ return
41
+ key = _session_key(session_id)
42
+ for item in list(_READ_STATE):
43
+ if item[0] == key:
44
+ _READ_STATE.pop(item, None)
@@ -0,0 +1,37 @@
1
+ """
2
+ KsADK Tracing - 可观测性模块 (OpenTelemetry)
3
+
4
+ 使用方式:
5
+ from ksadk.tracing import setup_tracing
6
+
7
+ # 优先使用标准 OTel/OTLP 环境变量,后端可以是 Langfuse 或其他 Collector
8
+ # OTEL_EXPORTER_OTLP_ENDPOINT=https://collector.example.com/otel
9
+ # OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
10
+ setup_tracing()
11
+
12
+ # 兼容旧 Langfuse 环境变量,也可以显式启用
13
+ setup_tracing(enable_langfuse=True)
14
+
15
+ 环境变量:
16
+ OTEL_EXPORTER_OTLP_ENDPOINT - 通用 OTLP endpoint
17
+ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT - traces 专用 OTLP endpoint
18
+ OTEL_EXPORTER_OTLP_TRACES_PROTOCOL - traces 专用 OTLP 协议
19
+ OTEL_EXPORTER_OTLP_TRACES_HEADERS - traces 专用 OTLP headers
20
+ CLOUD_MONITOR_APP_KEY - 云监控 OTLP AppKey,注入 Ksc-Appkey header
21
+ CLOUD_MONITOR_OTLP_ENABLED - 云监控 OTLP 导出开关 (0.6.7 新增)
22
+ CLOUD_MONITOR_OTLP_ENDPOINT - 云监控 OTLP endpoint
23
+ CLOUD_MONITOR_OTLP_PROTOCOL - 云监控 OTLP 协议
24
+ CLOUD_MONITOR_OTLP_HEADERS - 云监控 OTLP headers (0.6.7 新增)
25
+ CLOUD_MONITOR_OTLP_TRACES_ENDPOINT - 云监控 traces 专用 endpoint
26
+ CLOUD_MONITOR_OTLP_TRACES_PROTOCOL - 云监控 traces 专用协议
27
+ LANGFUSE_PUBLIC_KEY - 存在即自动启用 Langfuse (无独立 LANGFUSE_ENABLED 开关)
28
+ LANGFUSE_SECRET_KEY - Langfuse Secret
29
+ LANGFUSE_BASE_URL - Langfuse 服务地址 (优先)
30
+ LANGFUSE_HOST - Langfuse 服务地址 (LANGFUSE_BASE_URL 别名)
31
+
32
+ Agent / session / user 等业务维度建议作为 span attributes 写入。
33
+ """
34
+
35
+ from ksadk.tracing.setup import get_memory_exporter, get_tracer, setup_tracing
36
+
37
+ __all__ = ["setup_tracing", "get_memory_exporter", "get_tracer"]
@@ -0,0 +1 @@
1
+ """Tracing Exporters"""
@@ -0,0 +1,116 @@
1
+ """
2
+ InMemoryExporter - 内存 Trace 存储
3
+
4
+ 用于本地 Web UI 查看 Traces
5
+ """
6
+
7
+ from typing import List, Dict, Any, Optional
8
+ from collections import deque
9
+ import threading
10
+ import time
11
+
12
+
13
+ class InMemoryExporter:
14
+ """内存 Trace Exporter"""
15
+
16
+ def __init__(self, max_traces: int = 1000):
17
+ self.max_traces = max_traces
18
+ self._traces: deque = deque(maxlen=max_traces)
19
+ self._lock = threading.Lock()
20
+
21
+ def export(self, spans) -> int:
22
+ """导出 Spans (符合 OpenTelemetry SpanExporter 接口)"""
23
+ from opentelemetry.sdk.trace.export import SpanExportResult
24
+
25
+ with self._lock:
26
+ for span in spans:
27
+ trace_data = self._span_to_dict(span)
28
+ self._traces.append(trace_data)
29
+
30
+ return SpanExportResult.SUCCESS
31
+
32
+ def shutdown(self) -> None:
33
+ """关闭 Exporter"""
34
+ pass
35
+
36
+ def force_flush(self, timeout_millis: int = 30000) -> bool:
37
+ """强制刷新"""
38
+ return True
39
+
40
+ def _span_to_dict(self, span) -> Dict[str, Any]:
41
+ """将 Span 转换为字典"""
42
+ ctx = span.get_span_context()
43
+
44
+ return {
45
+ "trace_id": format(ctx.trace_id, '032x'),
46
+ "span_id": format(ctx.span_id, '016x'),
47
+ "parent_span_id": format(span.parent.span_id, '016x') if span.parent else None,
48
+ "name": span.name,
49
+ "kind": str(span.kind),
50
+ "start_time": span.start_time,
51
+ "end_time": span.end_time,
52
+ "duration_ns": span.end_time - span.start_time if span.end_time else 0,
53
+ "attributes": dict(span.attributes) if span.attributes else {},
54
+ "status": {
55
+ "code": str(span.status.status_code),
56
+ "description": span.status.description
57
+ },
58
+ "events": [
59
+ {
60
+ "name": event.name,
61
+ "timestamp": event.timestamp,
62
+ "attributes": dict(event.attributes) if event.attributes else {}
63
+ }
64
+ for event in span.events
65
+ ] if span.events else []
66
+ }
67
+
68
+ def get_traces(self, limit: int = 100) -> List[Dict[str, Any]]:
69
+ """获取 Traces"""
70
+ with self._lock:
71
+ traces = list(self._traces)[-limit:]
72
+
73
+ # 按 trace_id 分组
74
+ grouped: Dict[str, List[Dict]] = {}
75
+ for span in traces:
76
+ trace_id = span["trace_id"]
77
+ if trace_id not in grouped:
78
+ grouped[trace_id] = []
79
+ grouped[trace_id].append(span)
80
+
81
+ # 转换为 trace 列表
82
+ result = []
83
+ for trace_id, spans in grouped.items():
84
+ result.append({
85
+ "trace_id": trace_id,
86
+ "spans": sorted(spans, key=lambda x: x["start_time"]),
87
+ "span_count": len(spans),
88
+ "start_time": min(s["start_time"] for s in spans),
89
+ "end_time": max(s["end_time"] for s in spans if s["end_time"]),
90
+ })
91
+
92
+ return sorted(result, key=lambda x: x["start_time"], reverse=True)[:limit]
93
+
94
+ def get_trace(self, trace_id: str) -> Optional[Dict[str, Any]]:
95
+ """获取单个 Trace"""
96
+ with self._lock:
97
+ spans = [s for s in self._traces if s["trace_id"] == trace_id]
98
+
99
+ if not spans:
100
+ return None
101
+
102
+ return {
103
+ "trace_id": trace_id,
104
+ "spans": sorted(spans, key=lambda x: x["start_time"]),
105
+ "span_count": len(spans)
106
+ }
107
+
108
+ def get_finished_spans(self) -> List[Dict[str, Any]]:
109
+ """返回所有已完成的 Spans (兼容 OpenTelemetry InMemorySpanExporter 接口)"""
110
+ with self._lock:
111
+ return list(self._traces)
112
+
113
+ def clear(self) -> None:
114
+ """清空 Traces"""
115
+ with self._lock:
116
+ self._traces.clear()
@@ -0,0 +1,445 @@
1
+ """
2
+ Langfuse Exporter for KsADK Tracing
3
+
4
+ Converts OpenTelemetry spans to Langfuse traces using low-level SDK API.
5
+ Compatible with Langfuse SDK v3.
6
+ """
7
+
8
+ import json
9
+ import logging
10
+ import os
11
+ from datetime import datetime
12
+ from typing import Sequence, Optional
13
+ from dataclasses import dataclass
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ @dataclass
19
+ class LangfuseExporterConfig:
20
+ """Configuration for Langfuse exporter"""
21
+ public_key: str
22
+ secret_key: str
23
+ host: str = "http://localhost:3000"
24
+ enabled: bool = True
25
+
26
+
27
+ # Alias for backward compatibility
28
+ LangfuseConfig = LangfuseExporterConfig
29
+
30
+
31
+ class _LangfuseSpanExporter:
32
+ """Internal span exporter that sends spans to Langfuse.
33
+
34
+ Uses Langfuse low-level SDK API (v3 compatible).
35
+ Agent metadata is loaded from ksadk.configs.settings.
36
+ """
37
+
38
+ def __init__(self, config: LangfuseExporterConfig):
39
+ self.config = config
40
+ self._langfuse = None
41
+ self._agent_config = None # Lazy load
42
+ self._init_langfuse()
43
+
44
+ def _get_agent_config(self):
45
+ """Lazy load agent config from unified settings"""
46
+ if self._agent_config is None:
47
+ try:
48
+ from ksadk.configs import settings
49
+ self._agent_config = settings.agent
50
+
51
+ # Log loaded metadata
52
+ if self._agent_config.agent_id:
53
+ logger.info(f"Agent metadata loaded: agent_id={self._agent_config.agent_id}")
54
+ if self._agent_config.tenant_id:
55
+ logger.debug(f"Tenant ID: {self._agent_config.tenant_id}")
56
+ except ImportError:
57
+ logger.warning("ksadk.configs not available, agent metadata disabled")
58
+ self._agent_config = None
59
+ return self._agent_config
60
+
61
+ def _init_langfuse(self):
62
+ """Initialize Langfuse client using low-level API"""
63
+ try:
64
+ # Set environment variables for Langfuse
65
+ os.environ["LANGFUSE_PUBLIC_KEY"] = self.config.public_key
66
+ os.environ["LANGFUSE_SECRET_KEY"] = self.config.secret_key
67
+ os.environ["LANGFUSE_HOST"] = self.config.host
68
+
69
+ # Use Langfuse low-level client
70
+ from langfuse import Langfuse
71
+ self._langfuse = Langfuse(
72
+ public_key=self.config.public_key,
73
+ secret_key=self.config.secret_key,
74
+ host=self.config.host
75
+ )
76
+ logger.info(f"Langfuse client initialized: {self.config.host}")
77
+ except ImportError:
78
+ logger.warning("Langfuse package not installed. Run: pip install langfuse")
79
+ self._langfuse = None
80
+ except Exception as e:
81
+ logger.error(f"Failed to initialize Langfuse: {e}")
82
+ self._langfuse = None
83
+
84
+ def export(self, spans) -> int:
85
+ """Export spans to Langfuse using low-level API"""
86
+ if not self._langfuse:
87
+ return 0
88
+
89
+ from opentelemetry.sdk.trace.export import SpanExportResult
90
+
91
+ try:
92
+ # Group spans by trace_id
93
+ traces = {}
94
+ for span in spans:
95
+ trace_id = format(span.context.trace_id, '032x')
96
+ if trace_id not in traces:
97
+ traces[trace_id] = []
98
+ traces[trace_id].append(span)
99
+
100
+ # Process each trace group
101
+ for trace_id, trace_spans in traces.items():
102
+ self._export_trace(trace_id, trace_spans)
103
+
104
+ self._langfuse.flush()
105
+ return SpanExportResult.SUCCESS
106
+
107
+ except Exception as e:
108
+ logger.error(f"Failed to export to Langfuse: {e}")
109
+ import traceback
110
+ traceback.print_exc()
111
+ return SpanExportResult.FAILURE
112
+
113
+ def _export_trace(self, trace_id: str, spans):
114
+ """Export spans using Langfuse ingestion API"""
115
+ # Find root span and categorize
116
+ root_span = None
117
+ llm_spans = []
118
+ tool_spans = []
119
+
120
+ for span in spans:
121
+ # Robust Root Span Detection:
122
+ # 1. Check if parent is None (standard OTEL way)
123
+ # 2. Check for known prefixes (fallback)
124
+ is_root = False
125
+ if hasattr(span, "parent") and span.parent:
126
+ # Local parent exists
127
+ is_root = False
128
+ elif hasattr(span, "context") and hasattr(span.context, "is_remote") and span.context.is_remote:
129
+ # Remote parent (distributed tracing) - treat as root for this service context?
130
+ # For now, we treat standard root spans (no parent) as root.
131
+ pass
132
+ elif not span.parent:
133
+ is_root = True
134
+
135
+ # Fallback for SDKs that might not expose parent property easily or if it's None
136
+ if not is_root:
137
+ name = span.name
138
+ if name.startswith("langgraph.") or name.startswith("langchain.") or name.startswith("adk."):
139
+ is_root = True
140
+
141
+ if is_root:
142
+ root_span = span
143
+ elif name == "call_llm":
144
+ llm_spans.append(span)
145
+ elif name.startswith("tool."):
146
+ tool_spans.append(span)
147
+
148
+ if not root_span:
149
+ # If batch doesn't contain a clear root, use the first span to carry context if needed
150
+ # But be careful not to treat random child spans as root for attributes
151
+ root_span = spans[0] if spans else None
152
+
153
+ if not root_span:
154
+ return
155
+
156
+ # Extract attributes
157
+ attrs = dict(root_span.attributes) if root_span.attributes else {}
158
+ # Use OTEL Trace ID as Langfuse Trace ID to ensure consistency between manual and auto-instrumented spans
159
+ invocation_id = trace_id
160
+ user_input = attrs.get("user.input", "")
161
+ agent_output = attrs.get("agent.output", "")
162
+
163
+ # Extract Langfuse-specific attributes from span
164
+ span_session_id = (
165
+ attrs.get("langfuse.session.id")
166
+ or attrs.get("langfuse.session_id")
167
+ or attrs.get("session.id")
168
+ )
169
+ span_tags = attrs.get("langfuse.tags", "")
170
+ span_user_id = (
171
+ attrs.get("langfuse.user.id")
172
+ or attrs.get("langfuse.user_id")
173
+ or attrs.get("user.id")
174
+ )
175
+
176
+ # Create trace using ingestion endpoint
177
+ try:
178
+ # Build base metadata
179
+ base_metadata = {
180
+ "trace_id": trace_id,
181
+ "framework": "ksadk",
182
+ }
183
+
184
+ # Get agent config from unified settings
185
+ agent_config = self._get_agent_config()
186
+
187
+ # Merge with agent metadata if available
188
+ langfuse_params = {}
189
+ trace_name = root_span.name
190
+
191
+ if agent_config:
192
+ agent_metadata = agent_config.to_langfuse_metadata()
193
+ base_metadata.update(agent_metadata)
194
+
195
+ langfuse_params = agent_config.to_langfuse_params()
196
+
197
+ # Use agent_name if available (only if root span)
198
+ if agent_config.agent_name and root_span == spans[0]: # Rough check if it's main Span
199
+ trace_name = agent_config.agent_name
200
+
201
+ # 优先使用 span attributes 中的值 (从 runner 传递)
202
+ if span_session_id:
203
+ langfuse_params["session_id"] = span_session_id
204
+
205
+ if span_user_id:
206
+ langfuse_params["user_id"] = span_user_id
207
+
208
+ # 处理 tags
209
+ existing_tags = langfuse_params.get("tags", []) or []
210
+ if span_tags:
211
+ span_tags_list = [t.strip() for t in span_tags.split(",") if t.strip()]
212
+ for tag in span_tags_list:
213
+ if tag not in existing_tags:
214
+ existing_tags.append(tag)
215
+
216
+ if agent_config:
217
+ if agent_config.agent_name and agent_config.agent_name not in existing_tags:
218
+ existing_tags.append(agent_config.agent_name)
219
+ if agent_config.environment and agent_config.environment not in existing_tags:
220
+ existing_tags.append(agent_config.environment)
221
+
222
+ if existing_tags:
223
+ langfuse_params["tags"] = existing_tags
224
+
225
+ # Prepare kwargs for trace() to avoid passing None and overwriting existing values
226
+ trace_kwargs = {
227
+ "id": invocation_id,
228
+ "name": trace_name,
229
+ "metadata": base_metadata,
230
+ **langfuse_params
231
+ }
232
+
233
+ if user_input:
234
+ trace_kwargs["input"] = {"text": user_input}
235
+ if agent_output:
236
+ trace_kwargs["output"] = {"text": agent_output}
237
+
238
+ # Use create_trace method (available in v3)
239
+ trace = self._langfuse.trace(**trace_kwargs)
240
+
241
+ # Add LLM generations
242
+ for llm_span in llm_spans:
243
+ self._add_generation(trace, llm_span)
244
+
245
+ # Add tool spans
246
+ for tool_span in tool_spans:
247
+ self._add_tool_span(trace, tool_span)
248
+
249
+ self._add_score_events(trace_id, spans)
250
+
251
+ except AttributeError:
252
+ # Fallback: use score/event API if trace() not available
253
+ self._export_via_events(invocation_id, root_span, llm_spans, tool_spans)
254
+
255
+ def _add_generation(self, trace, span):
256
+ """Add LLM generation to trace"""
257
+ attrs = dict(span.attributes) if span.attributes else {}
258
+
259
+ llm_request_str = attrs.get("gcp.vertex.agent.llm_request", "{}")
260
+ llm_response_str = attrs.get("gcp.vertex.agent.llm_response", "{}")
261
+
262
+ try:
263
+ llm_request = json.loads(llm_request_str)
264
+ llm_response = json.loads(llm_response_str)
265
+ except json.JSONDecodeError:
266
+ llm_request = {"raw": llm_request_str}
267
+ llm_response = {"raw": llm_response_str}
268
+
269
+ # Extract text content
270
+ input_text = ""
271
+ output_text = ""
272
+
273
+ if "contents" in llm_request:
274
+ contents = llm_request.get("contents", [])
275
+ if contents and "parts" in contents[0]:
276
+ parts = contents[0].get("parts", [])
277
+ if parts and "text" in parts[0]:
278
+ input_text = parts[0]["text"]
279
+
280
+ if "candidates" in llm_response:
281
+ candidates = llm_response.get("candidates", [])
282
+ if candidates and "content" in candidates[0]:
283
+ content = candidates[0]["content"]
284
+ if "parts" in content:
285
+ parts = content["parts"]
286
+ if parts and "text" in parts[0]:
287
+ output_text = parts[0]["text"]
288
+
289
+ model = attrs.get("model", attrs.get("gen_ai.request.model", "unknown"))
290
+
291
+ try:
292
+ trace.generation(
293
+ name=span.name,
294
+ model=model,
295
+ input=input_text or llm_request,
296
+ output=output_text or llm_response,
297
+ metadata={
298
+ "span_id": format(span.context.span_id, '016x'),
299
+ }
300
+ )
301
+ except AttributeError:
302
+ # Generation method not available, skip
303
+ pass
304
+
305
+ def _add_tool_span(self, trace, span):
306
+ """Add tool execution span"""
307
+ attrs = dict(span.attributes) if span.attributes else {}
308
+
309
+ tool_name = attrs.get("tool.name", span.name.replace("tool.", ""))
310
+ tool_input = attrs.get("tool.input", "")
311
+ tool_output = attrs.get("tool.output", "")
312
+
313
+ try:
314
+ trace.span(
315
+ name=f"tool:{tool_name}",
316
+ input={"args": tool_input} if tool_input else None,
317
+ output={"result": tool_output} if tool_output else None,
318
+ metadata={
319
+ "tool_name": tool_name,
320
+ }
321
+ )
322
+ except AttributeError:
323
+ pass
324
+
325
+ def _add_score_events(self, trace_id: str, spans) -> None:
326
+ """Convert OTel score events into Langfuse scores when the client supports it."""
327
+ for span in spans:
328
+ for event in getattr(span, "events", ()) or ():
329
+ attrs = dict(getattr(event, "attributes", None) or {})
330
+ event_name = str(getattr(event, "name", "") or "")
331
+ if event_name != "langfuse.score" and not attrs.get("score.name"):
332
+ continue
333
+ self._add_score(trace_id, attrs)
334
+
335
+ def _add_score(self, trace_id: str, attrs: dict) -> None:
336
+ if not self._langfuse or not hasattr(self._langfuse, "score"):
337
+ return
338
+ score_name = attrs.get("score.name") or attrs.get("langfuse.score.name")
339
+ if not score_name:
340
+ return
341
+
342
+ known_keys = {
343
+ "score.id",
344
+ "score.name",
345
+ "score.value",
346
+ "score.data_type",
347
+ "score.comment",
348
+ "langfuse.score.id",
349
+ "langfuse.score.name",
350
+ "langfuse.score.value",
351
+ "langfuse.score.data_type",
352
+ "langfuse.score.comment",
353
+ "langfuse.trace_id",
354
+ "trace_id",
355
+ "langfuse.observation_id",
356
+ "observation_id",
357
+ }
358
+ score_kwargs = {
359
+ "trace_id": attrs.get("langfuse.trace_id") or attrs.get("trace_id") or trace_id,
360
+ "name": score_name,
361
+ "value": attrs.get("score.value") or attrs.get("langfuse.score.value"),
362
+ }
363
+ score_id = attrs.get("score.id") or attrs.get("langfuse.score.id")
364
+ if score_id:
365
+ score_kwargs["id"] = score_id
366
+ data_type = attrs.get("score.data_type") or attrs.get("langfuse.score.data_type")
367
+ if data_type:
368
+ score_kwargs["data_type"] = data_type
369
+ comment = attrs.get("score.comment") or attrs.get("langfuse.score.comment")
370
+ if comment:
371
+ score_kwargs["comment"] = comment
372
+ observation_id = attrs.get("langfuse.observation_id") or attrs.get("observation_id")
373
+ if observation_id:
374
+ score_kwargs["observation_id"] = observation_id
375
+ metadata = {key: value for key, value in attrs.items() if key not in known_keys}
376
+ if metadata:
377
+ score_kwargs["metadata"] = metadata
378
+
379
+ try:
380
+ self._langfuse.score(**score_kwargs)
381
+ except TypeError:
382
+ score_kwargs["traceId"] = score_kwargs.pop("trace_id")
383
+ if "observation_id" in score_kwargs:
384
+ score_kwargs["observationId"] = score_kwargs.pop("observation_id")
385
+ if "data_type" in score_kwargs:
386
+ score_kwargs["dataType"] = score_kwargs.pop("data_type")
387
+ self._langfuse.score(**score_kwargs)
388
+ except AttributeError:
389
+ pass
390
+
391
+ def _export_via_events(self, trace_id: str, root_span, llm_spans, tool_spans):
392
+ """Fallback export using event-based API"""
393
+ # This is a fallback for when trace() method is not available
394
+ logger.debug(f"Exporting trace {trace_id} via fallback method")
395
+ # Just log for now - can be enhanced later
396
+ pass
397
+
398
+ def shutdown(self):
399
+ """Shutdown the exporter"""
400
+ if self._langfuse:
401
+ try:
402
+ self._langfuse.flush()
403
+ self._langfuse.shutdown()
404
+ except Exception:
405
+ pass
406
+
407
+ def force_flush(self, timeout_millis: int = 30000) -> bool:
408
+ """Force flush pending spans"""
409
+ if self._langfuse:
410
+ try:
411
+ self._langfuse.flush()
412
+ except Exception:
413
+ pass
414
+ return True
415
+
416
+
417
+ class LangfuseExporter:
418
+ """Langfuse exporter for KsADK tracing system.
419
+
420
+ Compatible with Langfuse SDK v3.
421
+ """
422
+
423
+ def __init__(self, config: LangfuseExporterConfig):
424
+ self.config = config
425
+ self.name = "langfuse_exporter"
426
+
427
+ self._exporter = _LangfuseSpanExporter(config)
428
+ self.processor = self._create_processor()
429
+
430
+ def _create_processor(self):
431
+ """Create span processor for this exporter"""
432
+ try:
433
+ from opentelemetry.sdk.trace.export import SimpleSpanProcessor
434
+ return SimpleSpanProcessor(self._exporter)
435
+ except ImportError:
436
+ logger.error("OpenTelemetry SDK not installed")
437
+ return None
438
+
439
+ @property
440
+ def resource_attributes(self) -> dict:
441
+ """Return resource attributes for this exporter"""
442
+ return {
443
+ "service.name": "ksadk",
444
+ "langfuse.host": self.config.host,
445
+ }