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,359 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any, Mapping, Sequence
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from ksadk.configs.settings import settings
|
|
10
|
+
from ksadk.conversations.compaction_prompt import (
|
|
11
|
+
build_compaction_prompt_messages,
|
|
12
|
+
extract_summary_text,
|
|
13
|
+
)
|
|
14
|
+
from ksadk.conversations.context import canonical_event_type, extract_event_text, summarize_event_groups
|
|
15
|
+
from ksadk.sessions.base import SessionEvent
|
|
16
|
+
|
|
17
|
+
SUMMARY_VERSION = "v1"
|
|
18
|
+
DEFAULT_COMPACTION_SUMMARY_TIMEOUT_MS = 45_000
|
|
19
|
+
DEFAULT_COMPACTION_SUMMARY_MAX_GROUPS = 12
|
|
20
|
+
SUMMARY_PREFIX = "Earlier conversation summary:"
|
|
21
|
+
|
|
22
|
+
# L4 semantic 熔断:独立计数 semantic LLM 调用失败(不复用 governance compact failure counter,
|
|
23
|
+
# 因为 summarize_compaction 捕获异常后返回 extractive,外层看是成功,governance 不触发)。
|
|
24
|
+
# 超过阈值后直接走 extractive,避免 Claude Code 的"1279 会话连续失败 50+ 次"浪费。
|
|
25
|
+
# 已知局限(有意取舍,对齐 Claude Code 行为):
|
|
26
|
+
# - 默认 0(opt-in),避免 transient 失败永久禁用 semantic;用户显式设 N>0 才启用。
|
|
27
|
+
# - 打开后无 half-open 探测,需进程重启或显式 _reset_semantic_failures 恢复(CC 同样如此)。
|
|
28
|
+
# - 计数为模块级全局,跨 session/model 共享;per-model key 化留作 follow-up(对齐 governance per-session 范式)。
|
|
29
|
+
_semantic_summary_failures: int = 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _max_consecutive_semantic_failures() -> int:
|
|
33
|
+
raw = os.environ.get("KSADK_MAX_CONSECUTIVE_SEMANTIC_FAILURES", "0")
|
|
34
|
+
try:
|
|
35
|
+
return max(0, int(raw))
|
|
36
|
+
except (TypeError, ValueError):
|
|
37
|
+
return 0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _semantic_circuit_open() -> bool:
|
|
41
|
+
"""semantic 熔断是否打开(超阈值则跳过 LLM 直接走 extractive)。0 = 禁用熔断。"""
|
|
42
|
+
threshold = _max_consecutive_semantic_failures()
|
|
43
|
+
if threshold <= 0:
|
|
44
|
+
return False
|
|
45
|
+
return _semantic_summary_failures >= threshold
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _record_semantic_failure() -> None:
|
|
49
|
+
global _semantic_summary_failures
|
|
50
|
+
_semantic_summary_failures += 1
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _reset_semantic_failures() -> None:
|
|
54
|
+
global _semantic_summary_failures
|
|
55
|
+
_semantic_summary_failures = 0
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class CompactionSummaryResult:
|
|
60
|
+
"""一次 checkpoint 摘要的标准结果。"""
|
|
61
|
+
|
|
62
|
+
summary_text: str
|
|
63
|
+
summary_strategy: str
|
|
64
|
+
summary_version: str = SUMMARY_VERSION
|
|
65
|
+
summary_model: str = ""
|
|
66
|
+
summary_usage: dict[str, Any] = field(default_factory=dict)
|
|
67
|
+
fallback_reason: str | None = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class SummaryModelClient:
|
|
71
|
+
"""独立的摘要模型客户端。
|
|
72
|
+
|
|
73
|
+
注意这里故意不复用 agent runner:
|
|
74
|
+
- runner 的职责是执行用户 agent;
|
|
75
|
+
- 摘要器的职责是平台内部的 context compaction。
|
|
76
|
+
两者拆开后,失败隔离和后续替换模型都会更清晰。
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self,
|
|
81
|
+
*,
|
|
82
|
+
api_base: str | None = None,
|
|
83
|
+
api_key: str | None = None,
|
|
84
|
+
):
|
|
85
|
+
self.api_base = str(api_base or settings.model.api_base or "").rstrip("/")
|
|
86
|
+
self.api_key = str(api_key or settings.model.api_key or "").strip()
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def is_available(self) -> bool:
|
|
90
|
+
return bool(self.api_base and self.api_key)
|
|
91
|
+
|
|
92
|
+
def _chat_completions_url(self) -> str:
|
|
93
|
+
if self.api_base.endswith("/v1"):
|
|
94
|
+
return f"{self.api_base}/chat/completions"
|
|
95
|
+
return f"{self.api_base}/v1/chat/completions"
|
|
96
|
+
|
|
97
|
+
async def summarize(
|
|
98
|
+
self,
|
|
99
|
+
*,
|
|
100
|
+
model: str,
|
|
101
|
+
messages: Sequence[dict[str, str]],
|
|
102
|
+
timeout_ms: int,
|
|
103
|
+
) -> tuple[str, dict[str, Any]]:
|
|
104
|
+
if not self.is_available:
|
|
105
|
+
raise RuntimeError("summary model client is not configured")
|
|
106
|
+
if not model:
|
|
107
|
+
raise RuntimeError("summary model is not configured")
|
|
108
|
+
|
|
109
|
+
headers = {
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
112
|
+
}
|
|
113
|
+
payload = {
|
|
114
|
+
"model": model,
|
|
115
|
+
"messages": list(messages),
|
|
116
|
+
"stream": False,
|
|
117
|
+
"temperature": 0,
|
|
118
|
+
}
|
|
119
|
+
timeout_seconds = max(1.0, float(timeout_ms) / 1000.0)
|
|
120
|
+
async with httpx.AsyncClient(timeout=timeout_seconds) as client:
|
|
121
|
+
response = await client.post(self._chat_completions_url(), headers=headers, json=payload)
|
|
122
|
+
response.raise_for_status()
|
|
123
|
+
data = response.json()
|
|
124
|
+
|
|
125
|
+
choices = data.get("choices") or []
|
|
126
|
+
message = choices[0].get("message") if choices else {}
|
|
127
|
+
content = message.get("content") if isinstance(message, Mapping) else ""
|
|
128
|
+
if isinstance(content, list):
|
|
129
|
+
fragments: list[str] = []
|
|
130
|
+
for item in content:
|
|
131
|
+
if isinstance(item, Mapping) and item.get("text"):
|
|
132
|
+
fragments.append(str(item["text"]))
|
|
133
|
+
content = "\n".join(fragment for fragment in fragments if fragment)
|
|
134
|
+
text = str(content or "").strip()
|
|
135
|
+
if not text:
|
|
136
|
+
raise RuntimeError("summary model returned empty content")
|
|
137
|
+
return text, dict(data.get("usage") or {})
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def resolve_summary_model_client() -> SummaryModelClient:
|
|
141
|
+
return SummaryModelClient()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _ensure_summary_prefix(summary_text: str) -> str:
|
|
145
|
+
text = str(summary_text or "").strip()
|
|
146
|
+
if not text or text.startswith(SUMMARY_PREFIX):
|
|
147
|
+
return text
|
|
148
|
+
return f"{SUMMARY_PREFIX}\n{text}"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _env_truthy(name: str) -> bool:
|
|
152
|
+
value = str(os.getenv(name, "")).strip().lower()
|
|
153
|
+
return value in {"1", "true", "yes", "on"}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def semantic_compaction_disabled() -> bool:
|
|
157
|
+
return _env_truthy("COMPACTION_DISABLE_SEMANTIC")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_summary_timeout_ms() -> int:
|
|
161
|
+
raw = os.getenv("COMPACTION_SUMMARY_TIMEOUT_MS", "").strip()
|
|
162
|
+
try:
|
|
163
|
+
return max(1_000, int(raw))
|
|
164
|
+
except (TypeError, ValueError):
|
|
165
|
+
return DEFAULT_COMPACTION_SUMMARY_TIMEOUT_MS
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_summary_max_groups() -> int:
|
|
169
|
+
raw = os.getenv("COMPACTION_SUMMARY_MAX_GROUPS", "").strip()
|
|
170
|
+
try:
|
|
171
|
+
return max(1, int(raw))
|
|
172
|
+
except (TypeError, ValueError):
|
|
173
|
+
return DEFAULT_COMPACTION_SUMMARY_MAX_GROUPS
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def resolve_summary_model(current_model: str | None) -> str:
|
|
177
|
+
override = str(os.getenv("COMPACTION_SUMMARY_MODEL", "")).strip()
|
|
178
|
+
if override:
|
|
179
|
+
return override
|
|
180
|
+
if current_model:
|
|
181
|
+
return str(current_model)
|
|
182
|
+
return str(settings.model.model_name or "")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def find_pinned_group_indexes(groups: Sequence[Sequence[SessionEvent]]) -> set[int]:
|
|
186
|
+
"""找出不能被 compact 的轮次。
|
|
187
|
+
|
|
188
|
+
当前先严格保护两类未完成状态:
|
|
189
|
+
1. approval_request 尚未收到 approval_response
|
|
190
|
+
2. tool_call 尚未看到 tool_result
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
pending_approval_groups: list[int] = []
|
|
194
|
+
pending_tool_groups: list[int] = []
|
|
195
|
+
for index, group in enumerate(groups):
|
|
196
|
+
for event in group:
|
|
197
|
+
event_type = canonical_event_type(
|
|
198
|
+
event.event_type,
|
|
199
|
+
author=event.author,
|
|
200
|
+
role=str((event.content or {}).get("role") or ""),
|
|
201
|
+
)
|
|
202
|
+
if event_type == "approval_request":
|
|
203
|
+
pending_approval_groups.append(index)
|
|
204
|
+
continue
|
|
205
|
+
if event_type == "approval_response" and pending_approval_groups:
|
|
206
|
+
pending_approval_groups.pop()
|
|
207
|
+
continue
|
|
208
|
+
if event_type == "tool_call":
|
|
209
|
+
pending_tool_groups.append(index)
|
|
210
|
+
continue
|
|
211
|
+
if event_type == "tool_result" and pending_tool_groups:
|
|
212
|
+
pending_tool_groups.pop()
|
|
213
|
+
return set(pending_approval_groups + pending_tool_groups)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def extract_pinned_state(groups: Sequence[Sequence[SessionEvent]]) -> dict[str, Any]:
|
|
217
|
+
"""提取必须在 checkpoint 里显式保留的状态。"""
|
|
218
|
+
|
|
219
|
+
pending_approvals: list[str] = []
|
|
220
|
+
pending_tools: list[str] = []
|
|
221
|
+
attachment_refs: list[str] = []
|
|
222
|
+
current_user_goal = ""
|
|
223
|
+
|
|
224
|
+
for group in groups:
|
|
225
|
+
for event in group:
|
|
226
|
+
event_type = canonical_event_type(
|
|
227
|
+
event.event_type,
|
|
228
|
+
author=event.author,
|
|
229
|
+
role=str((event.content or {}).get("role") or ""),
|
|
230
|
+
)
|
|
231
|
+
text = extract_event_text(event)
|
|
232
|
+
if event_type == "approval_request" and text:
|
|
233
|
+
pending_approvals.append(text)
|
|
234
|
+
elif event_type == "approval_response" and pending_approvals:
|
|
235
|
+
pending_approvals.pop()
|
|
236
|
+
elif event_type == "tool_call" and text:
|
|
237
|
+
pending_tools.append(text)
|
|
238
|
+
elif event_type == "tool_result" and pending_tools:
|
|
239
|
+
pending_tools.pop()
|
|
240
|
+
elif event_type == "attachment_ref":
|
|
241
|
+
attachment_refs.append(text)
|
|
242
|
+
elif event_type == "user_message" and text:
|
|
243
|
+
current_user_goal = text
|
|
244
|
+
for attachment in (event.metadata or {}).get("attachments") or []:
|
|
245
|
+
if not isinstance(attachment, Mapping):
|
|
246
|
+
continue
|
|
247
|
+
label = str(
|
|
248
|
+
attachment.get("display_name")
|
|
249
|
+
or attachment.get("file_uri")
|
|
250
|
+
or attachment.get("storage_path")
|
|
251
|
+
or ""
|
|
252
|
+
).strip()
|
|
253
|
+
if label:
|
|
254
|
+
attachment_refs.append(label)
|
|
255
|
+
|
|
256
|
+
unique_attachments: list[str] = []
|
|
257
|
+
for item in attachment_refs:
|
|
258
|
+
normalized = str(item or "").strip()
|
|
259
|
+
if normalized and normalized not in unique_attachments:
|
|
260
|
+
unique_attachments.append(normalized)
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
"pending_approvals": pending_approvals,
|
|
264
|
+
"pending_tools": pending_tools,
|
|
265
|
+
"attachment_refs": unique_attachments[-5:],
|
|
266
|
+
"current_user_goal": current_user_goal,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def _build_semantic_input(
|
|
271
|
+
*,
|
|
272
|
+
previous_summary: str,
|
|
273
|
+
groups_to_compact: Sequence[Sequence[SessionEvent]],
|
|
274
|
+
pinned_state: Mapping[str, Any],
|
|
275
|
+
model_metadata: Mapping[str, Any] | None,
|
|
276
|
+
) -> tuple[str, list[list[SessionEvent]]]:
|
|
277
|
+
max_groups = get_summary_max_groups()
|
|
278
|
+
selected_groups = [list(group) for group in groups_to_compact]
|
|
279
|
+
merged_previous_summary = previous_summary.strip()
|
|
280
|
+
if len(selected_groups) > max_groups:
|
|
281
|
+
skipped_groups = selected_groups[:-max_groups]
|
|
282
|
+
selected_groups = selected_groups[-max_groups:]
|
|
283
|
+
skipped_summary = summarize_event_groups(skipped_groups, previous_summary=merged_previous_summary)
|
|
284
|
+
merged_previous_summary = skipped_summary
|
|
285
|
+
return merged_previous_summary, selected_groups
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
async def summarize_compaction(
|
|
289
|
+
*,
|
|
290
|
+
groups_to_compact: Sequence[Sequence[SessionEvent]],
|
|
291
|
+
previous_summary: str,
|
|
292
|
+
pinned_state: Mapping[str, Any],
|
|
293
|
+
model_metadata: Mapping[str, Any] | None,
|
|
294
|
+
model: str | None,
|
|
295
|
+
) -> CompactionSummaryResult:
|
|
296
|
+
"""语义摘要优先,失败后自动回退到 extractive。"""
|
|
297
|
+
|
|
298
|
+
fallback_summary = summarize_event_groups(list(groups_to_compact), previous_summary=previous_summary)
|
|
299
|
+
if semantic_compaction_disabled():
|
|
300
|
+
return CompactionSummaryResult(
|
|
301
|
+
summary_text=fallback_summary,
|
|
302
|
+
summary_strategy="extractive",
|
|
303
|
+
fallback_reason="semantic summarizer disabled",
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
# L4 semantic 熔断:连续失败超阈值则跳过 LLM 直接走 extractive,直到进程重启或显式 reset。
|
|
307
|
+
if _semantic_circuit_open():
|
|
308
|
+
return CompactionSummaryResult(
|
|
309
|
+
summary_text=fallback_summary,
|
|
310
|
+
summary_strategy="extractive",
|
|
311
|
+
fallback_reason="semantic_circuit_open",
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
summary_model = resolve_summary_model(model)
|
|
315
|
+
client = resolve_summary_model_client()
|
|
316
|
+
if not client.is_available:
|
|
317
|
+
return CompactionSummaryResult(
|
|
318
|
+
summary_text=fallback_summary,
|
|
319
|
+
summary_strategy="extractive",
|
|
320
|
+
fallback_reason="summary model client is not configured",
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
merged_previous_summary, selected_groups = _build_semantic_input(
|
|
325
|
+
previous_summary=previous_summary,
|
|
326
|
+
groups_to_compact=groups_to_compact,
|
|
327
|
+
pinned_state=pinned_state,
|
|
328
|
+
model_metadata=model_metadata,
|
|
329
|
+
)
|
|
330
|
+
prompt_messages = build_compaction_prompt_messages(
|
|
331
|
+
previous_summary=merged_previous_summary,
|
|
332
|
+
groups_to_compact=selected_groups,
|
|
333
|
+
pinned_state=pinned_state,
|
|
334
|
+
model_metadata=model_metadata,
|
|
335
|
+
)
|
|
336
|
+
raw_text, usage = await client.summarize(
|
|
337
|
+
model=summary_model,
|
|
338
|
+
messages=prompt_messages,
|
|
339
|
+
timeout_ms=get_summary_timeout_ms(),
|
|
340
|
+
)
|
|
341
|
+
summary_text = extract_summary_text(raw_text)
|
|
342
|
+
if not summary_text:
|
|
343
|
+
raise RuntimeError("summary model returned empty <summary> block")
|
|
344
|
+
# LLM 调用成功,清零 semantic 失败计数。
|
|
345
|
+
_reset_semantic_failures()
|
|
346
|
+
return CompactionSummaryResult(
|
|
347
|
+
summary_text=_ensure_summary_prefix(summary_text),
|
|
348
|
+
summary_strategy="semantic",
|
|
349
|
+
summary_model=summary_model,
|
|
350
|
+
summary_usage=usage,
|
|
351
|
+
)
|
|
352
|
+
except Exception as exc:
|
|
353
|
+
# LLM 调用失败(非 extractive 主动选择),记录 semantic 失败用于熔断判定。
|
|
354
|
+
_record_semantic_failure()
|
|
355
|
+
return CompactionSummaryResult(
|
|
356
|
+
summary_text=fallback_summary,
|
|
357
|
+
summary_strategy="extractive",
|
|
358
|
+
fallback_reason=str(exc) or exc.__class__.__name__,
|
|
359
|
+
)
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
from typing import Any, Sequence
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from ksadk.configs.settings import settings
|
|
10
|
+
from ksadk.conversations.model_options import model_options_for_chat_completions
|
|
11
|
+
from ksadk.conversations.reasoning_markup import strip_reasoning_markup
|
|
12
|
+
|
|
13
|
+
DEFAULT_SESSION_TITLE_TIMEOUT_MS = 8_000
|
|
14
|
+
SESSION_TITLE_MAX_CHARS = 24
|
|
15
|
+
HEURISTIC_SESSION_TITLE_SOURCE = "heuristic"
|
|
16
|
+
SESSION_TITLE_SOURCE_SCAN_LIMIT = 8_000
|
|
17
|
+
|
|
18
|
+
_TITLE_PROMPT = (
|
|
19
|
+
"你是会话标题生成器。"
|
|
20
|
+
"请基于首轮用户问题和首轮助手回答,生成一个适合左侧会话列表的中文标题。\n"
|
|
21
|
+
"要求:\n"
|
|
22
|
+
"1. 优先输出 4 到 8 个汉字,最多 12 个汉字\n"
|
|
23
|
+
"2. 输出主题名或任务名,不要直接复述整句提问\n"
|
|
24
|
+
"3. 去掉“你好”“请”“帮我”“看看这个”等口语前缀和文件名\n"
|
|
25
|
+
"4. 如果是自我介绍/能力说明,改写成“能力介绍”“功能概览”这类主题名\n"
|
|
26
|
+
"5. 如果是在看图或看附件,改写成“架构图分析”“附件分析”“简历分析”这类主题名\n"
|
|
27
|
+
"6. 不要标点、引号、书名号、解释,只输出标题本身\n"
|
|
28
|
+
"示例:\n"
|
|
29
|
+
"- 你好,请介绍一下你自己 -> 招聘助手能力\n"
|
|
30
|
+
"- 看看这个上传文件,这里还有他画的架构图 -> 架构图分析"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
_SELF_INTRO_RE = re.compile(r"(介绍(?:一下)?你自己|你是谁|你的能力|你能做什么|自我介绍)")
|
|
34
|
+
_ARCH_RE = re.compile(r"(架构图|架构|微服务|系统设计|服务拓扑)")
|
|
35
|
+
_RECRUIT_RE = re.compile(r"(简历|候选人|面试|招聘|职位|jd\b)")
|
|
36
|
+
_FILE_RE = re.compile(r"(上传文件|上传图片|附件|file|pdf|png|jpg|jpeg)")
|
|
37
|
+
_ANALYZE_RE = re.compile(r"(分析|解读|评审|review|总结|说明|看下|看看|评估)")
|
|
38
|
+
_PROMPT_FILLERS_RE = re.compile(
|
|
39
|
+
r"^(你好|您好|请问|请|帮我|麻烦|看看这个|看看|看下|分析一下|分析|介绍一下|介绍|解释一下|解释|总结一下|总结|直接开始分析吧|直接开始|这里还有|这边有|给我看下)+",
|
|
40
|
+
)
|
|
41
|
+
_FILE_MARKER_WORDS = ("上传文件", "上传文件引用", "附件")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _replace_file_markup(text: str) -> str:
|
|
45
|
+
segments: list[str] = []
|
|
46
|
+
for line in str(text or "").splitlines():
|
|
47
|
+
stripped = line.lstrip("#").strip()
|
|
48
|
+
if stripped.startswith("附件") and any(sep in stripped for sep in ("-", ":", ":")):
|
|
49
|
+
segments.append(" 附件 ")
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
current = line
|
|
53
|
+
while "[" in current and "]" in current:
|
|
54
|
+
start = current.find("[")
|
|
55
|
+
end = current.find("]", start + 1)
|
|
56
|
+
if end < 0:
|
|
57
|
+
break
|
|
58
|
+
bracketed = current[start : end + 1]
|
|
59
|
+
if any(word in bracketed for word in _FILE_MARKER_WORDS):
|
|
60
|
+
current = f"{current[:start]} 附件 {current[end + 1:]}"
|
|
61
|
+
else:
|
|
62
|
+
break
|
|
63
|
+
segments.append(current)
|
|
64
|
+
return "\n".join(segments)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _normalize_source_text(text: str) -> str:
|
|
68
|
+
value = strip_reasoning_markup(str(text or "")[:SESSION_TITLE_SOURCE_SCAN_LIMIT]).strip()
|
|
69
|
+
if not value:
|
|
70
|
+
return ""
|
|
71
|
+
value = _replace_file_markup(value)
|
|
72
|
+
value = re.sub(r"\s+", " ", value)
|
|
73
|
+
return value.strip()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _sanitize_title(text: str) -> str:
|
|
77
|
+
value = strip_reasoning_markup(str(text or "")).strip()
|
|
78
|
+
if not value:
|
|
79
|
+
return ""
|
|
80
|
+
value = value.splitlines()[0].strip()
|
|
81
|
+
value = re.sub(r"^标题[::]\s*", "", value)
|
|
82
|
+
value = value.strip("`'\"“”‘’《》[]()()")
|
|
83
|
+
value = re.sub(r"[。!?!?;;::,,、]+$", "", value).strip()
|
|
84
|
+
value = " ".join(value.split())
|
|
85
|
+
if len(value) > SESSION_TITLE_MAX_CHARS:
|
|
86
|
+
value = value[:SESSION_TITLE_MAX_CHARS].rstrip()
|
|
87
|
+
return value
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _normalize_compare_text(text: str) -> str:
|
|
91
|
+
value = _normalize_source_text(text)
|
|
92
|
+
value = _PROMPT_FILLERS_RE.sub("", value).strip()
|
|
93
|
+
value = re.sub(r"[^\w\u4e00-\u9fff]+", "", value)
|
|
94
|
+
return value.lower()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _truncate_title(text: str) -> str:
|
|
98
|
+
value = strip_reasoning_markup(str(text or "")).strip()
|
|
99
|
+
if len(value) <= SESSION_TITLE_MAX_CHARS:
|
|
100
|
+
return value
|
|
101
|
+
return value[:SESSION_TITLE_MAX_CHARS].rstrip()
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def build_fallback_title(text: str) -> str:
|
|
105
|
+
value = _normalize_source_text(text)
|
|
106
|
+
value = _replace_file_markup(value)
|
|
107
|
+
value = re.sub(r"\s+", " ", value).strip()
|
|
108
|
+
return _truncate_title(value)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def build_heuristic_title(*, first_prompt: str, assistant_text: str) -> str:
|
|
112
|
+
prompt = _normalize_source_text(first_prompt)
|
|
113
|
+
assistant = _normalize_source_text(assistant_text)
|
|
114
|
+
combined = f"{prompt} {assistant}".strip()
|
|
115
|
+
prompt_lower = prompt.lower()
|
|
116
|
+
combined_lower = combined.lower()
|
|
117
|
+
|
|
118
|
+
if _SELF_INTRO_RE.search(prompt):
|
|
119
|
+
if _RECRUIT_RE.search(combined_lower):
|
|
120
|
+
return "招聘助手能力"
|
|
121
|
+
return "Agent能力介绍"
|
|
122
|
+
|
|
123
|
+
if _ARCH_RE.search(combined):
|
|
124
|
+
return "架构图分析" if _ANALYZE_RE.search(combined) or assistant else "架构讨论"
|
|
125
|
+
|
|
126
|
+
if _RECRUIT_RE.search(combined_lower):
|
|
127
|
+
if "简历" in combined_lower or "候选人" in combined_lower:
|
|
128
|
+
return "简历分析"
|
|
129
|
+
if "面试" in combined_lower and (_ANALYZE_RE.search(combined) or _FILE_RE.search(combined_lower)):
|
|
130
|
+
return "面试分析"
|
|
131
|
+
|
|
132
|
+
if _FILE_RE.search(combined_lower):
|
|
133
|
+
return "附件分析" if _ANALYZE_RE.search(combined) or assistant else "附件内容"
|
|
134
|
+
|
|
135
|
+
candidate = _PROMPT_FILLERS_RE.sub("", prompt).strip(",,。!?!?;;:: ")
|
|
136
|
+
candidate = re.sub(r"^(这个|这份|这张|这段|这个上传文件|上传文件|附件)\s*", "", candidate)
|
|
137
|
+
candidate = candidate.strip(",,。!?!?;;:: ")
|
|
138
|
+
if _SELF_INTRO_RE.search(candidate):
|
|
139
|
+
return "自我介绍"
|
|
140
|
+
if candidate.endswith("架构图") or candidate == "架构图":
|
|
141
|
+
return "架构图分析"
|
|
142
|
+
if _FILE_RE.search(candidate.lower()):
|
|
143
|
+
return "附件分析"
|
|
144
|
+
return _truncate_title(candidate)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def is_low_quality_title(title: str, *, first_prompt: str) -> bool:
|
|
148
|
+
cleaned_title = _sanitize_title(title)
|
|
149
|
+
if not cleaned_title:
|
|
150
|
+
return True
|
|
151
|
+
prompt_norm = _normalize_compare_text(first_prompt)
|
|
152
|
+
title_norm = _normalize_compare_text(cleaned_title)
|
|
153
|
+
if not title_norm:
|
|
154
|
+
return True
|
|
155
|
+
if title_norm == prompt_norm:
|
|
156
|
+
return True
|
|
157
|
+
if prompt_norm.startswith(title_norm) and len(prompt_norm) - len(title_norm) <= 4:
|
|
158
|
+
return True
|
|
159
|
+
if title_norm.startswith(("你好", "请", "帮我", "看看这个")):
|
|
160
|
+
return True
|
|
161
|
+
return False
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def resolve_session_title_model(current_model: str | None) -> str:
|
|
165
|
+
override = str(os.getenv("SESSION_TITLE_MODEL", "")).strip()
|
|
166
|
+
if override:
|
|
167
|
+
return override
|
|
168
|
+
if current_model:
|
|
169
|
+
return str(current_model).strip()
|
|
170
|
+
return str(settings.model.model_name or "").strip()
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def build_session_title_messages(*, first_prompt: str, assistant_text: str) -> list[dict[str, str]]:
|
|
174
|
+
assistant_excerpt = strip_reasoning_markup(str(assistant_text or "")).strip()
|
|
175
|
+
if len(assistant_excerpt) > 240:
|
|
176
|
+
assistant_excerpt = assistant_excerpt[:240].rstrip() + "…"
|
|
177
|
+
return [
|
|
178
|
+
{"role": "system", "content": _TITLE_PROMPT},
|
|
179
|
+
{
|
|
180
|
+
"role": "user",
|
|
181
|
+
"content": (
|
|
182
|
+
f"首轮用户问题:\n{str(first_prompt or '').strip()}\n\n"
|
|
183
|
+
f"首轮助手回答:\n{assistant_excerpt}"
|
|
184
|
+
),
|
|
185
|
+
},
|
|
186
|
+
]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class SessionTitleClient:
|
|
190
|
+
def __init__(
|
|
191
|
+
self,
|
|
192
|
+
*,
|
|
193
|
+
api_base: str | None = None,
|
|
194
|
+
api_key: str | None = None,
|
|
195
|
+
):
|
|
196
|
+
self.api_base = str(api_base or settings.model.api_base or "").rstrip("/")
|
|
197
|
+
self.api_key = str(api_key or settings.model.api_key or "").strip()
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def is_available(self) -> bool:
|
|
201
|
+
return bool(self.api_base and self.api_key)
|
|
202
|
+
|
|
203
|
+
def _chat_completions_url(self) -> str:
|
|
204
|
+
if self.api_base.endswith("/v1"):
|
|
205
|
+
return f"{self.api_base}/chat/completions"
|
|
206
|
+
return f"{self.api_base}/v1/chat/completions"
|
|
207
|
+
|
|
208
|
+
async def generate_title(
|
|
209
|
+
self,
|
|
210
|
+
*,
|
|
211
|
+
model: str,
|
|
212
|
+
messages: Sequence[dict[str, str]],
|
|
213
|
+
timeout_ms: int = DEFAULT_SESSION_TITLE_TIMEOUT_MS,
|
|
214
|
+
) -> tuple[str, dict[str, Any]]:
|
|
215
|
+
if not self.is_available:
|
|
216
|
+
raise RuntimeError("session title client is not configured")
|
|
217
|
+
if not model:
|
|
218
|
+
raise RuntimeError("session title model is not configured")
|
|
219
|
+
|
|
220
|
+
headers = {
|
|
221
|
+
"Content-Type": "application/json",
|
|
222
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
223
|
+
}
|
|
224
|
+
payload = {
|
|
225
|
+
"model": model,
|
|
226
|
+
"messages": list(messages),
|
|
227
|
+
"stream": False,
|
|
228
|
+
"temperature": 0,
|
|
229
|
+
**model_options_for_chat_completions({"thinking": {"type": "disabled"}}),
|
|
230
|
+
}
|
|
231
|
+
timeout_seconds = max(1.0, float(timeout_ms) / 1000.0)
|
|
232
|
+
async with httpx.AsyncClient(timeout=timeout_seconds) as client:
|
|
233
|
+
response = await client.post(self._chat_completions_url(), headers=headers, json=payload)
|
|
234
|
+
response.raise_for_status()
|
|
235
|
+
data = response.json()
|
|
236
|
+
|
|
237
|
+
choices = data.get("choices") or []
|
|
238
|
+
message = choices[0].get("message") if choices else {}
|
|
239
|
+
content = message.get("content") if isinstance(message, dict) else ""
|
|
240
|
+
if isinstance(content, list):
|
|
241
|
+
fragments: list[str] = []
|
|
242
|
+
for item in content:
|
|
243
|
+
if isinstance(item, dict) and item.get("text"):
|
|
244
|
+
fragments.append(str(item["text"]))
|
|
245
|
+
content = "\n".join(fragment for fragment in fragments if fragment)
|
|
246
|
+
|
|
247
|
+
title = _sanitize_title(str(content or ""))
|
|
248
|
+
if not title:
|
|
249
|
+
raise RuntimeError("session title model returned empty content")
|
|
250
|
+
return title, dict(data.get("usage") or {})
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def resolve_session_title_client() -> SessionTitleClient:
|
|
254
|
+
return SessionTitleClient()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
部署模块
|
|
3
|
+
|
|
4
|
+
支持多种部署目标:
|
|
5
|
+
- docker: 本地 Docker 容器
|
|
6
|
+
- k8s: Kubernetes 集群
|
|
7
|
+
- serverless: 金山云 Serverless 计算引擎
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from ksadk.deployment.base import (
|
|
11
|
+
BaseDeployProvider,
|
|
12
|
+
DeployTarget,
|
|
13
|
+
DeployResult,
|
|
14
|
+
DeployStatus,
|
|
15
|
+
PackageInfo,
|
|
16
|
+
ResourceSpec,
|
|
17
|
+
ScalingConfig,
|
|
18
|
+
NetworkConfig,
|
|
19
|
+
)
|
|
20
|
+
from ksadk.deployment.registry import DeployProviderRegistry
|
|
21
|
+
|
|
22
|
+
# 导入并注册所有 Provider
|
|
23
|
+
from ksadk.deployment import providers
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DeploymentManager:
|
|
27
|
+
"""部署管理器 - 统一入口
|
|
28
|
+
|
|
29
|
+
使用方式:
|
|
30
|
+
manager = DeploymentManager()
|
|
31
|
+
provider = manager.get_provider("docker")
|
|
32
|
+
result = await provider.deploy(package_info, target)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def get_provider(name: str, config: dict = None) -> BaseDeployProvider:
|
|
37
|
+
"""获取部署 Provider
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
name: Provider 名称 (docker, k8s, serverless)
|
|
41
|
+
config: Provider 配置
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Provider 实例
|
|
45
|
+
"""
|
|
46
|
+
return DeployProviderRegistry.get(name, config)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def list_providers() -> list:
|
|
50
|
+
"""列出所有可用 Provider"""
|
|
51
|
+
return DeployProviderRegistry.get_provider_info()
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def has_provider(name: str) -> bool:
|
|
55
|
+
"""检查 Provider 是否存在"""
|
|
56
|
+
return DeployProviderRegistry.has_provider(name)
|
|
57
|
+
|
|
58
|
+
# 向后兼容: create() 方法
|
|
59
|
+
@classmethod
|
|
60
|
+
def create(cls, target: str) -> DeployTarget:
|
|
61
|
+
"""创建部署目标
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
target: 部署目标 (docker, k8s, serverless)
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
部署目标实例
|
|
68
|
+
"""
|
|
69
|
+
return cls.get_provider(target)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = [
|
|
73
|
+
"DeploymentManager",
|
|
74
|
+
"BaseDeployProvider",
|
|
75
|
+
"DeployTarget",
|
|
76
|
+
"DeployResult",
|
|
77
|
+
"DeployStatus",
|
|
78
|
+
"PackageInfo",
|
|
79
|
+
"ResourceSpec",
|
|
80
|
+
"ScalingConfig",
|
|
81
|
+
"NetworkConfig",
|
|
82
|
+
"DeployProviderRegistry",
|
|
83
|
+
]
|