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.
- agentengine_sdk_python-0.6.9.dist-info/METADATA +179 -0
- agentengine_sdk_python-0.6.9.dist-info/RECORD +487 -0
- {agentengine_sdk_python-0.6.2.dist-info → agentengine_sdk_python-0.6.9.dist-info}/WHEEL +1 -1
- agentengine_sdk_python-0.6.9.dist-info/entry_points.txt +3 -0
- agentengine_sdk_python-0.6.9.dist-info/licenses/LICENSE +175 -0
- agentengine_sdk_python-0.6.9.dist-info/top_level.txt +2 -0
- ksadk/__init__.py +13 -0
- ksadk/__main__.py +4 -0
- ksadk/a2a/__init__.py +15 -0
- ksadk/a2a/card_builder.py +64 -0
- ksadk/a2a/client.py +309 -0
- ksadk/a2a/executor.py +201 -0
- ksadk/a2a/server.py +79 -0
- ksadk/agents/__init__.py +20 -0
- ksadk/agents/base.py +370 -0
- ksadk/agents/context.py +38 -0
- ksadk/agents/event.py +35 -0
- ksadk/agents/loop_agent.py +71 -0
- ksadk/agents/parallel_agent.py +109 -0
- ksadk/agents/runner_adapter.py +24 -0
- ksadk/agents/sequential_agent.py +34 -0
- ksadk/api/__init__.py +3 -0
- ksadk/api/client.py +2227 -0
- ksadk/builders/__init__.py +20 -0
- ksadk/builders/base.py +66 -0
- ksadk/builders/code_builder.py +1990 -0
- ksadk/builders/container_builder.py +786 -0
- ksadk/builders/framework_requirements.py +59 -0
- ksadk/builders/ks3_uploader.py +389 -0
- ksadk/builders/mcp_builder.py +476 -0
- ksadk/builders/requirements_utils.py +75 -0
- ksadk/cli/__init__.py +531 -0
- ksadk/cli/__main__.py +4 -0
- ksadk/cli/agent_ref.py +204 -0
- ksadk/cli/cmd_a2a.py +167 -0
- ksadk/cli/cmd_agent.py +201 -0
- ksadk/cli/cmd_build.py +270 -0
- ksadk/cli/cmd_completion.py +304 -0
- ksadk/cli/cmd_config.py +758 -0
- ksadk/cli/cmd_create.py +2277 -0
- ksadk/cli/cmd_dashboard.py +900 -0
- ksadk/cli/cmd_deploy.py +704 -0
- ksadk/cli/cmd_destroy.py +345 -0
- ksadk/cli/cmd_files.py +1227 -0
- ksadk/cli/cmd_hermes.py +1259 -0
- ksadk/cli/cmd_invoke.py +1336 -0
- ksadk/cli/cmd_launch.py +564 -0
- ksadk/cli/cmd_mcp.py +1174 -0
- ksadk/cli/cmd_model.py +302 -0
- ksadk/cli/cmd_openclaw.py +3918 -0
- ksadk/cli/cmd_run.py +232 -0
- ksadk/cli/cmd_status.py +588 -0
- ksadk/cli/cmd_version.py +522 -0
- ksadk/cli/cmd_web.py +288 -0
- ksadk/cli/deploy_utils.py +87 -0
- ksadk/cli/dry_run.py +214 -0
- ksadk/cli/env_options.py +82 -0
- ksadk/cli/error_utils.py +525 -0
- ksadk/cli/global_options.py +31 -0
- ksadk/cli/local_runtime.py +97 -0
- ksadk/cli/model_catalog.py +136 -0
- ksadk/cli/network_options.py +410 -0
- ksadk/cli/resource_common.py +621 -0
- ksadk/cli/storage.py +84 -0
- ksadk/cli/ui.py +431 -0
- ksadk/cli/workflow_common.py +552 -0
- ksadk/common/__init__.py +14 -0
- ksadk/common/aicp_env.py +128 -0
- ksadk/common/auth.py +190 -0
- ksadk/common/constants.py +84 -0
- ksadk/common/llm_utils.py +61 -0
- ksadk/configs/__init__.py +61 -0
- ksadk/configs/env_registry.py +342 -0
- ksadk/configs/global_config.py +200 -0
- ksadk/configs/settings.py +706 -0
- ksadk/conversations/__init__.py +95 -0
- ksadk/conversations/attachment_storage.py +379 -0
- ksadk/conversations/attachments.py +774 -0
- ksadk/conversations/compaction_pipeline.py +387 -0
- ksadk/conversations/compaction_prompt.py +128 -0
- ksadk/conversations/context.py +303 -0
- ksadk/conversations/model_context.py +360 -0
- ksadk/conversations/model_options.py +136 -0
- ksadk/conversations/normalize.py +446 -0
- ksadk/conversations/reasoning_markup.py +91 -0
- ksadk/conversations/run_kinds.py +61 -0
- ksadk/conversations/run_status.py +53 -0
- ksadk/conversations/runtime.py +5208 -0
- ksadk/conversations/semantic_summary.py +359 -0
- ksadk/conversations/session_title.py +254 -0
- ksadk/deployment/__init__.py +83 -0
- ksadk/deployment/agent_access.py +226 -0
- ksadk/deployment/base.py +229 -0
- ksadk/deployment/manager.py +332 -0
- ksadk/deployment/providers/__init__.py +10 -0
- ksadk/deployment/providers/serverless.py +1105 -0
- ksadk/deployment/registry.py +120 -0
- ksadk/deployment/state.py +78 -0
- ksadk/deployment/ui_config.py +21 -0
- ksadk/detection/__init__.py +7 -0
- ksadk/detection/detector.py +431 -0
- ksadk/detection/mcp_detector.py +250 -0
- ksadk/hermes_terminal.py +467 -0
- ksadk/identity/__init__.py +17 -0
- ksadk/identity/resolver.py +385 -0
- ksadk/knowledge_base/__init__.py +62 -0
- ksadk/knowledge_base/adk_tool.py +47 -0
- ksadk/knowledge_base/client.py +297 -0
- ksadk/knowledge_base/langchain_tool.py +55 -0
- ksadk/knowledge_base/service.py +66 -0
- ksadk/knowledge_base/tool.py +50 -0
- ksadk/markdown.py +169 -0
- ksadk/mcp_runtime/__init__.py +231 -0
- ksadk/memory/__init__.py +57 -0
- ksadk/memory/adk/__init__.py +51 -0
- ksadk/memory/adk/backends/__init__.py +5 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +52 -0
- ksadk/memory/adk/backends/http_ltm_backend.py +183 -0
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +96 -0
- ksadk/memory/adk/backends/sdk_ltm_backend.py +456 -0
- ksadk/memory/adk/long_term_memory.py +273 -0
- ksadk/memory/adk/short_term_memory.py +289 -0
- ksadk/memory/adk_tool.py +31 -0
- ksadk/memory/backends/__init__.py +6 -0
- ksadk/memory/backends/base.py +103 -0
- ksadk/memory/backends/memory.py +112 -0
- ksadk/memory/backends/redis.py +146 -0
- ksadk/memory/langchain_tool.py +39 -0
- ksadk/memory/ltm_backend_factory.py +24 -0
- ksadk/memory/manager.py +215 -0
- ksadk/memory/service.py +172 -0
- ksadk/memory/tool.py +96 -0
- ksadk/model_policy.py +223 -0
- ksadk/openclaw_gateway.py +378 -0
- ksadk/runners/__init__.py +8 -0
- ksadk/runners/adk_runner.py +1135 -0
- ksadk/runners/base_runner.py +305 -0
- ksadk/runners/deepagents_runner.py +13 -0
- ksadk/runners/factory.py +73 -0
- ksadk/runners/langchain_runner.py +539 -0
- ksadk/runners/langgraph_runner.py +852 -0
- ksadk/runners/patch_langchain.py +187 -0
- ksadk/runners/remote_runner.py +667 -0
- ksadk/runners/usage_accumulator.py +38 -0
- ksadk/runners/utils/__init__.py +19 -0
- ksadk/runners/utils/langfuse.py +230 -0
- ksadk/runners/utils/loader.py +62 -0
- ksadk/runtime_context.py +166 -0
- ksadk/runtime_state.py +25 -0
- ksadk/sandbox/__init__.py +28 -0
- ksadk/sandbox/backends/__init__.py +9 -0
- ksadk/sandbox/backends/e2b.py +154 -0
- ksadk/sandbox/backends/local_process.py +131 -0
- ksadk/sandbox/base.py +101 -0
- ksadk/sandbox/factory.py +53 -0
- ksadk/sandbox/registry.py +187 -0
- ksadk/server/__init__.py +7 -0
- ksadk/server/api_models.py +73 -0
- ksadk/server/app.py +3789 -0
- ksadk/server/static/assets/ArtifactsPanel-C0meuOdi.js +1 -0
- ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +9 -0
- ksadk/server/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/server/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/server/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/server/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/server/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/server/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/server/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/server/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/server/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/server/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/server/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/server/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/server/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/server/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/server/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/server/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/server/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/server/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +8 -0
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
- ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
- ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +1 -0
- ksadk/server/static/assets/addon-fit-DthTIhi3.js +1 -0
- ksadk/server/static/assets/apl-CnwPGSsG.js +1 -0
- ksadk/server/static/assets/arc-bj2rZnP5.js +1 -0
- ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +1 -0
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-2u1ltDIj.js +36 -0
- ksadk/server/static/assets/asciiarmor-qTkVPQu6.js +1 -0
- ksadk/server/static/assets/asn1-Dr8qZg38.js +1 -0
- ksadk/server/static/assets/asterisk-Bja0s6e1.js +1 -0
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-D6fvdK20.js +132 -0
- ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-BK82L5n5.js +10 -0
- ksadk/server/static/assets/channel-BSSOwFIb.js +1 -0
- ksadk/server/static/assets/chunk-2J33WTMH-DLVdkeyQ.js +1 -0
- ksadk/server/static/assets/chunk-4BX2VUAB-BbwsYcbW.js +1 -0
- ksadk/server/static/assets/chunk-55IACEB6-DOairxzw.js +1 -0
- ksadk/server/static/assets/chunk-727SXJPM-hCO487gs.js +206 -0
- ksadk/server/static/assets/chunk-AQP2D5EJ-XU8vDOuG.js +231 -0
- ksadk/server/static/assets/chunk-FMBD7UC4-PrapyfMu.js +15 -0
- ksadk/server/static/assets/chunk-ND2GUHAM-CboKhTZ3.js +1 -0
- ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +1 -0
- ksadk/server/static/assets/clike-DHH8Ad3s.js +1 -0
- ksadk/server/static/assets/clojure-BflJGmDX.js +1 -0
- ksadk/server/static/assets/cmake-CyVbuzPu.js +1 -0
- ksadk/server/static/assets/cobol-B_OZ4V-R.js +1 -0
- ksadk/server/static/assets/coffeescript-B2pKbFk8.js +1 -0
- ksadk/server/static/assets/commonlisp-CcllspGY.js +1 -0
- ksadk/server/static/assets/cose-bilkent-S5V4N54A-_N8bJ-EU.js +1 -0
- ksadk/server/static/assets/crystal-M5-qzICs.js +1 -0
- ksadk/server/static/assets/css-CYpP4FRV.js +1 -0
- ksadk/server/static/assets/cypher-p9eYesGn.js +1 -0
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +321 -0
- ksadk/server/static/assets/d-BhMjBjQP.js +1 -0
- ksadk/server/static/assets/dagre-BM42HDAG-FoDlo5J2.js +4 -0
- ksadk/server/static/assets/dagre-Bx709z4p.js +1 -0
- ksadk/server/static/assets/defaultLocale-C8Fc0cco.js +1 -0
- ksadk/server/static/assets/diagram-2AECGRRQ-BBp6ebBw.js +43 -0
- ksadk/server/static/assets/diagram-5GNKFQAL-CqOvG1PR.js +10 -0
- ksadk/server/static/assets/diagram-KO2AKTUF-O9T3t6ba.js +3 -0
- ksadk/server/static/assets/diagram-LMA3HP47-CGG8ekBO.js +24 -0
- ksadk/server/static/assets/diagram-OG6HWLK6-4BmH1EEg.js +24 -0
- ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
- ksadk/server/static/assets/dist-6kSZvCZh.js +1 -0
- ksadk/server/static/assets/dist-B67uF2uK.js +1 -0
- ksadk/server/static/assets/dist-BMKM66B4.js +1 -0
- ksadk/server/static/assets/dist-BVzcWa6D.js +1 -0
- ksadk/server/static/assets/dist-Bk1l05Ni.js +1 -0
- ksadk/server/static/assets/dist-BkJjNih3.js +1 -0
- ksadk/server/static/assets/dist-BmuTWcm7.js +9 -0
- ksadk/server/static/assets/dist-C2DKRFVK.js +1 -0
- ksadk/server/static/assets/dist-CWiTDN_V.js +6 -0
- ksadk/server/static/assets/dist-CZ6C3x8B.js +23 -0
- ksadk/server/static/assets/dist-CiZHB6ZW.js +1 -0
- ksadk/server/static/assets/dist-Cp1_jKwf.js +1 -0
- ksadk/server/static/assets/dist-Cwhk4lwI.js +2 -0
- ksadk/server/static/assets/dist-D5JGcxBx.js +11 -0
- ksadk/server/static/assets/dist-D99wf6_X.js +1 -0
- ksadk/server/static/assets/dist-DCpZrjaK.js +1 -0
- ksadk/server/static/assets/dist-DI-oVAXw.js +1 -0
- ksadk/server/static/assets/dist-DLMjL01k.js +1 -0
- ksadk/server/static/assets/dist-DLeM1OCK.js +1 -0
- ksadk/server/static/assets/dist-DM0rEQPk.js +1 -0
- ksadk/server/static/assets/dist-DbaH3p5h.js +1 -0
- ksadk/server/static/assets/dist-S4klkK5W.js +1 -0
- ksadk/server/static/assets/dockerfile-BLkNEvjs.js +1 -0
- ksadk/server/static/assets/dtd-DTF72YNO.js +1 -0
- ksadk/server/static/assets/dylan-C6jEEEk-.js +1 -0
- ksadk/server/static/assets/ebnf-D4c0_ac3.js +1 -0
- ksadk/server/static/assets/ecl-BSZaIHnp.js +1 -0
- ksadk/server/static/assets/eiffel-BEjRio4Q.js +1 -0
- ksadk/server/static/assets/elm-Cshzl8qu.js +1 -0
- ksadk/server/static/assets/erDiagram-TEJ5UH35-oJhaci7S.js +85 -0
- ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
- ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +1 -0
- ksadk/server/static/assets/factor-D7LVTn2l.js +1 -0
- ksadk/server/static/assets/fcl-ClOhbFR7.js +1 -0
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-DtTmUan-.js +162 -0
- ksadk/server/static/assets/forth-Cezjo90N.js +1 -0
- ksadk/server/static/assets/fortran-Bt6PBEDR.js +1 -0
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-BSsb_eij.js +292 -0
- ksadk/server/static/assets/gas-BHEdbvp9.js +1 -0
- ksadk/server/static/assets/gherkin-oBAE_ms0.js +1 -0
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-BR5s6Pws.js +106 -0
- ksadk/server/static/assets/graphlib-B8gBHxth.js +1 -0
- ksadk/server/static/assets/groovy-BC3IOsC8.js +1 -0
- ksadk/server/static/assets/haskell-BRsoo5mP.js +1 -0
- ksadk/server/static/assets/haxe-DIz0ZZqd.js +1 -0
- ksadk/server/static/assets/http-CLVgA2GD.js +1 -0
- ksadk/server/static/assets/idl-BUZw3wgd.js +1 -0
- ksadk/server/static/assets/index-BH7-pC0B.js +165 -0
- ksadk/server/static/assets/index-DAURbCsP.css +1 -0
- ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +1 -0
- ksadk/server/static/assets/infoDiagram-5YYISTIA-DYPc5cvh.js +2 -0
- ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
- ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-MoBdALDg.js +70 -0
- ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
- ksadk/server/static/assets/journeyDiagram-JHISSGLW-DgLiQT8l.js +139 -0
- ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
- ksadk/server/static/assets/kanban-definition-UN3LZRKU-CsFx112F.js +89 -0
- ksadk/server/static/assets/katex-DRsiwpM2.js +265 -0
- ksadk/server/static/assets/linear-TNRQ5Orv.js +1 -0
- ksadk/server/static/assets/livescript-BXxG0Yva.js +1 -0
- ksadk/server/static/assets/lua-CiA1ziua.js +1 -0
- ksadk/server/static/assets/mathematica-u8YMmbU0.js +1 -0
- ksadk/server/static/assets/mbox-BEMVcqjs.js +1 -0
- ksadk/server/static/assets/mermaid-parser.core-D2eMVOgo.js +161 -0
- ksadk/server/static/assets/mindmap-definition-RKZ34NQL-BtByYFhL.js +96 -0
- ksadk/server/static/assets/mirc-C9zpzAZU.js +1 -0
- ksadk/server/static/assets/mllike-B45xgp2S.js +1 -0
- ksadk/server/static/assets/modelica-CqHI_q-D.js +1 -0
- ksadk/server/static/assets/mscgen-qgSLujhx.js +1 -0
- ksadk/server/static/assets/mumps-CW_TBmxz.js +1 -0
- ksadk/server/static/assets/nginx-BMaDbqW3.js +1 -0
- ksadk/server/static/assets/nsis-AQ_alPln.js +1 -0
- ksadk/server/static/assets/ntriples-d28e9m0E.js +1 -0
- ksadk/server/static/assets/octave-D2Q8cUp1.js +1 -0
- ksadk/server/static/assets/ordinal-hYBb2elL.js +1 -0
- ksadk/server/static/assets/oz-BwTct_5T.js +1 -0
- ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +1 -0
- ksadk/server/static/assets/pascal-Dp_KdFgX.js +1 -0
- ksadk/server/static/assets/perl-CdEHsPfU.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +1 -0
- ksadk/server/static/assets/pieDiagram-4H26LBE5-DPnuCB8c.js +30 -0
- ksadk/server/static/assets/pig-AF4Hwhju.js +1 -0
- ksadk/server/static/assets/powershell-CzG71I4L.js +1 -0
- ksadk/server/static/assets/properties-C357ku5U.js +1 -0
- ksadk/server/static/assets/protobuf-D1ij_kNL.js +1 -0
- ksadk/server/static/assets/pug-Bugr-47h.js +1 -0
- ksadk/server/static/assets/puppet-B4hC2X4m.js +1 -0
- ksadk/server/static/assets/python-BqYw9LYJ.js +1 -0
- ksadk/server/static/assets/q-B9NhS7L_.js +1 -0
- ksadk/server/static/assets/quadrantDiagram-W4KKPZXB-miFpCPv4.js +7 -0
- ksadk/server/static/assets/r-DADKenSm.js +1 -0
- ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +1 -0
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-mjB_yYkW.js +84 -0
- ksadk/server/static/assets/rpm-gpDK5sbt.js +1 -0
- ksadk/server/static/assets/ruby-DsYpTuWg.js +1 -0
- ksadk/server/static/assets/sankeyDiagram-5OEKKPKP-D7hSlZZZ.js +40 -0
- ksadk/server/static/assets/sas-C2OyD2Y6.js +1 -0
- ksadk/server/static/assets/scheme-CyDdOh7e.js +1 -0
- ksadk/server/static/assets/sequenceDiagram-3UESZ5HK-D9Cx6hC3.js +162 -0
- ksadk/server/static/assets/shell-Du5Qg9im.js +1 -0
- ksadk/server/static/assets/sieve-BAxa3IjF.js +1 -0
- ksadk/server/static/assets/simple-mode-DRpGK0lJ.js +1 -0
- ksadk/server/static/assets/smalltalk-BLp5-jwC.js +1 -0
- ksadk/server/static/assets/solr-BBopId9w.js +1 -0
- ksadk/server/static/assets/sparql-Dz-mlCAC.js +1 -0
- ksadk/server/static/assets/spreadsheet-CTIncYxj.js +1 -0
- ksadk/server/static/assets/sql-DcCJ9jop.js +1 -0
- ksadk/server/static/assets/stateDiagram-AJRCARHV-D_zrg47o.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +1 -0
- ksadk/server/static/assets/stex-sDrdk2BW.js +1 -0
- ksadk/server/static/assets/stylus-DLLZ8dgm.js +1 -0
- ksadk/server/static/assets/swift-DKB6_1j6.js +1 -0
- ksadk/server/static/assets/tcl-BGfruO1u.js +1 -0
- ksadk/server/static/assets/textile-DWBqthVk.js +1 -0
- ksadk/server/static/assets/tiddlywiki-VlUiK86J.js +1 -0
- ksadk/server/static/assets/tiki-CxVlf5KZ.js +1 -0
- ksadk/server/static/assets/timeline-definition-PNZ67QCA-CwSec0Wa.js +120 -0
- ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
- ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +1 -0
- ksadk/server/static/assets/troff-C2dAgh7P.js +1 -0
- ksadk/server/static/assets/ttcn-BePYh-hG.js +1 -0
- ksadk/server/static/assets/ttcn-cfg-CY0aot7Q.js +1 -0
- ksadk/server/static/assets/turtle-BDLWE2cD.js +1 -0
- ksadk/server/static/assets/vb-BthdM_4N.js +1 -0
- ksadk/server/static/assets/vbscript-D9f6rSsU.js +1 -0
- ksadk/server/static/assets/velocity-CqftRsjg.js +1 -0
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-agCVobiF.js +34 -0
- ksadk/server/static/assets/verilog-D-x6ne0Z.js +1 -0
- ksadk/server/static/assets/vhdl-CMrOq2q1.js +1 -0
- ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-TmrlhWNt.js +78 -0
- ksadk/server/static/assets/webidl-D5jiJvOU.js +1 -0
- ksadk/server/static/assets/xquery-fj_R-kMw.js +1 -0
- ksadk/server/static/assets/xterm-DooSxjI5.js +36 -0
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-DV71V-ah.js +7 -0
- ksadk/server/static/assets/yacas-CXXgtw0p.js +1 -0
- ksadk/server/static/assets/z80-CL1naaMV.js +1 -0
- ksadk/server/static/favicon.svg +1 -0
- ksadk/server/static/icons.svg +24 -0
- ksadk/server/static/index.html +14 -0
- ksadk/server/terminal_sessions.py +551 -0
- ksadk/sessions/__init__.py +283 -0
- ksadk/sessions/base.py +354 -0
- ksadk/sessions/continuity.py +313 -0
- ksadk/sessions/errors.py +7 -0
- ksadk/sessions/in_memory.py +273 -0
- ksadk/sessions/local_service.py +949 -0
- ksadk/sessions/postgres_service.py +838 -0
- ksadk/sessions/sqlite_service.py +13 -0
- ksadk/skills/__init__.py +9 -0
- ksadk/skills/loader.py +46 -0
- ksadk/skills/models.py +120 -0
- ksadk/skills/package_store.py +104 -0
- ksadk/skills/runtime/__init__.py +17 -0
- ksadk/skills/runtime/agent.py +183 -0
- ksadk/skills/runtime/artifacts.py +39 -0
- ksadk/skills/runtime/backends/__init__.py +1 -0
- ksadk/skills/runtime/backends/disabled.py +8 -0
- ksadk/skills/runtime/backends/e2b.py +168 -0
- ksadk/skills/runtime/backends/local.py +95 -0
- ksadk/skills/runtime/base.py +103 -0
- ksadk/skills/runtime/executor.py +219 -0
- ksadk/skills/runtime/factory.py +37 -0
- ksadk/skills/runtime/loader.py +131 -0
- ksadk/skills/runtime/registry.py +150 -0
- ksadk/skills/runtime/request.py +67 -0
- ksadk/skills/service_client.py +239 -0
- ksadk/skills/service_env.py +58 -0
- ksadk/skills/tool_defs.py +221 -0
- ksadk/terminal_client.py +69 -0
- ksadk/terminal_exec_policy.py +229 -0
- ksadk/tools/__init__.py +17 -0
- ksadk/tools/gateway.py +230 -0
- ksadk/tools/result_budget.py +154 -0
- ksadk/toolsets/__init__.py +852 -0
- ksadk/toolsets/_langchain.py +11 -0
- ksadk/toolsets/platform.py +93 -0
- ksadk/toolsets/sandbox.py +310 -0
- ksadk/toolsets/skills.py +217 -0
- ksadk/toolsets/web.py +266 -0
- ksadk/toolsets/workspace.py +878 -0
- ksadk/toolsets/workspace_state.py +44 -0
- ksadk/tracing/__init__.py +37 -0
- ksadk/tracing/exporters/__init__.py +1 -0
- ksadk/tracing/exporters/inmemory_exporter.py +116 -0
- ksadk/tracing/exporters/langfuse_exporter.py +445 -0
- ksadk/tracing/setup.py +829 -0
- ksadk/tracing/span_utils.py +114 -0
- ksadk/tui/__init__.py +12 -0
- ksadk/tui/app.py +400 -0
- ksadk/tui/clipboard.py +100 -0
- ksadk/tui/widgets/__init__.py +22 -0
- ksadk/tui/widgets/assistant.py +89 -0
- ksadk/tui/widgets/base.py +54 -0
- ksadk/tui/widgets/chat_input.py +246 -0
- ksadk/tui/widgets/history.py +156 -0
- ksadk/tui/widgets/system.py +87 -0
- ksadk/tui/widgets/thinking.py +110 -0
- ksadk/tui/widgets/tool_call.py +161 -0
- ksadk/tui/widgets/user.py +37 -0
- ksadk/ui_config.py +168 -0
- ksadk/version.py +4 -0
- ksadk_runtime_common/__init__.py +20 -0
- ksadk_runtime_common/memory_backend/__init__.py +29 -0
- ksadk_runtime_common/memory_backend/manifest.py +79 -0
- ksadk_runtime_common/memory_backend/providers/__init__.py +6 -0
- ksadk_runtime_common/memory_backend/providers/lancedb.py +151 -0
- ksadk_runtime_common/memory_backend/providers/mem0.py +74 -0
- ksadk_runtime_common/memory_backend/registry.py +56 -0
- ksadk_runtime_common/memory_backend/render.py +71 -0
- ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -0
- ksadk_runtime_common/workspace_files/__init__.py +29 -0
- ksadk_runtime_common/workspace_files/bootstrap.py +56 -0
- ksadk_runtime_common/workspace_files/constants.py +9 -0
- ksadk_runtime_common/workspace_files/path_utils.py +71 -0
- ksadk_runtime_common/workspace_files/preview.py +96 -0
- ksadk_runtime_common/workspace_files/router.py +254 -0
- agentengine_sdk_python-0.6.2.dist-info/METADATA +0 -46
- agentengine_sdk_python-0.6.2.dist-info/RECORD +0 -4
- 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
|
+
}
|