agentengine-sdk-python 0.6.4__py3-none-any.whl → 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentengine_sdk_python-0.7.0.dist-info/METADATA +181 -0
- agentengine_sdk_python-0.7.0.dist-info/RECORD +482 -0
- {agentengine_sdk_python-0.6.4.dist-info → agentengine_sdk_python-0.7.0.dist-info}/WHEEL +1 -1
- agentengine_sdk_python-0.7.0.dist-info/entry_points.txt +3 -0
- agentengine_sdk_python-0.7.0.dist-info/licenses/LICENSE +175 -0
- agentengine_sdk_python-0.7.0.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 +2246 -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 +2304 -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 +1263 -0
- ksadk/cli/cmd_invoke.py +1503 -0
- ksadk/cli/cmd_launch.py +564 -0
- ksadk/cli/cmd_mcp.py +1179 -0
- ksadk/cli/cmd_model.py +302 -0
- ksadk/cli/cmd_openclaw.py +3922 -0
- ksadk/cli/cmd_run.py +239 -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 +412 -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 +343 -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/message_projection.py +269 -0
- ksadk/conversations/model_context.py +370 -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 +5276 -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 +1115 -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/resilient_session_service.py +268 -0
- ksadk/memory/adk/short_term_memory.py +304 -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 +1994 -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 +751 -0
- ksadk/runners/langgraph_runner.py +985 -0
- ksadk/runners/patch_langchain.py +187 -0
- ksadk/runners/remote_runner.py +792 -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 +3931 -0
- ksadk/server/static/assets/ArtifactsPanel-D-SSn2ee.js +1 -0
- ksadk/server/static/assets/CodeBlock-P16VOLYi.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-CdGiQWHR.js +8 -0
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +1 -0
- ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-CHOd7Rch.css +1 -0
- ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.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-BA13sHc9.js +1 -0
- ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +1 -0
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-DzJzgVoL.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-UTdVcZhn.js +132 -0
- ksadk/server/static/assets/brainfuck-D5EjA2JK.js +1 -0
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dix0GD4m.js +10 -0
- ksadk/server/static/assets/channel-CTuydARX.js +1 -0
- ksadk/server/static/assets/chunk-2J33WTMH-C2JxuZ42.js +1 -0
- ksadk/server/static/assets/chunk-4BX2VUAB-Be57QPgD.js +1 -0
- ksadk/server/static/assets/chunk-55IACEB6-WjSuy4nv.js +1 -0
- ksadk/server/static/assets/chunk-727SXJPM-BOovP-b5.js +206 -0
- ksadk/server/static/assets/chunk-AQP2D5EJ-DOmZNmWj.js +231 -0
- ksadk/server/static/assets/chunk-FMBD7UC4-DzwlodkU.js +15 -0
- ksadk/server/static/assets/chunk-ND2GUHAM-DMqAikEU.js +1 -0
- ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.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-Zhy2GBnP.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-CbKrtIUz.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-BRApgQRK.js +43 -0
- ksadk/server/static/assets/diagram-5GNKFQAL-D0xbnDiK.js +10 -0
- ksadk/server/static/assets/diagram-KO2AKTUF-CVugVI9L.js +3 -0
- ksadk/server/static/assets/diagram-LMA3HP47-DozUGgee.js +24 -0
- ksadk/server/static/assets/diagram-OG6HWLK6-ZOYsKlru.js +24 -0
- ksadk/server/static/assets/diff-ChtP43wD.js +1 -0
- ksadk/server/static/assets/dist-2hInLS_J.js +9 -0
- ksadk/server/static/assets/dist-8EEyGgDx.js +1 -0
- ksadk/server/static/assets/dist-8_SfK1IP.js +1 -0
- ksadk/server/static/assets/dist-B0NP_Z0z.js +23 -0
- ksadk/server/static/assets/dist-BIJVDMuB.js +1 -0
- ksadk/server/static/assets/dist-BmlMPsCc.js +2 -0
- ksadk/server/static/assets/dist-BrCcQ47T.js +1 -0
- ksadk/server/static/assets/dist-BssVmjIo.js +6 -0
- ksadk/server/static/assets/dist-C3HIIaN5.js +1 -0
- ksadk/server/static/assets/dist-CPBtqRTW.js +1 -0
- ksadk/server/static/assets/dist-CkEKJFtk.js +1 -0
- ksadk/server/static/assets/dist-D-JMdWPQ.js +1 -0
- ksadk/server/static/assets/dist-D-xOD048.js +1 -0
- ksadk/server/static/assets/dist-D57wnGWd.js +1 -0
- ksadk/server/static/assets/dist-DL_NKc_z.js +1 -0
- ksadk/server/static/assets/dist-DMezvBGJ.js +1 -0
- ksadk/server/static/assets/dist-DmFaq_Iy.js +1 -0
- ksadk/server/static/assets/dist-Dp0k7bWI.js +1 -0
- ksadk/server/static/assets/dist-DpKtt4Bo.js +1 -0
- ksadk/server/static/assets/dist-DyOkZmze.js +11 -0
- ksadk/server/static/assets/dist-DyWsb78Q.js +1 -0
- ksadk/server/static/assets/dist-gX6GOLKq.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-Bk-9bgE5.js +85 -0
- ksadk/server/static/assets/erlang-DaB2Rkuy.js +1 -0
- ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.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-Dn9kZVuZ.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-BGxXlJqm.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-BIao9Yjg.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-C7Q0X-wi.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-C00Lwg3L.js +165 -0
- ksadk/server/static/assets/index-DAURbCsP.css +1 -0
- ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +1 -0
- ksadk/server/static/assets/infoDiagram-5YYISTIA-BO_CSqq5.js +2 -0
- ksadk/server/static/assets/init-D6jRqBbL.js +1 -0
- ksadk/server/static/assets/ishikawaDiagram-YF4QCWOH-eYLPLd46.js +70 -0
- ksadk/server/static/assets/javascript-9Tg8ixDm.js +1 -0
- ksadk/server/static/assets/journeyDiagram-JHISSGLW-De9geSb0.js +139 -0
- ksadk/server/static/assets/julia-CQfgDRfP.js +1 -0
- ksadk/server/static/assets/kanban-definition-UN3LZRKU-Cs80kQto.js +89 -0
- ksadk/server/static/assets/katex-DSrCFD8n.js +265 -0
- ksadk/server/static/assets/linear-CN9sbKTF.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-DlgSBU8l.js +161 -0
- ksadk/server/static/assets/mindmap-definition-RKZ34NQL-9afz7Oug.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-CGkyRxlg.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-M0uWAf4n.js +1 -0
- ksadk/server/static/assets/pieDiagram-4H26LBE5-DPv_VstN.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-o77wZ1XK.js +7 -0
- ksadk/server/static/assets/r-DADKenSm.js +1 -0
- ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +1 -0
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-BYVw81VC.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-B7nZFMKT.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-BGRRrFw5.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-BUfHCoPs.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.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-FbCTGrf9.js +120 -0
- ksadk/server/static/assets/toml-LvoKBwCs.js +1 -0
- ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.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-DWgwtPsJ.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-BEQz7wyy.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-2x8G-tTM.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-Drma3AYl.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 +279 -0
- ksadk/sessions/base.py +354 -0
- ksadk/sessions/continuity.py +337 -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 +901 -0
- ksadk/sessions/resilience.py +52 -0
- ksadk/sessions/resilient.py +360 -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 +854 -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 +917 -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 +892 -0
- ksadk/tracing/span_utils.py +114 -0
- ksadk/tui/__init__.py +27 -0
- ksadk/tui/loop.py +1877 -0
- ksadk/tui/stream_render.py +68 -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/__init__.py +0 -3
- agentengine_sdk_python-0.6.4.dist-info/METADATA +0 -48
- agentengine_sdk_python-0.6.4.dist-info/RECORD +0 -5
- agentengine_sdk_python-0.6.4.dist-info/top_level.txt +0 -1
ksadk/model_policy.py
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import copy
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any, Mapping
|
|
7
|
+
|
|
8
|
+
from ksadk.configs.settings import DEFAULT_MODEL_NAME
|
|
9
|
+
|
|
10
|
+
DEFAULT_MULTIMODAL_MODEL = "kimi-k2.7-code"
|
|
11
|
+
DEFAULT_FALLBACK_MODEL = "deepseek-v4-pro"
|
|
12
|
+
|
|
13
|
+
DEFAULT_MODEL_POLICY: dict[str, Any] = {
|
|
14
|
+
"version": "v1",
|
|
15
|
+
"primary": {"model": DEFAULT_MODEL_NAME},
|
|
16
|
+
"multimodal": {"model": DEFAULT_MULTIMODAL_MODEL},
|
|
17
|
+
"fallback": {
|
|
18
|
+
"model": DEFAULT_FALLBACK_MODEL,
|
|
19
|
+
"fallback_errors": [
|
|
20
|
+
"timeout",
|
|
21
|
+
"temporarily unavailable",
|
|
22
|
+
"temporary unavailable",
|
|
23
|
+
"model unavailable",
|
|
24
|
+
"rate limit",
|
|
25
|
+
"too many requests",
|
|
26
|
+
"503",
|
|
27
|
+
"504",
|
|
28
|
+
],
|
|
29
|
+
"on_errors": [
|
|
30
|
+
"timeout",
|
|
31
|
+
"temporarily unavailable",
|
|
32
|
+
"temporary unavailable",
|
|
33
|
+
"model unavailable",
|
|
34
|
+
"rate limit",
|
|
35
|
+
"too many requests",
|
|
36
|
+
"503",
|
|
37
|
+
"504",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
"models": {
|
|
41
|
+
DEFAULT_MODEL_NAME: {
|
|
42
|
+
"reasoning": True,
|
|
43
|
+
"options": {},
|
|
44
|
+
},
|
|
45
|
+
DEFAULT_MULTIMODAL_MODEL: {
|
|
46
|
+
"input": ["text", "image"],
|
|
47
|
+
"reasoning": True,
|
|
48
|
+
"options": {"temperature": 1},
|
|
49
|
+
},
|
|
50
|
+
DEFAULT_FALLBACK_MODEL: {
|
|
51
|
+
"reasoning": True,
|
|
52
|
+
"options": {},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _deep_merge(base: dict[str, Any], override: Mapping[str, Any]) -> dict[str, Any]:
|
|
59
|
+
merged = copy.deepcopy(base)
|
|
60
|
+
for key, value in override.items():
|
|
61
|
+
if (
|
|
62
|
+
isinstance(value, Mapping)
|
|
63
|
+
and isinstance(merged.get(key), dict)
|
|
64
|
+
):
|
|
65
|
+
merged[key] = _deep_merge(merged[key], value)
|
|
66
|
+
else:
|
|
67
|
+
merged[key] = copy.deepcopy(value)
|
|
68
|
+
return merged
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def normalize_model_policy(raw: str | Mapping[str, Any] | None = None) -> dict[str, Any]:
|
|
72
|
+
if raw is None or raw == "":
|
|
73
|
+
return copy.deepcopy(DEFAULT_MODEL_POLICY)
|
|
74
|
+
if isinstance(raw, str):
|
|
75
|
+
try:
|
|
76
|
+
parsed = json.loads(raw)
|
|
77
|
+
except json.JSONDecodeError:
|
|
78
|
+
return copy.deepcopy(DEFAULT_MODEL_POLICY)
|
|
79
|
+
else:
|
|
80
|
+
parsed = raw
|
|
81
|
+
if not isinstance(parsed, Mapping):
|
|
82
|
+
return copy.deepcopy(DEFAULT_MODEL_POLICY)
|
|
83
|
+
normalized = _deep_merge(DEFAULT_MODEL_POLICY, parsed)
|
|
84
|
+
fallback = normalized.get("fallback")
|
|
85
|
+
if isinstance(fallback, dict):
|
|
86
|
+
raw_errors = fallback.get("fallback_errors") or fallback.get("on_errors")
|
|
87
|
+
if isinstance(raw_errors, list):
|
|
88
|
+
fallback["fallback_errors"] = list(raw_errors)
|
|
89
|
+
fallback["on_errors"] = list(raw_errors)
|
|
90
|
+
return normalized
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _unqualified_model_name(model: str) -> str:
|
|
94
|
+
return str(model or "").strip().rsplit("/", 1)[-1]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def model_policy_options_for_model(
|
|
98
|
+
model: str,
|
|
99
|
+
policy: str | Mapping[str, Any] | None = None,
|
|
100
|
+
) -> dict[str, Any]:
|
|
101
|
+
normalized = normalize_model_policy(policy)
|
|
102
|
+
models = normalized.get("models")
|
|
103
|
+
if not isinstance(models, Mapping):
|
|
104
|
+
return {}
|
|
105
|
+
|
|
106
|
+
candidates = [str(model or "").strip(), _unqualified_model_name(model)]
|
|
107
|
+
for candidate in candidates:
|
|
108
|
+
config = models.get(candidate)
|
|
109
|
+
if isinstance(config, Mapping) and isinstance(config.get("options"), Mapping):
|
|
110
|
+
return dict(config["options"])
|
|
111
|
+
return {}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def fallback_model_for_exception(
|
|
115
|
+
exc: BaseException,
|
|
116
|
+
*,
|
|
117
|
+
current_model: str,
|
|
118
|
+
policy: str | Mapping[str, Any] | None = None,
|
|
119
|
+
) -> str | None:
|
|
120
|
+
normalized = normalize_model_policy(policy)
|
|
121
|
+
fallback = normalized.get("fallback")
|
|
122
|
+
if not isinstance(fallback, Mapping):
|
|
123
|
+
return None
|
|
124
|
+
|
|
125
|
+
fallback_model = str(fallback.get("model") or "").strip()
|
|
126
|
+
if not fallback_model or fallback_model == str(current_model or "").strip():
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
message = str(exc or "").strip().lower()
|
|
130
|
+
if not message:
|
|
131
|
+
return None
|
|
132
|
+
if "400" in message or "invalid request" in message or "bad request" in message:
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
transient_markers = fallback.get("fallback_errors") or fallback.get("on_errors")
|
|
136
|
+
if not isinstance(transient_markers, list):
|
|
137
|
+
transient_markers = DEFAULT_MODEL_POLICY["fallback"]["on_errors"]
|
|
138
|
+
|
|
139
|
+
if any(str(marker).lower() in message for marker in transient_markers):
|
|
140
|
+
return fallback_model
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _provider_ref(model: str, provider: str = "ksyun") -> str:
|
|
145
|
+
value = str(model or "").strip()
|
|
146
|
+
if not value or "/" in value:
|
|
147
|
+
return value
|
|
148
|
+
return f"{provider}/{value}"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _role_model(policy: Mapping[str, Any], role: str) -> str:
|
|
152
|
+
value = policy.get(role)
|
|
153
|
+
if isinstance(value, Mapping):
|
|
154
|
+
return str(value.get("model") or "").strip()
|
|
155
|
+
return str(value or "").strip()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _catalog_from_policy(policy: Mapping[str, Any]) -> list[dict[str, Any]]:
|
|
159
|
+
models = policy.get("models") if isinstance(policy.get("models"), Mapping) else {}
|
|
160
|
+
catalog: list[dict[str, Any]] = []
|
|
161
|
+
seen: set[str] = set()
|
|
162
|
+
for role in ("primary", "multimodal", "fallback"):
|
|
163
|
+
model = _role_model(policy, role)
|
|
164
|
+
if not model or model in seen:
|
|
165
|
+
continue
|
|
166
|
+
seen.add(model)
|
|
167
|
+
metadata = dict(models.get(model) or {}) if isinstance(models, Mapping) else {}
|
|
168
|
+
item = {
|
|
169
|
+
"id": model,
|
|
170
|
+
"name": model,
|
|
171
|
+
"api": metadata.get("api") or "openai-completions",
|
|
172
|
+
"input": metadata.get("input") or ["text"],
|
|
173
|
+
}
|
|
174
|
+
if isinstance(metadata.get("reasoning"), bool):
|
|
175
|
+
item["reasoning"] = metadata["reasoning"]
|
|
176
|
+
if isinstance(metadata.get("options"), Mapping) and metadata["options"]:
|
|
177
|
+
item["options"] = dict(metadata["options"])
|
|
178
|
+
catalog.append(item)
|
|
179
|
+
return catalog
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def build_runtime_model_policy_env(
|
|
183
|
+
env_vars: Mapping[str, str] | None,
|
|
184
|
+
*,
|
|
185
|
+
runtime: str,
|
|
186
|
+
policy: str | Mapping[str, Any] | None = None,
|
|
187
|
+
) -> dict[str, str]:
|
|
188
|
+
env = dict(env_vars or {})
|
|
189
|
+
normalized = normalize_model_policy(policy or os.getenv("AGENTENGINE_MODEL_POLICY_JSON"))
|
|
190
|
+
env.setdefault(
|
|
191
|
+
"AGENTENGINE_MODEL_POLICY_JSON",
|
|
192
|
+
json.dumps(normalized, ensure_ascii=False, sort_keys=True, separators=(",", ":")),
|
|
193
|
+
)
|
|
194
|
+
primary = _role_model(normalized, "primary")
|
|
195
|
+
fallback = _role_model(normalized, "fallback")
|
|
196
|
+
multimodal = _role_model(normalized, "multimodal")
|
|
197
|
+
has_primary = any(
|
|
198
|
+
str(env.get(key) or "").strip()
|
|
199
|
+
for key in ("OPENCLAW_DEFAULT_MODEL", "HERMES_DEFAULT_MODEL", "OPENAI_MODEL_NAME", "MODEL_NAME")
|
|
200
|
+
)
|
|
201
|
+
runtime_name = str(runtime or "").strip().lower()
|
|
202
|
+
if runtime_name == "openclaw":
|
|
203
|
+
if primary and not has_primary:
|
|
204
|
+
env["OPENAI_MODEL_NAME"] = _provider_ref(primary)
|
|
205
|
+
if fallback:
|
|
206
|
+
env.setdefault("OPENCLAW_FALLBACK_MODEL", _provider_ref(fallback))
|
|
207
|
+
if multimodal:
|
|
208
|
+
env.setdefault("OPENCLAW_IMAGE_MODEL", _provider_ref(multimodal))
|
|
209
|
+
env.setdefault("OPENCLAW_MODEL_CATALOG_JSON", json.dumps(_catalog_from_policy(normalized), ensure_ascii=False))
|
|
210
|
+
return env
|
|
211
|
+
if runtime_name == "hermes":
|
|
212
|
+
if primary and not has_primary:
|
|
213
|
+
env["OPENAI_MODEL_NAME"] = primary
|
|
214
|
+
env["HERMES_DEFAULT_MODEL"] = primary
|
|
215
|
+
if fallback:
|
|
216
|
+
env.setdefault("HERMES_FALLBACK_MODEL", fallback)
|
|
217
|
+
env.setdefault("HERMES_MODEL_CATALOG_JSON", json.dumps(_catalog_from_policy(normalized), ensure_ascii=False))
|
|
218
|
+
return env
|
|
219
|
+
if primary and not has_primary:
|
|
220
|
+
env["OPENAI_MODEL_NAME"] = primary
|
|
221
|
+
if fallback:
|
|
222
|
+
env.setdefault("OPENAI_FALLBACK_MODEL_NAME", fallback)
|
|
223
|
+
return env
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
"""Thin OpenClaw gateway client for Dashboard short-link sessions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
import platform
|
|
8
|
+
import uuid
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Any, Optional
|
|
11
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
12
|
+
|
|
13
|
+
import requests
|
|
14
|
+
|
|
15
|
+
from ksadk.api import AgentEngineClient
|
|
16
|
+
from ksadk.version import VERSION as KSADK_VERSION
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DEFAULT_CLIENT_NAME = "openclaw-control-ui"
|
|
20
|
+
DEFAULT_CLIENT_MODE = "webchat"
|
|
21
|
+
DEFAULT_SCOPES = ("operator.admin",)
|
|
22
|
+
GATEWAY_PROTOCOL_VERSION = 4
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class OpenClawGatewayError(RuntimeError):
|
|
26
|
+
"""Gateway connection or protocol error."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OpenClawGatewayRequestError(OpenClawGatewayError):
|
|
30
|
+
"""Structured gateway RPC error."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, message: str, *, code: Any = None, details: Any = None):
|
|
33
|
+
self.code = code
|
|
34
|
+
self.details = details
|
|
35
|
+
super().__init__(message)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class DashboardAccessInfo:
|
|
40
|
+
agent_id: str
|
|
41
|
+
agent_name: Optional[str]
|
|
42
|
+
access_url: str
|
|
43
|
+
ws_url: str
|
|
44
|
+
cookie_header: str
|
|
45
|
+
origin: str
|
|
46
|
+
link_id: Optional[str] = None
|
|
47
|
+
expires_at: Optional[str] = None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def derive_gateway_ws_url(access_url: str) -> str:
|
|
51
|
+
"""Derive the router websocket URL from a Dashboard short-link URL."""
|
|
52
|
+
parsed = urlsplit((access_url or "").strip())
|
|
53
|
+
if not parsed.scheme or not parsed.netloc:
|
|
54
|
+
raise OpenClawGatewayError("Dashboard access URL is invalid")
|
|
55
|
+
|
|
56
|
+
marker = "/s/"
|
|
57
|
+
path = parsed.path or "/"
|
|
58
|
+
marker_idx = path.find(marker)
|
|
59
|
+
base_path = path[:marker_idx] if marker_idx >= 0 else path
|
|
60
|
+
if not base_path:
|
|
61
|
+
base_path = "/"
|
|
62
|
+
if not base_path.endswith("/"):
|
|
63
|
+
base_path = f"{base_path}/"
|
|
64
|
+
|
|
65
|
+
ws_scheme = "wss" if parsed.scheme == "https" else "ws"
|
|
66
|
+
return urlunsplit((ws_scheme, parsed.netloc, base_path, "", ""))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class OpenClawGatewayClient:
|
|
70
|
+
"""Minimal cookie-session websocket client for a managed OpenClaw gateway."""
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
*,
|
|
75
|
+
region: str,
|
|
76
|
+
agent_id: str,
|
|
77
|
+
agent_name: Optional[str] = None,
|
|
78
|
+
client_name: str = DEFAULT_CLIENT_NAME,
|
|
79
|
+
client_mode: str = DEFAULT_CLIENT_MODE,
|
|
80
|
+
):
|
|
81
|
+
self.region = region
|
|
82
|
+
self.agent_id = agent_id
|
|
83
|
+
self.agent_name = agent_name
|
|
84
|
+
self.client_name = client_name
|
|
85
|
+
self.client_mode = client_mode
|
|
86
|
+
self.instance_id = str(uuid.uuid4())
|
|
87
|
+
self.session = requests.Session()
|
|
88
|
+
self._ws: Any = None
|
|
89
|
+
self.connection_info: Optional[DashboardAccessInfo] = None
|
|
90
|
+
self.hello: Optional[dict[str, Any]] = None
|
|
91
|
+
self.challenge_nonce: Optional[str] = None
|
|
92
|
+
|
|
93
|
+
async def __aenter__(self) -> "OpenClawGatewayClient":
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> bool:
|
|
97
|
+
await self.close()
|
|
98
|
+
return False
|
|
99
|
+
|
|
100
|
+
async def close(self) -> None:
|
|
101
|
+
if self._ws is not None:
|
|
102
|
+
try:
|
|
103
|
+
await self._ws.close()
|
|
104
|
+
except Exception:
|
|
105
|
+
pass
|
|
106
|
+
self._ws = None
|
|
107
|
+
self.session.close()
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def methods(self) -> list[str]:
|
|
111
|
+
features = (self.hello or {}).get("features") or {}
|
|
112
|
+
methods = features.get("methods")
|
|
113
|
+
if isinstance(methods, list):
|
|
114
|
+
return [str(item) for item in methods]
|
|
115
|
+
return []
|
|
116
|
+
|
|
117
|
+
def has_method(self, method: str) -> bool:
|
|
118
|
+
return method in set(self.methods)
|
|
119
|
+
|
|
120
|
+
async def build_access_info(
|
|
121
|
+
self,
|
|
122
|
+
*,
|
|
123
|
+
path: Optional[str] = None,
|
|
124
|
+
expires_seconds: Optional[int] = None,
|
|
125
|
+
link_type: str = "private",
|
|
126
|
+
force_new: bool = False,
|
|
127
|
+
) -> DashboardAccessInfo:
|
|
128
|
+
async with AgentEngineClient(region=self.region) as client:
|
|
129
|
+
link = await client.create_dashboard_access_link(
|
|
130
|
+
agent_id=self.agent_id,
|
|
131
|
+
name=self.agent_name,
|
|
132
|
+
link_type=link_type,
|
|
133
|
+
path=path,
|
|
134
|
+
expires_seconds=expires_seconds,
|
|
135
|
+
force_new=force_new,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
access_url = str(link.get("access_url") or "").strip()
|
|
139
|
+
if not access_url:
|
|
140
|
+
raise OpenClawGatewayError("CreateDashboardAccessLink returned an empty access URL")
|
|
141
|
+
|
|
142
|
+
response = await asyncio.to_thread(
|
|
143
|
+
self.session.get,
|
|
144
|
+
access_url,
|
|
145
|
+
allow_redirects=False,
|
|
146
|
+
timeout=30,
|
|
147
|
+
)
|
|
148
|
+
if response.status_code >= 400 or response.status_code < 300:
|
|
149
|
+
raise OpenClawGatewayError(
|
|
150
|
+
f"Dashboard short-link bootstrap failed: HTTP {response.status_code}"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
cookie_header = self._build_cookie_header()
|
|
154
|
+
if not cookie_header:
|
|
155
|
+
raise OpenClawGatewayError("Dashboard short-link bootstrap did not produce a session cookie")
|
|
156
|
+
|
|
157
|
+
parsed = urlsplit(access_url)
|
|
158
|
+
self.connection_info = DashboardAccessInfo(
|
|
159
|
+
agent_id=self.agent_id,
|
|
160
|
+
agent_name=self.agent_name,
|
|
161
|
+
access_url=access_url,
|
|
162
|
+
ws_url=derive_gateway_ws_url(access_url),
|
|
163
|
+
cookie_header=cookie_header,
|
|
164
|
+
origin=f"{parsed.scheme}://{parsed.netloc}",
|
|
165
|
+
link_id=str(link.get("link_id") or "").strip() or None,
|
|
166
|
+
expires_at=str(link.get("expires_at") or "").strip() or None,
|
|
167
|
+
)
|
|
168
|
+
return self.connection_info
|
|
169
|
+
|
|
170
|
+
async def connect(
|
|
171
|
+
self,
|
|
172
|
+
*,
|
|
173
|
+
path: Optional[str] = None,
|
|
174
|
+
expires_seconds: Optional[int] = None,
|
|
175
|
+
link_type: str = "private",
|
|
176
|
+
) -> dict[str, Any]:
|
|
177
|
+
info = self.connection_info or await self.build_access_info(
|
|
178
|
+
path=path,
|
|
179
|
+
expires_seconds=expires_seconds,
|
|
180
|
+
link_type=link_type,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
headers = {
|
|
184
|
+
"Cookie": info.cookie_header,
|
|
185
|
+
"User-Agent": f"ksadk/{KSADK_VERSION}",
|
|
186
|
+
"Origin": info.origin,
|
|
187
|
+
}
|
|
188
|
+
self._ws = await self._connect_ws(info.ws_url, headers)
|
|
189
|
+
self.challenge_nonce = await self._wait_for_connect_challenge()
|
|
190
|
+
self.hello = await self.request(
|
|
191
|
+
"connect",
|
|
192
|
+
{
|
|
193
|
+
"minProtocol": GATEWAY_PROTOCOL_VERSION,
|
|
194
|
+
"maxProtocol": GATEWAY_PROTOCOL_VERSION,
|
|
195
|
+
"client": {
|
|
196
|
+
"id": self.client_name,
|
|
197
|
+
"displayName": "ksadk openclaw channel",
|
|
198
|
+
"version": KSADK_VERSION,
|
|
199
|
+
"platform": platform.system().lower() or "unknown",
|
|
200
|
+
"mode": self.client_mode,
|
|
201
|
+
"instanceId": self.instance_id,
|
|
202
|
+
},
|
|
203
|
+
"caps": [],
|
|
204
|
+
"role": "operator",
|
|
205
|
+
"scopes": list(DEFAULT_SCOPES),
|
|
206
|
+
},
|
|
207
|
+
timeout_ms=10_000,
|
|
208
|
+
)
|
|
209
|
+
return self.hello
|
|
210
|
+
|
|
211
|
+
async def channels_status(self, *, probe: bool = False, timeout_ms: Optional[int] = None) -> dict[str, Any]:
|
|
212
|
+
params: dict[str, Any] = {"probe": bool(probe)}
|
|
213
|
+
if timeout_ms is not None:
|
|
214
|
+
params["timeoutMs"] = int(timeout_ms)
|
|
215
|
+
return await self.request("channels.status", params)
|
|
216
|
+
|
|
217
|
+
async def config_get(self) -> dict[str, Any]:
|
|
218
|
+
return await self.request("config.get", {})
|
|
219
|
+
|
|
220
|
+
async def config_apply(
|
|
221
|
+
self,
|
|
222
|
+
*,
|
|
223
|
+
config: dict[str, Any],
|
|
224
|
+
base_hash: str,
|
|
225
|
+
note: Optional[str] = None,
|
|
226
|
+
session_key: Optional[str] = None,
|
|
227
|
+
restart_delay_ms: Optional[int] = None,
|
|
228
|
+
) -> dict[str, Any]:
|
|
229
|
+
params: dict[str, Any] = {
|
|
230
|
+
"raw": json.dumps(config, ensure_ascii=False, indent=2),
|
|
231
|
+
"baseHash": base_hash,
|
|
232
|
+
}
|
|
233
|
+
if note:
|
|
234
|
+
params["note"] = note
|
|
235
|
+
if session_key:
|
|
236
|
+
params["sessionKey"] = session_key
|
|
237
|
+
if restart_delay_ms is not None:
|
|
238
|
+
params["restartDelayMs"] = int(restart_delay_ms)
|
|
239
|
+
return await self.request("config.apply", params, timeout_ms=20_000)
|
|
240
|
+
|
|
241
|
+
async def web_login_start(
|
|
242
|
+
self,
|
|
243
|
+
*,
|
|
244
|
+
force: bool = False,
|
|
245
|
+
timeout_ms: Optional[int] = None,
|
|
246
|
+
) -> dict[str, Any]:
|
|
247
|
+
params: dict[str, Any] = {"force": bool(force)}
|
|
248
|
+
if timeout_ms is not None:
|
|
249
|
+
params["timeoutMs"] = int(timeout_ms)
|
|
250
|
+
return await self.request("web.login.start", params, timeout_ms=(timeout_ms or 30_000) + 5_000)
|
|
251
|
+
|
|
252
|
+
async def web_login_wait(
|
|
253
|
+
self,
|
|
254
|
+
*,
|
|
255
|
+
account_id: Optional[str] = None,
|
|
256
|
+
session_key: Optional[str] = None,
|
|
257
|
+
timeout_ms: Optional[int] = None,
|
|
258
|
+
) -> dict[str, Any]:
|
|
259
|
+
params: dict[str, Any] = {}
|
|
260
|
+
effective_account_id = account_id or session_key
|
|
261
|
+
if effective_account_id:
|
|
262
|
+
params["accountId"] = effective_account_id
|
|
263
|
+
if timeout_ms is not None:
|
|
264
|
+
params["timeoutMs"] = int(timeout_ms)
|
|
265
|
+
return await self.request("web.login.wait", params, timeout_ms=(timeout_ms or 120_000) + 5_000)
|
|
266
|
+
|
|
267
|
+
async def request(
|
|
268
|
+
self,
|
|
269
|
+
method: str,
|
|
270
|
+
params: Optional[dict[str, Any]] = None,
|
|
271
|
+
*,
|
|
272
|
+
timeout_ms: int = 30_000,
|
|
273
|
+
) -> dict[str, Any]:
|
|
274
|
+
if self._ws is None:
|
|
275
|
+
raise OpenClawGatewayError("Gateway websocket is not connected")
|
|
276
|
+
|
|
277
|
+
request_id = uuid.uuid4().hex
|
|
278
|
+
payload = {
|
|
279
|
+
"type": "req",
|
|
280
|
+
"id": request_id,
|
|
281
|
+
"method": method,
|
|
282
|
+
"params": params or {},
|
|
283
|
+
}
|
|
284
|
+
await self._ws.send(json.dumps(payload, ensure_ascii=False))
|
|
285
|
+
return await self._wait_for_response(request_id, timeout_ms=timeout_ms)
|
|
286
|
+
|
|
287
|
+
async def wait_for_disconnect(self, *, timeout_ms: int = 5_000) -> bool:
|
|
288
|
+
"""Wait briefly for the current websocket to close, typically after config-triggered restart."""
|
|
289
|
+
if self._ws is None:
|
|
290
|
+
return True
|
|
291
|
+
|
|
292
|
+
deadline = asyncio.get_running_loop().time() + (timeout_ms / 1000)
|
|
293
|
+
while True:
|
|
294
|
+
remaining = deadline - asyncio.get_running_loop().time()
|
|
295
|
+
if remaining <= 0:
|
|
296
|
+
return False
|
|
297
|
+
try:
|
|
298
|
+
await self._recv_json(timeout=remaining)
|
|
299
|
+
except OpenClawGatewayError as exc:
|
|
300
|
+
return "timed out" not in str(exc).lower()
|
|
301
|
+
|
|
302
|
+
def _build_cookie_header(self) -> str:
|
|
303
|
+
cookies = self.session.cookies.get_dict()
|
|
304
|
+
return "; ".join(f"{name}={value}" for name, value in cookies.items())
|
|
305
|
+
|
|
306
|
+
async def _connect_ws(self, ws_url: str, headers: dict[str, str]):
|
|
307
|
+
try:
|
|
308
|
+
import websockets
|
|
309
|
+
except Exception as exc: # pragma: no cover - exercised only when dependency missing
|
|
310
|
+
raise OpenClawGatewayError(
|
|
311
|
+
"Missing dependency `websockets`; reinstall ksadk with channel support enabled"
|
|
312
|
+
) from exc
|
|
313
|
+
|
|
314
|
+
connect_kwargs = {
|
|
315
|
+
"open_timeout": 10,
|
|
316
|
+
"ping_interval": 20,
|
|
317
|
+
"ping_timeout": 20,
|
|
318
|
+
"max_size": 50 * 1024 * 1024,
|
|
319
|
+
}
|
|
320
|
+
try:
|
|
321
|
+
return await websockets.connect(ws_url, additional_headers=headers, **connect_kwargs)
|
|
322
|
+
except TypeError:
|
|
323
|
+
return await websockets.connect(ws_url, extra_headers=headers, **connect_kwargs)
|
|
324
|
+
|
|
325
|
+
async def _wait_for_connect_challenge(self, *, timeout_ms: int = 10_000) -> str:
|
|
326
|
+
deadline = timeout_ms / 1000
|
|
327
|
+
while True:
|
|
328
|
+
frame = await self._recv_json(timeout=deadline)
|
|
329
|
+
if frame.get("type") != "event":
|
|
330
|
+
continue
|
|
331
|
+
if frame.get("event") != "connect.challenge":
|
|
332
|
+
continue
|
|
333
|
+
payload = frame.get("payload") or {}
|
|
334
|
+
nonce = str(payload.get("nonce") or "").strip()
|
|
335
|
+
if nonce:
|
|
336
|
+
return nonce
|
|
337
|
+
raise OpenClawGatewayError("Gateway connect challenge missing nonce")
|
|
338
|
+
|
|
339
|
+
async def _wait_for_response(self, request_id: str, *, timeout_ms: int) -> dict[str, Any]:
|
|
340
|
+
deadline = timeout_ms / 1000
|
|
341
|
+
while True:
|
|
342
|
+
frame = await self._recv_json(timeout=deadline)
|
|
343
|
+
if frame.get("type") != "res":
|
|
344
|
+
continue
|
|
345
|
+
if frame.get("id") != request_id:
|
|
346
|
+
continue
|
|
347
|
+
if frame.get("ok"):
|
|
348
|
+
payload = frame.get("payload")
|
|
349
|
+
if isinstance(payload, dict):
|
|
350
|
+
return payload
|
|
351
|
+
return {"value": payload}
|
|
352
|
+
error = frame.get("error") or {}
|
|
353
|
+
raise OpenClawGatewayRequestError(
|
|
354
|
+
str(error.get("message") or "Gateway request failed"),
|
|
355
|
+
code=error.get("code"),
|
|
356
|
+
details=error.get("details"),
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
async def _recv_json(self, *, timeout: float) -> dict[str, Any]:
|
|
360
|
+
if self._ws is None:
|
|
361
|
+
raise OpenClawGatewayError("Gateway websocket is not connected")
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
raw = await asyncio.wait_for(self._ws.recv(), timeout=timeout)
|
|
365
|
+
except asyncio.TimeoutError as exc:
|
|
366
|
+
raise OpenClawGatewayError("Gateway websocket timed out") from exc
|
|
367
|
+
except Exception as exc:
|
|
368
|
+
raise OpenClawGatewayError(f"Gateway websocket receive failed: {exc}") from exc
|
|
369
|
+
|
|
370
|
+
if isinstance(raw, bytes):
|
|
371
|
+
raw = raw.decode("utf-8", errors="replace")
|
|
372
|
+
try:
|
|
373
|
+
parsed = json.loads(raw)
|
|
374
|
+
except Exception as exc:
|
|
375
|
+
raise OpenClawGatewayError("Gateway websocket returned invalid JSON") from exc
|
|
376
|
+
if not isinstance(parsed, dict):
|
|
377
|
+
raise OpenClawGatewayError("Gateway websocket returned an unexpected frame")
|
|
378
|
+
return parsed
|