agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.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 → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
- agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
- ksadk/a2a/__init__.py +178 -11
- ksadk/a2a/bootstrap.py +334 -0
- ksadk/a2a/card.py +120 -0
- ksadk/a2a/context_store.py +203 -0
- ksadk/a2a/control_plane.py +818 -0
- ksadk/a2a/credential.py +99 -0
- ksadk/a2a/event_adapter.py +149 -0
- ksadk/a2a/executor.py +406 -89
- ksadk/a2a/external_transport.py +516 -0
- ksadk/a2a/identity.py +304 -0
- ksadk/a2a/ids.py +22 -0
- ksadk/a2a/langgraph.py +285 -0
- ksadk/a2a/resume_store.py +201 -0
- ksadk/a2a/routes.py +105 -0
- ksadk/a2a/server.py +107 -60
- ksadk/a2a/space_client.py +1101 -0
- ksadk/a2a/task_adapter.py +423 -0
- ksadk/a2a/task_event_dispatcher.py +167 -0
- ksadk/a2a/task_event_outbox.py +326 -0
- ksadk/a2a/task_store.py +206 -0
- ksadk/a2ui/__init__.py +27 -0
- ksadk/a2ui/core.py +186 -0
- ksadk/a2ui/models.py +166 -0
- ksadk/a2ui/renderer.py +198 -0
- ksadk/agui/__init__.py +9 -0
- ksadk/agui/a2ui_projection.py +92 -0
- ksadk/agui/agent.py +857 -0
- ksadk/agui/config.py +86 -0
- ksadk/agui/routes.py +55 -0
- ksadk/api/client.py +233 -191
- ksadk/builders/__init__.py +2 -0
- ksadk/builders/base.py +16 -14
- ksadk/builders/code_builder.py +318 -236
- ksadk/builders/container_builder.py +187 -167
- ksadk/builders/framework_requirements.py +29 -11
- ksadk/builders/ks3_uploader.py +58 -27
- ksadk/builders/managed_runtime_builder.py +145 -0
- ksadk/builders/mcp_builder.py +91 -92
- ksadk/builders/requirements_utils.py +1 -5
- ksadk/cli/__init__.py +89 -171
- ksadk/cli/cmd_a2a.py +254 -70
- ksadk/cli/cmd_agent.py +19 -5
- ksadk/cli/cmd_build.py +158 -29
- ksadk/cli/cmd_completion.py +47 -35
- ksadk/cli/cmd_config.py +267 -198
- ksadk/cli/cmd_create.py +500 -720
- ksadk/cli/cmd_dashboard.py +120 -45
- ksadk/cli/cmd_deploy.py +117 -58
- ksadk/cli/cmd_destroy.py +44 -14
- ksadk/cli/cmd_files.py +63 -24
- ksadk/cli/cmd_hermes.py +168 -89
- ksadk/cli/cmd_invoke.py +184 -122
- ksadk/cli/cmd_launch.py +64 -28
- ksadk/cli/cmd_mcp.py +98 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +483 -227
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +33 -10
- ksadk/cli/cmd_status.py +80 -31
- ksadk/cli/cmd_version.py +20 -13
- ksadk/cli/cmd_web.py +89 -13
- ksadk/cli/deploy_utils.py +20 -20
- ksadk/cli/dry_run.py +5 -3
- ksadk/cli/error_utils.py +37 -12
- ksadk/cli/global_options.py +1 -2
- ksadk/cli/local_runtime.py +1 -2
- ksadk/cli/model_catalog.py +6 -2
- ksadk/cli/network_options.py +34 -14
- ksadk/cli/resource_common.py +6 -2
- ksadk/cli/storage.py +0 -1
- ksadk/cli/ui.py +5 -3
- ksadk/cli/workflow_common.py +51 -17
- ksadk/codex/__init__.py +12 -0
- ksadk/codex/client.py +408 -0
- ksadk/codex/phase.py +143 -0
- ksadk/codex/runtime.py +449 -0
- ksadk/common/aicp_env.py +0 -1
- ksadk/common/auth.py +2 -2
- ksadk/common/constants.py +1 -3
- ksadk/common/llm_utils.py +17 -13
- ksadk/compat/__init__.py +5 -0
- ksadk/compat/adk_compat.py +200 -0
- ksadk/compat/copilotkit_a2ui.py +330 -0
- ksadk/configs/__init__.py +12 -12
- ksadk/configs/env_registry.py +500 -100
- ksadk/configs/global_config.py +2 -1
- ksadk/configs/settings.py +151 -124
- ksadk/conversations/__init__.py +7 -5
- ksadk/conversations/attachment_storage.py +16 -11
- ksadk/conversations/attachments.py +44 -36
- ksadk/conversations/compaction_pipeline.py +12 -12
- ksadk/conversations/compaction_prompt.py +9 -5
- ksadk/conversations/context.py +221 -6
- ksadk/conversations/message_projection.py +438 -51
- ksadk/conversations/model_context.py +12 -6
- ksadk/conversations/model_options.py +0 -1
- ksadk/conversations/normalize.py +20 -16
- ksadk/conversations/reasoning_markup.py +1 -1
- ksadk/conversations/runtime.py +339 -5255
- ksadk/conversations/runtime_compaction.py +333 -0
- ksadk/conversations/runtime_constants.py +27 -0
- ksadk/conversations/runtime_governance.py +185 -0
- ksadk/conversations/runtime_input.py +652 -0
- ksadk/conversations/runtime_invocation.py +395 -0
- ksadk/conversations/runtime_metadata.py +475 -0
- ksadk/conversations/runtime_observability.py +355 -0
- ksadk/conversations/runtime_payloads.py +272 -0
- ksadk/conversations/runtime_persistence.py +440 -0
- ksadk/conversations/runtime_preparation.py +418 -0
- ksadk/conversations/runtime_resume.py +816 -0
- ksadk/conversations/runtime_stream_events.py +902 -0
- ksadk/conversations/runtime_streaming.py +547 -0
- ksadk/conversations/semantic_summary.py +17 -5
- ksadk/conversations/session_title.py +6 -3
- ksadk/deployment/__init__.py +15 -16
- ksadk/deployment/agent_access.py +12 -23
- ksadk/deployment/base.py +51 -38
- ksadk/deployment/manager.py +63 -65
- ksadk/deployment/providers/serverless.py +309 -202
- ksadk/deployment/registry.py +38 -32
- ksadk/deployment/state.py +11 -11
- ksadk/deployment/ui_config.py +1 -1
- ksadk/detection/__init__.py +1 -1
- ksadk/detection/detector.py +146 -83
- ksadk/detection/mcp_detector.py +9 -6
- ksadk/events/__init__.py +25 -0
- ksadk/events/parser.py +191 -0
- ksadk/events/replay.py +37 -0
- ksadk/events/runtime_event.py +264 -0
- ksadk/events/store.py +317 -0
- ksadk/harness/__init__.py +34 -0
- ksadk/harness/app.py +278 -0
- ksadk/harness/config.py +181 -0
- ksadk/harness/reasoner.py +105 -0
- ksadk/harness/runner.py +211 -0
- ksadk/harness/sandbox.py +141 -0
- ksadk/harness/tools.py +222 -0
- ksadk/hermes_terminal.py +23 -12
- ksadk/identity/resolver.py +15 -9
- ksadk/ids.py +32 -0
- ksadk/knowledge_base/adk_tool.py +1 -1
- ksadk/knowledge_base/client.py +23 -29
- ksadk/managed_runtime.py +188 -0
- ksadk/markdown.py +5 -2
- ksadk/mcp_runtime/__init__.py +9 -6
- ksadk/memory/__init__.py +1 -1
- ksadk/memory/adk/__init__.py +2 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
- ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
- ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
- ksadk/memory/adk/long_term_memory.py +31 -35
- ksadk/memory/adk/resilient_session_service.py +4 -5
- ksadk/memory/adk/short_term_memory.py +12 -21
- ksadk/memory/adk_tool.py +3 -2
- ksadk/memory/backends/base.py +19 -19
- ksadk/memory/backends/memory.py +24 -25
- ksadk/memory/backends/redis.py +31 -30
- ksadk/memory/langchain_tool.py +2 -1
- ksadk/memory/manager.py +52 -47
- ksadk/memory/service.py +10 -8
- ksadk/model_policy.py +15 -7
- ksadk/model_proxy/__init__.py +51 -0
- ksadk/model_proxy/bootstrap.py +80 -0
- ksadk/model_proxy/cache.py +165 -0
- ksadk/model_proxy/config.py +45 -0
- ksadk/model_proxy/demo_webui.py +115 -0
- ksadk/model_proxy/detect.py +145 -0
- ksadk/model_proxy/gate.py +68 -0
- ksadk/model_proxy/namespace.py +173 -0
- ksadk/model_proxy/protocol_proxy.py +22 -0
- ksadk/model_proxy/server.py +300 -0
- ksadk/model_proxy/transform.py +691 -0
- ksadk/openclaw_gateway.py +29 -14
- ksadk/runners/adk_runner.py +345 -120
- ksadk/runners/base_runner.py +46 -29
- ksadk/runners/codex_runner.py +132 -0
- ksadk/runners/deepagents_runner.py +0 -1
- ksadk/runners/factory.py +17 -5
- ksadk/runners/langchain_runner.py +29 -742
- ksadk/runners/langgraph_runner.py +352 -90
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +134 -33
- ksadk/runners/usage_accumulator.py +1 -0
- ksadk/runners/utils/langfuse.py +3 -3
- ksadk/runners/utils/loader.py +7 -7
- ksadk/runtime/__init__.py +41 -0
- ksadk/runtime/adapter.py +345 -0
- ksadk/runtime/framework_adapters.py +124 -0
- ksadk/runtime/preprocessing.py +118 -0
- ksadk/runtime/runner_adapter.py +873 -0
- ksadk/runtime_context.py +18 -3
- ksadk/runtime_state.py +0 -1
- ksadk/sandbox/__init__.py +4 -1
- ksadk/sandbox/backends/__init__.py +4 -1
- ksadk/sandbox/backends/e2b.py +13 -5
- ksadk/sandbox/backends/local_process.py +11 -3
- ksadk/sandbox/base.py +10 -15
- ksadk/sandbox/factory.py +14 -4
- ksadk/sandbox/registry.py +57 -6
- ksadk/server/api_models.py +15 -5
- ksadk/server/app.py +455 -3885
- ksadk/server/composition.py +21 -0
- ksadk/server/factory.py +624 -0
- ksadk/server/routes/__init__.py +1 -0
- ksadk/server/routes/checkpoint_resolution.py +116 -0
- ksadk/server/routes/common.py +713 -0
- ksadk/server/routes/control.py +327 -0
- ksadk/server/routes/dependencies.py +98 -0
- ksadk/server/routes/misc.py +448 -0
- ksadk/server/routes/models.py +443 -0
- ksadk/server/routes/openai_compat.py +207 -0
- ksadk/server/routes/projection.py +795 -0
- ksadk/server/routes/routers.py +52 -0
- ksadk/server/routes/run.py +726 -0
- ksadk/server/routes/sessions.py +649 -0
- ksadk/server/routes/streaming.py +223 -0
- ksadk/server/routes/workspace.py +381 -0
- ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
- ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
- ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
- ksadk/server/static/assets/{arc-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
- ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
- ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
- ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
- ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
- ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
- ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
- ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
- ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
- ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
- ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
- ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
- ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
- ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
- ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
- ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
- ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
- ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
- ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
- ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
- ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
- ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
- ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
- ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
- ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
- ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
- ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
- ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
- ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
- ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +111 -58
- ksadk/sessions/__init__.py +69 -19
- ksadk/sessions/base.py +31 -11
- ksadk/sessions/continuity.py +2 -3
- ksadk/sessions/in_memory.py +46 -2
- ksadk/sessions/local_service.py +148 -17
- ksadk/sessions/postgres_service.py +143 -25
- ksadk/sessions/resilient.py +36 -8
- ksadk/skills/models.py +17 -5
- ksadk/skills/package_store.py +5 -2
- ksadk/skills/runtime/agent.py +20 -5
- ksadk/skills/runtime/artifacts.py +1 -5
- ksadk/skills/runtime/backends/e2b.py +10 -4
- ksadk/skills/runtime/backends/local.py +15 -3
- ksadk/skills/runtime/base.py +1 -2
- ksadk/skills/runtime/executor.py +10 -3
- ksadk/skills/runtime/factory.py +4 -2
- ksadk/skills/runtime/loader.py +1 -2
- ksadk/skills/runtime/registry.py +15 -10
- ksadk/skills/runtime/request.py +3 -1
- ksadk/skills/service_client.py +38 -17
- ksadk/skills/tool_defs.py +15 -10
- ksadk/terminal_exec_policy.py +3 -4
- ksadk/tools/gateway.py +92 -15
- ksadk/tools/result_budget.py +12 -4
- ksadk/toolsets/__init__.py +134 -36
- ksadk/toolsets/platform.py +21 -5
- ksadk/toolsets/sandbox.py +82 -16
- ksadk/toolsets/skills.py +200 -39
- ksadk/toolsets/web.py +123 -26
- ksadk/toolsets/workspace.py +212 -101
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/exporters/langfuse_exporter.py +91 -76
- ksadk/tracing/setup.py +69 -53
- ksadk/tracing/span_utils.py +5 -2
- ksadk/tui/loop.py +78 -30
- ksadk/tui/stream_render.py +1 -0
- ksadk/ui_config.py +5 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
- agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
- ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
- ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
- ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
- ksadk/server/static/assets/channel-CTuydARX.js +0 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
- ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
- ksadk/server/static/assets/index-DAURbCsP.css +0 -1
- ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
- ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
- ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
- ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
ksadk/api/client.py
CHANGED
|
@@ -4,17 +4,17 @@ AgentEngine Server API 客户端
|
|
|
4
4
|
支持 AWS V4 签名认证,用于通过 KOP 网关访问 AgentEngine Server。
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import os
|
|
8
|
-
import re
|
|
9
7
|
import json
|
|
10
|
-
import uuid
|
|
11
|
-
import socket
|
|
12
8
|
import logging
|
|
13
9
|
import mimetypes
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import socket
|
|
13
|
+
import uuid
|
|
14
14
|
from contextlib import contextmanager
|
|
15
15
|
from dataclasses import dataclass
|
|
16
16
|
from pathlib import Path
|
|
17
|
-
from typing import
|
|
17
|
+
from typing import Any, Callable, Dict, Iterator, Optional, Sequence
|
|
18
18
|
from urllib.parse import quote, unquote, urlparse, urlsplit
|
|
19
19
|
|
|
20
20
|
import requests
|
|
@@ -38,7 +38,9 @@ class AttachmentContent:
|
|
|
38
38
|
class DryRunExit(Exception):
|
|
39
39
|
"""DryRun 模式退出异常。"""
|
|
40
40
|
|
|
41
|
-
def __init__(
|
|
41
|
+
def __init__(
|
|
42
|
+
self, message: str = "Dry Run finished.", *, payload: Optional[Dict[str, Any]] = None
|
|
43
|
+
):
|
|
42
44
|
self.payload = payload or {}
|
|
43
45
|
super().__init__(message)
|
|
44
46
|
|
|
@@ -54,6 +56,7 @@ class AgentEngineAPIError(Exception):
|
|
|
54
56
|
details: Optional[Dict[str, Any]] = None,
|
|
55
57
|
):
|
|
56
58
|
self.raw_code = code
|
|
59
|
+
self.code: Optional[int]
|
|
57
60
|
try:
|
|
58
61
|
self.code = int(code)
|
|
59
62
|
except (TypeError, ValueError):
|
|
@@ -69,9 +72,9 @@ class AgentEngineAPIError(Exception):
|
|
|
69
72
|
|
|
70
73
|
class AgentEngineClient:
|
|
71
74
|
"""AgentEngine Server API 客户端
|
|
72
|
-
|
|
75
|
+
|
|
73
76
|
使用 AWS V4 签名认证访问 KOP 网关后的 AgentEngine Server。
|
|
74
|
-
|
|
77
|
+
|
|
75
78
|
凭证来源 (优先级从高到低):
|
|
76
79
|
1. 构造函数参数
|
|
77
80
|
2. 环境变量 KSYUN_ACCESS_KEY / KSYUN_SECRET_KEY
|
|
@@ -85,8 +88,8 @@ class AgentEngineClient:
|
|
|
85
88
|
_permission_probe_cache: dict[tuple[str, str, str], bool] = {}
|
|
86
89
|
|
|
87
90
|
def __init__(
|
|
88
|
-
self,
|
|
89
|
-
base_url: Optional[str] = None,
|
|
91
|
+
self,
|
|
92
|
+
base_url: Optional[str] = None,
|
|
90
93
|
access_key: Optional[str] = None,
|
|
91
94
|
secret_key: Optional[str] = None,
|
|
92
95
|
region: str = "cn-beijing-6",
|
|
@@ -95,13 +98,9 @@ class AgentEngineClient:
|
|
|
95
98
|
dry_run: bool = False,
|
|
96
99
|
extra_headers: Optional[Dict[str, str]] = None,
|
|
97
100
|
):
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
102
|
-
if not self.base_url:
|
|
103
|
-
self.base_url = self._detect_default_base_url()
|
|
104
|
-
|
|
101
|
+
resolved_base_url = base_url or os.getenv("AGENTENGINE_SERVER_URL")
|
|
102
|
+
self.base_url: str = resolved_base_url or self._detect_default_base_url()
|
|
103
|
+
|
|
105
104
|
# 本地调试覆盖 (如果需要)
|
|
106
105
|
# self.base_url = "http://localhost:8081"
|
|
107
106
|
self.timeout = timeout
|
|
@@ -111,8 +110,8 @@ class AgentEngineClient:
|
|
|
111
110
|
self.dry_run = bool(dry_run or self._is_global_dry_run_enabled())
|
|
112
111
|
self.extra_headers = extra_headers or {}
|
|
113
112
|
# 签名 service 可通过环境变量覆盖(例如 aicp)
|
|
114
|
-
self.service = service or os.getenv("AGENTENGINE_SIGN_SERVICE"
|
|
115
|
-
|
|
113
|
+
self.service: str = service or os.getenv("AGENTENGINE_SIGN_SERVICE") or "aicp"
|
|
114
|
+
|
|
116
115
|
# AWS V4 签名
|
|
117
116
|
self._auth = AWSV4Auth(
|
|
118
117
|
access_key_id=access_key or "",
|
|
@@ -120,12 +119,12 @@ class AgentEngineClient:
|
|
|
120
119
|
region=self.region,
|
|
121
120
|
service=self.service,
|
|
122
121
|
)
|
|
123
|
-
|
|
122
|
+
|
|
124
123
|
if self._auth.is_enabled:
|
|
125
124
|
logger.debug(f"AgentEngineClient initialized with V4Auth: {self.base_url}")
|
|
126
125
|
else:
|
|
127
126
|
logger.debug("AgentEngineClient: No credentials, signing disabled")
|
|
128
|
-
|
|
127
|
+
|
|
129
128
|
self._session: Optional[requests.Session] = None
|
|
130
129
|
self._http_error_log_suppressors: list[HttpErrorLogSuppressor] = []
|
|
131
130
|
# 反查身份的实例缓存(避免同会话重复调 IAM);None=未尝试,ResolvedIdentity|None=已反查
|
|
@@ -135,10 +134,10 @@ class AgentEngineClient:
|
|
|
135
134
|
@staticmethod
|
|
136
135
|
def _ssl_verify_enabled() -> bool:
|
|
137
136
|
insecure = (
|
|
138
|
-
os.getenv("AGENTENGINE_SSL_INSECURE")
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
)
|
|
137
|
+
(os.getenv("AGENTENGINE_SSL_INSECURE") or os.getenv("CURL_SSL_INSECURE") or "")
|
|
138
|
+
.strip()
|
|
139
|
+
.lower()
|
|
140
|
+
)
|
|
142
141
|
if insecure in {"1", "true", "yes", "on"}:
|
|
143
142
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
144
143
|
return False
|
|
@@ -303,7 +302,9 @@ class AgentEngineClient:
|
|
|
303
302
|
@staticmethod
|
|
304
303
|
def _is_auth_related_error_details(details: Dict[str, Any]) -> bool:
|
|
305
304
|
remote_code = str(details.get("remote_error_code") or "").strip().lower()
|
|
306
|
-
remote_message =
|
|
305
|
+
remote_message = (
|
|
306
|
+
str(details.get("remote_error_message") or details.get("message") or "").strip().lower()
|
|
307
|
+
)
|
|
307
308
|
if remote_code in {
|
|
308
309
|
"missingaccesskey",
|
|
309
310
|
"missingsecretkey",
|
|
@@ -336,7 +337,9 @@ class AgentEngineClient:
|
|
|
336
337
|
@staticmethod
|
|
337
338
|
def _is_inner_account_intranet_error(details: Dict[str, Any]) -> bool:
|
|
338
339
|
remote_code = str(details.get("remote_error_code") or "").strip().lower()
|
|
339
|
-
remote_message =
|
|
340
|
+
remote_message = (
|
|
341
|
+
str(details.get("remote_error_message") or details.get("message") or "").strip().lower()
|
|
342
|
+
)
|
|
340
343
|
return (
|
|
341
344
|
remote_code == "inneraccountcanonlyaccessthroughintranet"
|
|
342
345
|
or "inner account can only access through intranet" in remote_message
|
|
@@ -356,7 +359,9 @@ class AgentEngineClient:
|
|
|
356
359
|
)
|
|
357
360
|
self.base_url = self._INNER_AICP_BASE_URL
|
|
358
361
|
|
|
359
|
-
def _build_action_request_target(
|
|
362
|
+
def _build_action_request_target(
|
|
363
|
+
self, path: str, action: str
|
|
364
|
+
) -> tuple[bool, Dict[str, str], str]:
|
|
360
365
|
kop_mode = self._is_kop_mode()
|
|
361
366
|
headers = self._build_headers(action=action, kop_mode=kop_mode)
|
|
362
367
|
if kop_mode:
|
|
@@ -366,14 +371,17 @@ class AgentEngineClient:
|
|
|
366
371
|
full_url = f"{self.base_url}{path}"
|
|
367
372
|
return kop_mode, headers, full_url
|
|
368
373
|
|
|
369
|
-
def _build_raw_action_request_target(
|
|
374
|
+
def _build_raw_action_request_target(
|
|
375
|
+
self, action: str, accept: str, has_files: bool
|
|
376
|
+
) -> tuple[bool, Dict[str, str], str]:
|
|
370
377
|
kop_mode = self._is_kop_mode()
|
|
371
378
|
headers = self._build_headers(action=action, kop_mode=kop_mode)
|
|
372
379
|
headers["Accept"] = accept
|
|
373
380
|
if has_files:
|
|
374
381
|
headers.pop("Content-Type", None)
|
|
382
|
+
version = os.getenv("AGENTENGINE_API_VERSION", "2024-06-12")
|
|
375
383
|
full_url = (
|
|
376
|
-
f"{self.base_url.rstrip('/')}/?Action={action}&Version={
|
|
384
|
+
f"{self.base_url.rstrip('/')}/?Action={action}&Version={version}"
|
|
377
385
|
if kop_mode
|
|
378
386
|
else f"{self.base_url}/agentengine/api/v1/{action}"
|
|
379
387
|
)
|
|
@@ -394,7 +402,9 @@ class AgentEngineClient:
|
|
|
394
402
|
if self._http_error_log_suppressors:
|
|
395
403
|
self._http_error_log_suppressors.pop()
|
|
396
404
|
|
|
397
|
-
def _log_http_error(
|
|
405
|
+
def _log_http_error(
|
|
406
|
+
self, *, method: str, full_url: str, status_code: int, details: Dict[str, Any]
|
|
407
|
+
) -> None:
|
|
398
408
|
for suppressor in reversed(self._http_error_log_suppressors):
|
|
399
409
|
try:
|
|
400
410
|
if suppressor(
|
|
@@ -433,7 +443,9 @@ class AgentEngineClient:
|
|
|
433
443
|
message = " ".join(message.split())[:200]
|
|
434
444
|
return f"{code}: {message}" if code else message
|
|
435
445
|
|
|
436
|
-
def _build_headers(
|
|
446
|
+
def _build_headers(
|
|
447
|
+
self, request_id: str = "", action: str = "", kop_mode: bool = False
|
|
448
|
+
) -> Dict[str, str]:
|
|
437
449
|
if not request_id:
|
|
438
450
|
request_id = str(uuid.uuid4())
|
|
439
451
|
headers = {
|
|
@@ -508,9 +520,7 @@ class AgentEngineClient:
|
|
|
508
520
|
# dry-run 不联网,只读缓存
|
|
509
521
|
self._resolved_identity = get_cached_identity(ak)
|
|
510
522
|
else:
|
|
511
|
-
self._resolved_identity = resolve_identity(
|
|
512
|
-
access_key=ak, secret_key=sk
|
|
513
|
-
)
|
|
523
|
+
self._resolved_identity = resolve_identity(access_key=ak, secret_key=sk)
|
|
514
524
|
except Exception as e:
|
|
515
525
|
logger.warning("反查子账号身份失败: %s", e)
|
|
516
526
|
self._resolved_identity = None
|
|
@@ -536,9 +546,7 @@ class AgentEngineClient:
|
|
|
536
546
|
access = params.get("Access") if isinstance(params, dict) else None
|
|
537
547
|
if isinstance(access, dict):
|
|
538
548
|
explicit_role = (
|
|
539
|
-
access.get("IamRole")
|
|
540
|
-
or access.get("iamRole")
|
|
541
|
-
or access.get("iam_role")
|
|
549
|
+
access.get("IamRole") or access.get("iamRole") or access.get("iam_role")
|
|
542
550
|
)
|
|
543
551
|
if str(explicit_role or "").strip():
|
|
544
552
|
return str(explicit_role).strip()
|
|
@@ -597,9 +605,9 @@ class AgentEngineClient:
|
|
|
597
605
|
self._permission_probe_cache[cache_key] = True
|
|
598
606
|
|
|
599
607
|
def _request(
|
|
600
|
-
self,
|
|
608
|
+
self,
|
|
601
609
|
method: str,
|
|
602
|
-
path: str,
|
|
610
|
+
path: str,
|
|
603
611
|
body: Optional[Dict[str, Any]] = None,
|
|
604
612
|
*,
|
|
605
613
|
ignore_dry_run: bool = False,
|
|
@@ -608,7 +616,7 @@ class AgentEngineClient:
|
|
|
608
616
|
action = path.rstrip("/").split("/")[-1] if path else ""
|
|
609
617
|
_kop_mode, headers, full_url = self._build_action_request_target(path, action)
|
|
610
618
|
body_str = json.dumps(body, ensure_ascii=False) if body else ""
|
|
611
|
-
|
|
619
|
+
|
|
612
620
|
# DryRun 模式
|
|
613
621
|
if self.dry_run and not ignore_dry_run:
|
|
614
622
|
signed_headers = headers
|
|
@@ -622,9 +630,9 @@ class AgentEngineClient:
|
|
|
622
630
|
)
|
|
623
631
|
|
|
624
632
|
# 生成 Curl 命令
|
|
625
|
-
curl_cmd = f
|
|
633
|
+
curl_cmd = f'curl -X {method} "{full_url}" \\\n'
|
|
626
634
|
for k, v in signed_headers.items():
|
|
627
|
-
curl_cmd += f
|
|
635
|
+
curl_cmd += f' -H "{k}: {v}" \\\n'
|
|
628
636
|
if body_str:
|
|
629
637
|
curl_cmd += f" -d '{body_str}'"
|
|
630
638
|
|
|
@@ -639,7 +647,7 @@ class AgentEngineClient:
|
|
|
639
647
|
"curl": curl_cmd,
|
|
640
648
|
},
|
|
641
649
|
)
|
|
642
|
-
|
|
650
|
+
|
|
643
651
|
session = self._get_session()
|
|
644
652
|
|
|
645
653
|
retried_inner_endpoint = False
|
|
@@ -685,31 +693,36 @@ class AgentEngineClient:
|
|
|
685
693
|
|
|
686
694
|
if response.text:
|
|
687
695
|
try:
|
|
688
|
-
|
|
696
|
+
payload = response.json()
|
|
689
697
|
except Exception as e:
|
|
690
698
|
raise Exception(f"Invalid JSON response from {full_url}: {response.text}") from e
|
|
699
|
+
if not isinstance(payload, dict):
|
|
700
|
+
raise Exception(f"Invalid JSON response from {full_url}: expected an object")
|
|
701
|
+
return payload
|
|
691
702
|
return {}
|
|
692
|
-
|
|
703
|
+
|
|
693
704
|
# Async 包装 (保持兼容性)
|
|
694
705
|
async def close(self):
|
|
695
706
|
if self._session:
|
|
696
707
|
self._session.close()
|
|
697
708
|
self._session = None
|
|
698
|
-
|
|
709
|
+
|
|
699
710
|
async def __aenter__(self):
|
|
700
711
|
return self
|
|
701
|
-
|
|
712
|
+
|
|
702
713
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
703
714
|
await self.close()
|
|
704
715
|
|
|
705
716
|
# ===== Action API (推荐使用) =====
|
|
706
|
-
|
|
717
|
+
|
|
707
718
|
@staticmethod
|
|
708
719
|
def _pascal_key(key: str) -> str:
|
|
709
720
|
"""PascalCase/camelCase 键名转 snake_case"""
|
|
710
721
|
# "MCPs" -> "mcps", "AgentId" -> "agent_id", "QuickAccess" -> "quick_access"
|
|
711
|
-
|
|
712
|
-
|
|
722
|
+
if re.fullmatch(r"[A-Z]+s", key):
|
|
723
|
+
return key.lower()
|
|
724
|
+
s1 = re.sub("([A-Z]+)([A-Z][a-z])", r"\1_\2", key)
|
|
725
|
+
s2 = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1)
|
|
713
726
|
return s2.lower()
|
|
714
727
|
|
|
715
728
|
@classmethod
|
|
@@ -747,7 +760,7 @@ class AgentEngineClient:
|
|
|
747
760
|
image = raw
|
|
748
761
|
for prefix in ("http://", "https://"):
|
|
749
762
|
if image.startswith(prefix):
|
|
750
|
-
image = image[len(prefix):]
|
|
763
|
+
image = image[len(prefix) :]
|
|
751
764
|
break
|
|
752
765
|
|
|
753
766
|
image_no_tag = image
|
|
@@ -798,9 +811,8 @@ class AgentEngineClient:
|
|
|
798
811
|
img_ns, img_repo, img_ver = cls._parse_container_image_ref(artifact)
|
|
799
812
|
|
|
800
813
|
inferred_enterprise_instance = cls._enterprise_instance_from_image_ref(artifact)
|
|
801
|
-
image_type = (
|
|
802
|
-
|
|
803
|
-
or ("Enterprise" if inferred_enterprise_instance else "Personal")
|
|
814
|
+
image_type = container.get("image_type") or (
|
|
815
|
+
"Enterprise" if inferred_enterprise_instance else "Personal"
|
|
804
816
|
)
|
|
805
817
|
params: Dict[str, Any] = {
|
|
806
818
|
"ImageType": image_type,
|
|
@@ -860,14 +872,13 @@ class AgentEngineClient:
|
|
|
860
872
|
if not isinstance(detail, dict):
|
|
861
873
|
return {}
|
|
862
874
|
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
)
|
|
875
|
+
basic_value = detail.get("basic")
|
|
876
|
+
quick_value = detail.get("quick_access")
|
|
877
|
+
deployment_value = detail.get("deployment")
|
|
878
|
+
basic: Dict[str, Any] = basic_value if isinstance(basic_value, dict) else {}
|
|
879
|
+
quick: Dict[str, Any] = quick_value if isinstance(quick_value, dict) else {}
|
|
880
|
+
deployment: Dict[str, Any] = deployment_value if isinstance(deployment_value, dict) else {}
|
|
881
|
+
framework = deployment.get("framework") or basic.get("framework") or detail.get("framework")
|
|
871
882
|
return {
|
|
872
883
|
"agent_id": basic.get("agent_id") or detail.get("agent_id"),
|
|
873
884
|
"name": basic.get("name") or detail.get("name"),
|
|
@@ -896,18 +907,13 @@ class AgentEngineClient:
|
|
|
896
907
|
payload = None
|
|
897
908
|
if isinstance(payload, dict):
|
|
898
909
|
message = (
|
|
899
|
-
str(payload.get("detail") or payload.get("Message") or message).strip()
|
|
900
|
-
or message
|
|
910
|
+
str(payload.get("detail") or payload.get("Message") or message).strip() or message
|
|
901
911
|
)
|
|
902
912
|
return AgentEngineAPIError(response.status_code, message)
|
|
903
913
|
|
|
904
914
|
@staticmethod
|
|
905
915
|
def _compact_params(params: Dict[str, Any] | None) -> Dict[str, Any]:
|
|
906
|
-
return {
|
|
907
|
-
key: value
|
|
908
|
-
for key, value in (params or {}).items()
|
|
909
|
-
if value is not None
|
|
910
|
-
}
|
|
916
|
+
return {key: value for key, value in (params or {}).items() if value is not None}
|
|
911
917
|
|
|
912
918
|
@staticmethod
|
|
913
919
|
def _workspace_prefers_action_proxy(detail: Dict[str, Any] | None) -> bool:
|
|
@@ -938,13 +944,15 @@ class AgentEngineClient:
|
|
|
938
944
|
},
|
|
939
945
|
}
|
|
940
946
|
|
|
941
|
-
detail = await self.get_agent(
|
|
947
|
+
detail = await self.get_agent(
|
|
948
|
+
agent_id=agent_id,
|
|
949
|
+
name=name,
|
|
950
|
+
include_api_key=True,
|
|
951
|
+
)
|
|
942
952
|
access = self._extract_runtime_access(detail)
|
|
943
953
|
resolved_agent_id = str(access.get("agent_id") or agent_id or "").strip() or None
|
|
944
954
|
resolved_name = str(access.get("name") or name or "").strip() or None
|
|
945
|
-
resolved_api_key = api_key_value or (
|
|
946
|
-
str(access.get("api_key") or "").strip() or None
|
|
947
|
-
)
|
|
955
|
+
resolved_api_key = api_key_value or (str(access.get("api_key") or "").strip() or None)
|
|
948
956
|
if self._workspace_prefers_action_proxy(detail):
|
|
949
957
|
return {
|
|
950
958
|
"mode": "action",
|
|
@@ -1039,8 +1047,13 @@ class AgentEngineClient:
|
|
|
1039
1047
|
api_key=api_key,
|
|
1040
1048
|
)
|
|
1041
1049
|
if transport["mode"] != "runtime":
|
|
1042
|
-
raise AgentEngineAPIError(
|
|
1043
|
-
|
|
1050
|
+
raise AgentEngineAPIError(
|
|
1051
|
+
400, "Workspace runtime direct access is unavailable for this agent"
|
|
1052
|
+
)
|
|
1053
|
+
access = transport.get("access")
|
|
1054
|
+
if not isinstance(access, dict):
|
|
1055
|
+
raise AgentEngineAPIError(502, "Workspace runtime access payload is invalid")
|
|
1056
|
+
return access
|
|
1044
1057
|
|
|
1045
1058
|
def _workspace_runtime_request(
|
|
1046
1059
|
self,
|
|
@@ -1075,8 +1088,7 @@ class AgentEngineClient:
|
|
|
1075
1088
|
payload = response.json()
|
|
1076
1089
|
except Exception as exc:
|
|
1077
1090
|
url = str(
|
|
1078
|
-
getattr(response, "_ksadk_workspace_url", "")
|
|
1079
|
-
or getattr(response, "url", "")
|
|
1091
|
+
getattr(response, "_ksadk_workspace_url", "") or getattr(response, "url", "")
|
|
1080
1092
|
).strip()
|
|
1081
1093
|
body = (response.text or "").strip()
|
|
1082
1094
|
body_preview = body[:200] if body else "<empty response body>"
|
|
@@ -1093,10 +1105,15 @@ class AgentEngineClient:
|
|
|
1093
1105
|
"workspace_runtime_body_preview": body_preview,
|
|
1094
1106
|
},
|
|
1095
1107
|
) from exc
|
|
1096
|
-
|
|
1108
|
+
normalized = self._to_snake_case(payload)
|
|
1109
|
+
if not isinstance(normalized, dict):
|
|
1110
|
+
raise AgentEngineAPIError(502, "workspace runtime returned a non-object JSON payload")
|
|
1111
|
+
return normalized
|
|
1097
1112
|
|
|
1098
1113
|
@staticmethod
|
|
1099
|
-
def _annotate_workspace_payload(
|
|
1114
|
+
def _annotate_workspace_payload(
|
|
1115
|
+
payload: Dict[str, Any], *, transport_mode: str
|
|
1116
|
+
) -> Dict[str, Any]:
|
|
1100
1117
|
annotated = dict(payload or {})
|
|
1101
1118
|
annotated["transport_mode"] = transport_mode
|
|
1102
1119
|
return annotated
|
|
@@ -1117,7 +1134,7 @@ class AgentEngineClient:
|
|
|
1117
1134
|
def _action(
|
|
1118
1135
|
self,
|
|
1119
1136
|
action: str,
|
|
1120
|
-
params: Dict[str, Any] = None,
|
|
1137
|
+
params: Optional[Dict[str, Any]] = None,
|
|
1121
1138
|
*,
|
|
1122
1139
|
ignore_dry_run: bool = False,
|
|
1123
1140
|
) -> Dict[str, Any]:
|
|
@@ -1126,24 +1143,31 @@ class AgentEngineClient:
|
|
|
1126
1143
|
self._maybe_precheck_permission(action, body)
|
|
1127
1144
|
request_kwargs = {"ignore_dry_run": True} if ignore_dry_run else {}
|
|
1128
1145
|
result = self._request("POST", f"/agentengine/api/v1/{action}", body, **request_kwargs)
|
|
1129
|
-
|
|
1146
|
+
|
|
1130
1147
|
# 检查错误 (统一返回格式 {"Code": 0, ...})
|
|
1131
1148
|
code = result.get("Code", 0)
|
|
1132
1149
|
if code != 0:
|
|
1133
1150
|
msg = result.get("Message", "Unknown API error")
|
|
1134
|
-
|
|
1135
|
-
|
|
1151
|
+
details = {}
|
|
1152
|
+
if result.get("RequestId"):
|
|
1153
|
+
details["request_id"] = str(result["RequestId"])
|
|
1154
|
+
if result.get("Action"):
|
|
1155
|
+
details["action"] = str(result["Action"])
|
|
1156
|
+
raise AgentEngineAPIError(code=code, message=msg, details=details)
|
|
1157
|
+
|
|
1136
1158
|
if result.get("Error"):
|
|
1137
1159
|
raise Exception(result["Error"].get("Message", "Unknown error"))
|
|
1138
|
-
|
|
1160
|
+
|
|
1139
1161
|
# 提取 Data 并统一转换为 snake_case
|
|
1140
1162
|
data = result.get("Data") if result.get("Data") is not None else result
|
|
1141
1163
|
data = self._to_snake_case(data)
|
|
1142
|
-
|
|
1164
|
+
|
|
1143
1165
|
# 预发环境 endpoint 协议归一化: https -> http
|
|
1144
1166
|
if self.logical_region and self.logical_region.strip().lower() == "pre-online":
|
|
1145
1167
|
data = self._fix_endpoints_protocol(data)
|
|
1146
|
-
|
|
1168
|
+
|
|
1169
|
+
if not isinstance(data, dict):
|
|
1170
|
+
raise AgentEngineAPIError(502, "Action API returned a non-object payload")
|
|
1147
1171
|
return data
|
|
1148
1172
|
|
|
1149
1173
|
def download_attachment_content(self, file_uri: str) -> AttachmentContent:
|
|
@@ -1182,7 +1206,12 @@ class AgentEngineClient:
|
|
|
1182
1206
|
|
|
1183
1207
|
payload: Dict[str, Any] = {
|
|
1184
1208
|
"EnablePublicAccess": bool(
|
|
1185
|
-
_pick(
|
|
1209
|
+
_pick(
|
|
1210
|
+
"enable_public_access",
|
|
1211
|
+
"enablePublicAccess",
|
|
1212
|
+
"EnablePublicAccess",
|
|
1213
|
+
default=False,
|
|
1214
|
+
)
|
|
1186
1215
|
),
|
|
1187
1216
|
"EnableVpcAccess": bool(
|
|
1188
1217
|
_pick("enable_vpc_access", "enableVpcAccess", "EnableVpcAccess", default=False)
|
|
@@ -1203,7 +1232,9 @@ class AgentEngineClient:
|
|
|
1203
1232
|
return payload
|
|
1204
1233
|
|
|
1205
1234
|
@staticmethod
|
|
1206
|
-
def _normalize_ui_config_payload(
|
|
1235
|
+
def _normalize_ui_config_payload(
|
|
1236
|
+
ui_config: Optional[Dict[str, Any]],
|
|
1237
|
+
) -> Optional[Dict[str, Any]]:
|
|
1207
1238
|
if not isinstance(ui_config, dict):
|
|
1208
1239
|
return None
|
|
1209
1240
|
|
|
@@ -1234,10 +1265,7 @@ class AgentEngineClient:
|
|
|
1234
1265
|
return None
|
|
1235
1266
|
|
|
1236
1267
|
mount_path = str(
|
|
1237
|
-
storage.get("mount_path")
|
|
1238
|
-
or storage.get("mountPath")
|
|
1239
|
-
or storage.get("MountPath")
|
|
1240
|
-
or ""
|
|
1268
|
+
storage.get("mount_path") or storage.get("mountPath") or storage.get("MountPath") or ""
|
|
1241
1269
|
).strip()
|
|
1242
1270
|
size_gi = storage.get("size_gi", storage.get("sizeGi", storage.get("SizeGi")))
|
|
1243
1271
|
if not mount_path and size_gi is None:
|
|
@@ -1251,14 +1279,14 @@ class AgentEngineClient:
|
|
|
1251
1279
|
return payload
|
|
1252
1280
|
|
|
1253
1281
|
@staticmethod
|
|
1254
|
-
def _normalize_memory_config_payload(
|
|
1282
|
+
def _normalize_memory_config_payload(
|
|
1283
|
+
memory_config: Optional[Dict[str, Any]],
|
|
1284
|
+
) -> Optional[Dict[str, Any]]:
|
|
1255
1285
|
if not isinstance(memory_config, dict):
|
|
1256
1286
|
return None
|
|
1257
1287
|
|
|
1258
1288
|
memory_system = str(
|
|
1259
|
-
memory_config.get("memory_system")
|
|
1260
|
-
or memory_config.get("MemorySystem")
|
|
1261
|
-
or ""
|
|
1289
|
+
memory_config.get("memory_system") or memory_config.get("MemorySystem") or ""
|
|
1262
1290
|
).strip()
|
|
1263
1291
|
if not memory_system:
|
|
1264
1292
|
return None
|
|
@@ -1268,17 +1296,12 @@ class AgentEngineClient:
|
|
|
1268
1296
|
}
|
|
1269
1297
|
field_mapping = {
|
|
1270
1298
|
"Mem0InstanceId": (
|
|
1271
|
-
memory_config.get("mem0_instance_id")
|
|
1272
|
-
or memory_config.get("Mem0InstanceId")
|
|
1299
|
+
memory_config.get("mem0_instance_id") or memory_config.get("Mem0InstanceId")
|
|
1273
1300
|
),
|
|
1274
1301
|
"Mem0InstanceName": (
|
|
1275
|
-
memory_config.get("mem0_instance_name")
|
|
1276
|
-
or memory_config.get("Mem0InstanceName")
|
|
1277
|
-
),
|
|
1278
|
-
"Mem0Region": (
|
|
1279
|
-
memory_config.get("mem0_region")
|
|
1280
|
-
or memory_config.get("Mem0Region")
|
|
1302
|
+
memory_config.get("mem0_instance_name") or memory_config.get("Mem0InstanceName")
|
|
1281
1303
|
),
|
|
1304
|
+
"Mem0Region": (memory_config.get("mem0_region") or memory_config.get("Mem0Region")),
|
|
1282
1305
|
}
|
|
1283
1306
|
for key, value in field_mapping.items():
|
|
1284
1307
|
text = str(value or "").strip()
|
|
@@ -1297,7 +1320,9 @@ class AgentEngineClient:
|
|
|
1297
1320
|
"Region": self._normalize_payload_region(data.get("region", "cn-beijing-6")),
|
|
1298
1321
|
"Resource": {
|
|
1299
1322
|
"Cpu": int(float(data.get("resources", {}).get("cpu", 2))),
|
|
1300
|
-
"Memory": int(
|
|
1323
|
+
"Memory": int(
|
|
1324
|
+
str(data.get("resources", {}).get("memory", "4Gi")).replace("Gi", "")
|
|
1325
|
+
),
|
|
1301
1326
|
},
|
|
1302
1327
|
"Scaling": {
|
|
1303
1328
|
"MinReplicas": int(data.get("scaling", {}).get("min_replicas", 1)),
|
|
@@ -1331,7 +1356,7 @@ class AgentEngineClient:
|
|
|
1331
1356
|
"IamRole": data.get("iam_role", "KsyunAgentEngineDefaultRole"),
|
|
1332
1357
|
}
|
|
1333
1358
|
|
|
1334
|
-
if params["DeploymentType"]
|
|
1359
|
+
if params["DeploymentType"] in {"Code", "ManagedRuntime"}:
|
|
1335
1360
|
ks3 = data.get("ks3", {})
|
|
1336
1361
|
params["CodeConfig"] = {
|
|
1337
1362
|
"Path": data.get("artifact_path", ""),
|
|
@@ -1340,6 +1365,13 @@ class AgentEngineClient:
|
|
|
1340
1365
|
"Region": self._normalize_payload_region(ks3.get("region", "cn-beijing-6")),
|
|
1341
1366
|
"Bucket": ks3.get("bucket"),
|
|
1342
1367
|
}
|
|
1368
|
+
if params["DeploymentType"] == "ManagedRuntime":
|
|
1369
|
+
runtime_config = data.get("runtime_config") or {}
|
|
1370
|
+
params["RuntimeConfig"] = {
|
|
1371
|
+
"Name": runtime_config.get("name"),
|
|
1372
|
+
"Version": runtime_config.get("version"),
|
|
1373
|
+
"ManifestSha256": runtime_config.get("manifest_sha256"),
|
|
1374
|
+
}
|
|
1343
1375
|
else:
|
|
1344
1376
|
ic = data.get("image_credential", {}) or {}
|
|
1345
1377
|
artifact = (data.get("artifact_path", "") or "").strip()
|
|
@@ -1371,7 +1403,12 @@ class AgentEngineClient:
|
|
|
1371
1403
|
|
|
1372
1404
|
return self._action("CreateAgentProduct", params)
|
|
1373
1405
|
|
|
1374
|
-
async def get_agent(
|
|
1406
|
+
async def get_agent(
|
|
1407
|
+
self,
|
|
1408
|
+
agent_id: Optional[str] = None,
|
|
1409
|
+
name: Optional[str] = None,
|
|
1410
|
+
include_api_key: bool = False,
|
|
1411
|
+
) -> Dict[str, Any]:
|
|
1375
1412
|
"""获取 Agent 详情(支持 AgentId 或 Name 查询)"""
|
|
1376
1413
|
if agent_id:
|
|
1377
1414
|
params: Dict[str, Any] = {"AgentId": agent_id}
|
|
@@ -1382,7 +1419,7 @@ class AgentEngineClient:
|
|
|
1382
1419
|
except Exception as e:
|
|
1383
1420
|
# 兼容旧控制面:极少数版本仍使用 Id 字段
|
|
1384
1421
|
if self._should_fallback_get_agent_with_legacy_id(e):
|
|
1385
|
-
fallback = {"Id": agent_id}
|
|
1422
|
+
fallback: Dict[str, Any] = {"Id": agent_id}
|
|
1386
1423
|
if include_api_key:
|
|
1387
1424
|
fallback["IncludeApiKey"] = True
|
|
1388
1425
|
return self._action("GetAgent", fallback)
|
|
@@ -1512,7 +1549,7 @@ class AgentEngineClient:
|
|
|
1512
1549
|
async def delete_dashboard_access_link(self, *, link_id: str) -> Dict[str, Any]:
|
|
1513
1550
|
"""删除 Dashboard 短链接。"""
|
|
1514
1551
|
return self._action("DeleteDashboardAccessLink", {"LinkId": link_id})
|
|
1515
|
-
|
|
1552
|
+
|
|
1516
1553
|
async def list_agents(
|
|
1517
1554
|
self,
|
|
1518
1555
|
region: Optional[str] = None,
|
|
@@ -1595,17 +1632,18 @@ class AgentEngineClient:
|
|
|
1595
1632
|
self._action("DeleteAgent", {"AgentId": agent_id})
|
|
1596
1633
|
return True
|
|
1597
1634
|
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
1635
|
async def update_agent(self, agent_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
1601
1636
|
"""更新 Agent (热更新)"""
|
|
1602
|
-
params = {"AgentId": agent_id}
|
|
1637
|
+
params: Dict[str, Any] = {"AgentId": agent_id}
|
|
1638
|
+
artifact_type = data.get("artifact_type")
|
|
1639
|
+
if artifact_type:
|
|
1640
|
+
params["DeploymentType"] = artifact_type
|
|
1603
1641
|
if data.get("description"):
|
|
1604
1642
|
params["Description"] = data["description"]
|
|
1605
|
-
|
|
1643
|
+
|
|
1606
1644
|
if data.get("artifact_path"):
|
|
1607
1645
|
artifact = (data.get("artifact_path", "") or "").strip()
|
|
1608
|
-
if (
|
|
1646
|
+
if (artifact_type or "").lower() == "container":
|
|
1609
1647
|
ic = data.get("image_credential", {}) or {}
|
|
1610
1648
|
params["ContainerConfig"] = self._build_container_config_payload(
|
|
1611
1649
|
artifact=artifact,
|
|
@@ -1620,20 +1658,27 @@ class AgentEngineClient:
|
|
|
1620
1658
|
"Region": self._normalize_payload_region(ks3.get("region", "cn-beijing-6")),
|
|
1621
1659
|
"Bucket": ks3.get("bucket"),
|
|
1622
1660
|
}
|
|
1623
|
-
|
|
1661
|
+
if artifact_type == "ManagedRuntime":
|
|
1662
|
+
runtime_config = data.get("runtime_config") or {}
|
|
1663
|
+
params["RuntimeConfig"] = {
|
|
1664
|
+
"Name": runtime_config.get("name"),
|
|
1665
|
+
"Version": runtime_config.get("version"),
|
|
1666
|
+
"ManifestSha256": runtime_config.get("manifest_sha256"),
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1624
1669
|
if data.get("resources"):
|
|
1625
1670
|
params["Resource"] = {
|
|
1626
1671
|
"Cpu": int(float(data["resources"].get("cpu", 2))),
|
|
1627
|
-
"Memory": int(str(data["resources"].get("memory", "4Gi")).replace("Gi", ""))
|
|
1672
|
+
"Memory": int(str(data["resources"].get("memory", "4Gi")).replace("Gi", "")),
|
|
1628
1673
|
}
|
|
1629
|
-
|
|
1674
|
+
|
|
1630
1675
|
if data.get("scaling"):
|
|
1631
1676
|
params["Scaling"] = {
|
|
1632
1677
|
"MinReplicas": int(data["scaling"].get("min_replicas", 1)),
|
|
1633
1678
|
"MaxReplicas": int(data["scaling"].get("max_replicas", 10)),
|
|
1634
1679
|
"Concurrency": int(data["scaling"].get("concurrency", 20)),
|
|
1635
1680
|
}
|
|
1636
|
-
|
|
1681
|
+
|
|
1637
1682
|
envs = data.get("env_vars") or data.get("environment_variables")
|
|
1638
1683
|
if envs:
|
|
1639
1684
|
env_vars = []
|
|
@@ -1683,27 +1728,27 @@ class AgentEngineClient:
|
|
|
1683
1728
|
advanced["ProjectId"] = project_id
|
|
1684
1729
|
if advanced:
|
|
1685
1730
|
params["Advanced"] = advanced
|
|
1686
|
-
|
|
1731
|
+
|
|
1687
1732
|
return self._action("UpdateAgent", params)
|
|
1688
1733
|
|
|
1689
1734
|
# ===== Session Actions =====
|
|
1690
|
-
|
|
1691
|
-
async def create_session(
|
|
1735
|
+
|
|
1736
|
+
async def create_session(
|
|
1737
|
+
self, agent_id: str, user_id: Optional[str] = None, expires_hours: int = 24
|
|
1738
|
+
) -> Dict[str, Any]:
|
|
1692
1739
|
"""创建会话"""
|
|
1693
|
-
return self._action(
|
|
1694
|
-
"AgentId": agent_id,
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
})
|
|
1698
|
-
|
|
1740
|
+
return self._action(
|
|
1741
|
+
"CreateSession", {"AgentId": agent_id, "UserId": user_id, "ExpiresHours": expires_hours}
|
|
1742
|
+
)
|
|
1743
|
+
|
|
1699
1744
|
async def get_session(self, session_id: str) -> Dict[str, Any]:
|
|
1700
1745
|
"""获取会话详情"""
|
|
1701
1746
|
return self._action("GetSession", {"Id": session_id})
|
|
1702
|
-
|
|
1747
|
+
|
|
1703
1748
|
async def list_sessions(self, agent_id: str, page: int = 1, size: int = 20) -> Dict[str, Any]:
|
|
1704
1749
|
"""列出会话"""
|
|
1705
1750
|
return self._action("ListSessions", {"AgentId": agent_id, "Page": page, "PageSize": size})
|
|
1706
|
-
|
|
1751
|
+
|
|
1707
1752
|
async def delete_session(self, session_id: str) -> bool:
|
|
1708
1753
|
"""删除会话"""
|
|
1709
1754
|
try:
|
|
@@ -1866,14 +1911,14 @@ class AgentEngineClient:
|
|
|
1866
1911
|
},
|
|
1867
1912
|
accept="application/octet-stream",
|
|
1868
1913
|
)
|
|
1869
|
-
return response.content
|
|
1914
|
+
return bytes(response.content)
|
|
1870
1915
|
access = transport["access"]
|
|
1871
1916
|
response = self._workspace_runtime_request(
|
|
1872
1917
|
access=access,
|
|
1873
1918
|
method="GET",
|
|
1874
1919
|
path=f"files/{self._encode_workspace_runtime_path(remote_path)}",
|
|
1875
1920
|
)
|
|
1876
|
-
return response.content
|
|
1921
|
+
return bytes(response.content)
|
|
1877
1922
|
|
|
1878
1923
|
async def delete_workspace_file(
|
|
1879
1924
|
self,
|
|
@@ -1944,13 +1989,17 @@ class AgentEngineClient:
|
|
|
1944
1989
|
return int(float(raw))
|
|
1945
1990
|
|
|
1946
1991
|
@staticmethod
|
|
1947
|
-
def _normalize_mcp_deployment_type(
|
|
1992
|
+
def _normalize_mcp_deployment_type(
|
|
1993
|
+
value: Optional[str], default: Optional[str] = None
|
|
1994
|
+
) -> Optional[str]:
|
|
1948
1995
|
raw = str(value or default or "").strip()
|
|
1949
1996
|
if not raw:
|
|
1950
1997
|
return None
|
|
1951
1998
|
return "Container" if raw.lower() == "container" else "Code"
|
|
1952
1999
|
|
|
1953
|
-
def _infer_mcp_deployment_type(
|
|
2000
|
+
def _infer_mcp_deployment_type(
|
|
2001
|
+
self, data: Dict[str, Any], default: Optional[str] = None
|
|
2002
|
+
) -> Optional[str]:
|
|
1954
2003
|
explicit = self._normalize_mcp_deployment_type(
|
|
1955
2004
|
data.get("deployment_type") or data.get("artifact_type"),
|
|
1956
2005
|
default=default,
|
|
@@ -2018,11 +2067,14 @@ class AgentEngineClient:
|
|
|
2018
2067
|
async def create_mcp(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
2019
2068
|
"""创建 MCP"""
|
|
2020
2069
|
if self._looks_like_nested_mcp_payload(data):
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2070
|
+
nested_params = dict(data)
|
|
2071
|
+
nested_params["Region"] = self._normalize_payload_region(
|
|
2072
|
+
nested_params.get("Region")
|
|
2073
|
+
or data.get("region")
|
|
2074
|
+
or self.logical_region
|
|
2075
|
+
or "cn-beijing-6"
|
|
2024
2076
|
)
|
|
2025
|
-
return self._action("CreateMCP",
|
|
2077
|
+
return self._action("CreateMCP", nested_params)
|
|
2026
2078
|
|
|
2027
2079
|
deployment_type = self._infer_mcp_deployment_type(data, default="Code") or "Code"
|
|
2028
2080
|
params: Dict[str, Any] = {
|
|
@@ -2043,11 +2095,11 @@ class AgentEngineClient:
|
|
|
2043
2095
|
if network_payload:
|
|
2044
2096
|
params["Network"] = network_payload
|
|
2045
2097
|
return self._action("CreateMCP", params)
|
|
2046
|
-
|
|
2098
|
+
|
|
2047
2099
|
async def get_mcp(self, mcp_id: str) -> Dict[str, Any]:
|
|
2048
2100
|
"""获取 MCP 详情"""
|
|
2049
2101
|
return self._action("GetMCP", {"Id": mcp_id})
|
|
2050
|
-
|
|
2102
|
+
|
|
2051
2103
|
async def list_mcps(
|
|
2052
2104
|
self,
|
|
2053
2105
|
region: Optional[str] = None,
|
|
@@ -2055,24 +2107,23 @@ class AgentEngineClient:
|
|
|
2055
2107
|
page_size: int = 20,
|
|
2056
2108
|
) -> Dict[str, Any]:
|
|
2057
2109
|
"""列出 MCP (注册中心)"""
|
|
2058
|
-
params = {"Page": int(page), "PageSize": int(page_size)}
|
|
2110
|
+
params: Dict[str, Any] = {"Page": int(page), "PageSize": int(page_size)}
|
|
2059
2111
|
if region:
|
|
2060
2112
|
params["Region"] = self._normalize_payload_region(region)
|
|
2061
2113
|
result = self._action("ListMCPs", params)
|
|
2062
|
-
# _action 已统一转 snake_case:
|
|
2063
|
-
# 实际上 MCPs -> mcps, Total -> total
|
|
2114
|
+
# _action 已统一转 snake_case: MCPs -> mcps, Total -> total
|
|
2064
2115
|
return {"mcps": result.get("mcps", []), "total": result.get("total", 0)}
|
|
2065
|
-
|
|
2116
|
+
|
|
2066
2117
|
async def update_mcp(self, mcp_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
2067
2118
|
"""更新 MCP (热更新)"""
|
|
2068
2119
|
if self._looks_like_nested_mcp_payload(data):
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
if "Region" in
|
|
2072
|
-
|
|
2073
|
-
|
|
2120
|
+
nested_params = dict(data)
|
|
2121
|
+
nested_params.setdefault("Id", mcp_id)
|
|
2122
|
+
if "Region" in nested_params or data.get("region") or self.logical_region:
|
|
2123
|
+
nested_params["Region"] = self._normalize_payload_region(
|
|
2124
|
+
nested_params.get("Region") or data.get("region") or self.logical_region
|
|
2074
2125
|
)
|
|
2075
|
-
return self._action("UpdateMCP",
|
|
2126
|
+
return self._action("UpdateMCP", nested_params)
|
|
2076
2127
|
|
|
2077
2128
|
params: Dict[str, Any] = {"Id": mcp_id}
|
|
2078
2129
|
deployment_type = self._infer_mcp_deployment_type(data)
|
|
@@ -2096,7 +2147,9 @@ class AgentEngineClient:
|
|
|
2096
2147
|
}
|
|
2097
2148
|
|
|
2098
2149
|
scaling = data.get("scaling", {}) or {}
|
|
2099
|
-
if any(
|
|
2150
|
+
if any(
|
|
2151
|
+
scaling.get(key) is not None for key in ("min_replicas", "max_replicas", "concurrency")
|
|
2152
|
+
):
|
|
2100
2153
|
params["Scaling"] = {
|
|
2101
2154
|
"MinReplicas": int(scaling.get("min_replicas", 1)),
|
|
2102
2155
|
"MaxReplicas": int(scaling.get("max_replicas", 5)),
|
|
@@ -2119,16 +2172,15 @@ class AgentEngineClient:
|
|
|
2119
2172
|
if data.get("region") is not None:
|
|
2120
2173
|
params["Region"] = self._normalize_payload_region(data.get("region"))
|
|
2121
2174
|
return self._action("UpdateMCP", params)
|
|
2122
|
-
|
|
2175
|
+
|
|
2123
2176
|
async def delete_mcp(self, mcp_id: str) -> bool:
|
|
2124
2177
|
"""删除 MCP"""
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
async def get_mcp_by_name(self, name: str, region: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|
2178
|
+
result = self._action("DeleteMCP", {"Id": mcp_id})
|
|
2179
|
+
return bool(result.get("deleted"))
|
|
2180
|
+
|
|
2181
|
+
async def get_mcp_by_name(
|
|
2182
|
+
self, name: str, region: Optional[str] = None
|
|
2183
|
+
) -> Optional[Dict[str, Any]]:
|
|
2132
2184
|
"""按名称查询 MCP"""
|
|
2133
2185
|
# 使用 ListMCPs 然后过滤 (Action API 暂不支持 by-name)
|
|
2134
2186
|
try:
|
|
@@ -2138,7 +2190,7 @@ class AgentEngineClient:
|
|
|
2138
2190
|
result = await self.list_mcps(region=region, page=page, page_size=page_size)
|
|
2139
2191
|
mcps = result.get("mcps", [])
|
|
2140
2192
|
for mcp in mcps:
|
|
2141
|
-
if mcp.get("name") == name:
|
|
2193
|
+
if isinstance(mcp, dict) and mcp.get("name") == name:
|
|
2142
2194
|
return mcp
|
|
2143
2195
|
if len(mcps) < page_size:
|
|
2144
2196
|
break
|
|
@@ -2148,39 +2200,38 @@ class AgentEngineClient:
|
|
|
2148
2200
|
return None
|
|
2149
2201
|
|
|
2150
2202
|
# ===== Upload Actions =====
|
|
2151
|
-
|
|
2203
|
+
|
|
2152
2204
|
async def get_presigned_url(self, filename: str) -> Dict[str, Any]:
|
|
2153
2205
|
"""获取 KS3 预签名上传 URL"""
|
|
2154
2206
|
return self._action("GetPresignedUrl", {"Filename": filename})
|
|
2155
2207
|
|
|
2156
2208
|
# ===== Chat Actions =====
|
|
2157
|
-
|
|
2158
|
-
async def chat(
|
|
2209
|
+
|
|
2210
|
+
async def chat(
|
|
2211
|
+
self, agent_id: str, message: str, session_id: Optional[str] = None
|
|
2212
|
+
) -> Dict[str, Any]:
|
|
2159
2213
|
"""调用 Agent"""
|
|
2160
2214
|
params = {
|
|
2161
2215
|
"AgentId": agent_id,
|
|
2162
2216
|
"Messages": [{"role": "user", "content": message}],
|
|
2163
|
-
"Stream": False
|
|
2217
|
+
"Stream": False,
|
|
2164
2218
|
}
|
|
2165
2219
|
if session_id:
|
|
2166
2220
|
params["SessionId"] = session_id
|
|
2167
2221
|
return self._action("RunAgent", params)
|
|
2168
2222
|
|
|
2169
2223
|
# ===== Version Actions =====
|
|
2170
|
-
|
|
2224
|
+
|
|
2171
2225
|
async def release_version(
|
|
2172
|
-
self,
|
|
2173
|
-
agent_id: str,
|
|
2174
|
-
tag: Optional[str] = None,
|
|
2175
|
-
description: Optional[str] = None
|
|
2226
|
+
self, agent_id: str, tag: Optional[str] = None, description: Optional[str] = None
|
|
2176
2227
|
) -> Dict[str, Any]:
|
|
2177
2228
|
"""发布新版本
|
|
2178
|
-
|
|
2229
|
+
|
|
2179
2230
|
Args:
|
|
2180
2231
|
agent_id: Agent ID
|
|
2181
2232
|
tag: 版本标签,不填则自动生成
|
|
2182
2233
|
description: 版本描述
|
|
2183
|
-
|
|
2234
|
+
|
|
2184
2235
|
Returns:
|
|
2185
2236
|
版本信息
|
|
2186
2237
|
"""
|
|
@@ -2190,46 +2241,37 @@ class AgentEngineClient:
|
|
|
2190
2241
|
if description:
|
|
2191
2242
|
params["Description"] = description
|
|
2192
2243
|
return self._action("CreateVersion", params)
|
|
2193
|
-
|
|
2194
|
-
async def list_versions(
|
|
2195
|
-
self,
|
|
2196
|
-
agent_id: str,
|
|
2197
|
-
page: int = 1,
|
|
2198
|
-
size: int = 10
|
|
2199
|
-
) -> Dict[str, Any]:
|
|
2244
|
+
|
|
2245
|
+
async def list_versions(self, agent_id: str, page: int = 1, size: int = 10) -> Dict[str, Any]:
|
|
2200
2246
|
"""列出版本历史
|
|
2201
|
-
|
|
2247
|
+
|
|
2202
2248
|
Args:
|
|
2203
2249
|
agent_id: Agent ID
|
|
2204
2250
|
page: 页码
|
|
2205
2251
|
size: 每页数量
|
|
2206
|
-
|
|
2252
|
+
|
|
2207
2253
|
Returns:
|
|
2208
2254
|
版本列表和分页信息
|
|
2209
2255
|
"""
|
|
2210
|
-
return self._action("ListVersions", {
|
|
2211
|
-
|
|
2212
|
-
"Page": page,
|
|
2213
|
-
"PageSize": size
|
|
2214
|
-
})
|
|
2215
|
-
|
|
2256
|
+
return self._action("ListVersions", {"AgentId": agent_id, "Page": page, "PageSize": size})
|
|
2257
|
+
|
|
2216
2258
|
async def rollback_version(
|
|
2217
|
-
self,
|
|
2218
|
-
agent_id: str,
|
|
2259
|
+
self,
|
|
2260
|
+
agent_id: str,
|
|
2219
2261
|
target_version_id: Optional[str] = None,
|
|
2220
2262
|
target_tag: Optional[str] = None,
|
|
2221
2263
|
ks3_access_key: Optional[str] = None,
|
|
2222
2264
|
ks3_secret_key: Optional[str] = None,
|
|
2223
2265
|
) -> Dict[str, Any]:
|
|
2224
2266
|
"""回滚到指定版本
|
|
2225
|
-
|
|
2267
|
+
|
|
2226
2268
|
Args:
|
|
2227
2269
|
agent_id: Agent ID
|
|
2228
2270
|
target_version_id: 目标版本 ID(与 target_tag 二选一)
|
|
2229
2271
|
target_tag: 目标版本标签(与 target_version_id 二选一)
|
|
2230
2272
|
ks3_access_key: KS3 Access Key (可选)
|
|
2231
2273
|
ks3_secret_key: KS3 Secret Key (可选)
|
|
2232
|
-
|
|
2274
|
+
|
|
2233
2275
|
Returns:
|
|
2234
2276
|
回滚结果
|
|
2235
2277
|
"""
|
|
@@ -2242,5 +2284,5 @@ class AgentEngineClient:
|
|
|
2242
2284
|
params["KS3AccessKey"] = ks3_access_key
|
|
2243
2285
|
if ks3_secret_key:
|
|
2244
2286
|
params["KS3SecretKey"] = ks3_secret_key
|
|
2245
|
-
|
|
2287
|
+
|
|
2246
2288
|
return self._action("RollbackVersion", params)
|