agentengine-sdk-python 0.6.9__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.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +41 -23
- 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 +252 -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 +533 -726
- 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 +173 -90
- ksadk/cli/cmd_invoke.py +388 -159
- ksadk/cli/cmd_launch.py +64 -28
- ksadk/cli/cmd_mcp.py +103 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +488 -228
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +44 -14
- 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 +38 -16
- 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 +501 -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 +656 -0
- ksadk/conversations/model_context.py +22 -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 -5187
- 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 +52 -39
- ksadk/deployment/manager.py +63 -65
- ksadk/deployment/providers/serverless.py +326 -209
- 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 +267 -0
- ksadk/memory/adk/short_term_memory.py +33 -27
- 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 +1248 -164
- 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 -530
- ksadk/runners/langgraph_runner.py +490 -95
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +264 -38
- 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 -3743
- 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-C0meuOdi.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-bj2rZnP5.js → arc-CFKwSk_B.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-2u1ltDIj.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-D6fvdK20.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-BK82L5n5.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
- ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-DLVdkeyQ.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-BbwsYcbW.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-DOairxzw.js → chunk-55IACEB6-BK8paA20.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-hCO487gs.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-XU8vDOuG.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-PrapyfMu.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-CboKhTZ3.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-_N8bJ-EU.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-FoDlo5J2.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BBp6ebBw.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-CqOvG1PR.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-O9T3t6ba.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-CGG8ekBO.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-4BmH1EEg.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
- ksadk/server/static/assets/{dist-CiZHB6ZW.js → dist-6CVKuTAe.js} +1 -1
- ksadk/server/static/assets/{dist-BMKM66B4.js → dist-BUHRxvDG.js} +1 -1
- ksadk/server/static/assets/{dist-CZ6C3x8B.js → dist-BZ9n9AjO.js} +1 -1
- ksadk/server/static/assets/{dist-DbaH3p5h.js → dist-BibcG1V9.js} +1 -1
- ksadk/server/static/assets/{dist-BVzcWa6D.js → dist-Bs-jQcRX.js} +1 -1
- ksadk/server/static/assets/{dist-D99wf6_X.js → dist-C2xjE7cO.js} +1 -1
- ksadk/server/static/assets/{dist-DLMjL01k.js → dist-C7-3jInC.js} +1 -1
- ksadk/server/static/assets/{dist-DI-oVAXw.js → dist-C99THtIA.js} +1 -1
- ksadk/server/static/assets/{dist-BkJjNih3.js → dist-CGcp2ex8.js} +1 -1
- ksadk/server/static/assets/{dist-D5JGcxBx.js → dist-CVQRZjPu.js} +1 -1
- ksadk/server/static/assets/{dist-CWiTDN_V.js → dist-Cf23NY4L.js} +1 -1
- ksadk/server/static/assets/{dist-DLeM1OCK.js → dist-CgF3fj15.js} +1 -1
- ksadk/server/static/assets/{dist-BmuTWcm7.js → dist-Cwt7koer.js} +1 -1
- ksadk/server/static/assets/{dist-C2DKRFVK.js → dist-D82mtD2s.js} +1 -1
- ksadk/server/static/assets/{dist-B67uF2uK.js → dist-DF06ORQo.js} +1 -1
- ksadk/server/static/assets/{dist-Cwhk4lwI.js → dist-DHn6nBzr.js} +1 -1
- ksadk/server/static/assets/{dist-S4klkK5W.js → dist-Djgl2wVZ.js} +1 -1
- ksadk/server/static/assets/{dist-DCpZrjaK.js → dist-DlzCRy0S.js} +1 -1
- ksadk/server/static/assets/{dist-Cp1_jKwf.js → dist-DqNnNFrw.js} +1 -1
- ksadk/server/static/assets/{dist-6kSZvCZh.js → dist-DyvYLMW9.js} +1 -1
- ksadk/server/static/assets/{dist-DM0rEQPk.js → dist-eoW6tZXA.js} +1 -1
- ksadk/server/static/assets/{dist-Bk1l05Ni.js → dist-ivOya1LD.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-oJhaci7S.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-DtTmUan-.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BSsb_eij.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-BR5s6Pws.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-DYPc5cvh.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-MoBdALDg.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-DgLiQT8l.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-CsFx112F.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
- ksadk/server/static/assets/{katex-DRsiwpM2.js → katex-DATssjp1.js} +1 -1
- ksadk/server/static/assets/{linear-TNRQ5Orv.js → linear-CvMBw9cA.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-D2eMVOgo.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-BtByYFhL.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-DPnuCB8c.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-miFpCPv4.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-mjB_yYkW.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-D7hSlZZZ.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-D9Cx6hC3.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-D_zrg47o.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-CwSec0Wa.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-agCVobiF.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-TmrlhWNt.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-DV71V-ah.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 +86 -40
- ksadk/sessions/base.py +31 -11
- ksadk/sessions/continuity.py +28 -5
- ksadk/sessions/in_memory.py +46 -2
- ksadk/sessions/local_service.py +148 -17
- ksadk/sessions/postgres_service.py +216 -35
- ksadk/sessions/resilience.py +52 -0
- ksadk/sessions/resilient.py +388 -0
- 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 +136 -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 +264 -114
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/exporters/langfuse_exporter.py +91 -76
- ksadk/tracing/setup.py +132 -53
- ksadk/tracing/span_utils.py +5 -2
- ksadk/tui/__init__.py +22 -7
- ksadk/tui/loop.py +1925 -0
- ksadk/tui/stream_render.py +69 -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.6.9.dist-info/RECORD +0 -487
- ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +0 -9
- ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +0 -8
- ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +0 -1
- ksadk/server/static/assets/channel-BSSOwFIb.js +0 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +0 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +0 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +0 -1
- ksadk/server/static/assets/index-BH7-pC0B.js +0 -165
- ksadk/server/static/assets/index-DAURbCsP.css +0 -1
- ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +0 -1
- ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +0 -1
- ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +0 -1
- ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +0 -1
- ksadk/tui/app.py +0 -400
- ksadk/tui/clipboard.py +0 -100
- ksadk/tui/widgets/__init__.py +0 -22
- ksadk/tui/widgets/assistant.py +0 -89
- ksadk/tui/widgets/base.py +0 -54
- ksadk/tui/widgets/chat_input.py +0 -246
- ksadk/tui/widgets/history.py +0 -156
- ksadk/tui/widgets/system.py +0 -87
- ksadk/tui/widgets/thinking.py +0 -110
- ksadk/tui/widgets/tool_call.py +0 -161
- ksadk/tui/widgets/user.py +0 -37
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -3,13 +3,12 @@ Container Builder - Docker 镜像构建
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
import
|
|
6
|
+
import platform
|
|
7
7
|
import shutil
|
|
8
|
+
import subprocess
|
|
8
9
|
import time
|
|
9
|
-
import platform
|
|
10
|
-
import asyncio
|
|
11
10
|
from pathlib import Path
|
|
12
|
-
from typing import Optional
|
|
11
|
+
from typing import TYPE_CHECKING, Optional
|
|
13
12
|
|
|
14
13
|
import click
|
|
15
14
|
|
|
@@ -25,12 +24,15 @@ from ksadk.builders.requirements_utils import (
|
|
|
25
24
|
parse_requirements_text,
|
|
26
25
|
)
|
|
27
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from ksadk.deployment.base import PackageInfo
|
|
29
|
+
|
|
28
30
|
|
|
29
31
|
def _registry_host(registry: str | None) -> str:
|
|
30
32
|
value = str(registry or "").strip()
|
|
31
33
|
for prefix in ("http://", "https://"):
|
|
32
34
|
if value.startswith(prefix):
|
|
33
|
-
value = value[len(prefix):]
|
|
35
|
+
value = value[len(prefix) :]
|
|
34
36
|
break
|
|
35
37
|
return value.split("/", 1)[0].strip()
|
|
36
38
|
|
|
@@ -100,8 +102,8 @@ def print_registry_credentials_help(registry: str | None, *, kind: str | None =
|
|
|
100
102
|
|
|
101
103
|
def ensure_docker_running() -> bool:
|
|
102
104
|
"""确保 Docker 正在运行"""
|
|
103
|
-
if not shutil.which(
|
|
104
|
-
click.secho("❌ 未找到 docker 命令", fg=
|
|
105
|
+
if not shutil.which("docker"):
|
|
106
|
+
click.secho("❌ 未找到 docker 命令", fg="red")
|
|
105
107
|
click.echo("")
|
|
106
108
|
click.echo("请先安装 Docker:")
|
|
107
109
|
if platform.system() == "Darwin":
|
|
@@ -113,36 +115,36 @@ def ensure_docker_running() -> bool:
|
|
|
113
115
|
else:
|
|
114
116
|
click.echo(" • 下载 Docker Desktop: https://www.docker.com/products/docker-desktop/")
|
|
115
117
|
return False
|
|
116
|
-
|
|
118
|
+
|
|
117
119
|
try:
|
|
118
|
-
result = subprocess.run([
|
|
120
|
+
result = subprocess.run(["docker", "info"], capture_output=True, timeout=10)
|
|
119
121
|
if result.returncode == 0:
|
|
120
122
|
return True
|
|
121
|
-
except:
|
|
123
|
+
except (OSError, subprocess.SubprocessError):
|
|
122
124
|
pass
|
|
123
|
-
|
|
124
|
-
click.secho("⚠️ Docker daemon 未运行", fg=
|
|
125
|
-
|
|
125
|
+
|
|
126
|
+
click.secho("⚠️ Docker daemon 未运行", fg="yellow")
|
|
127
|
+
|
|
126
128
|
system_name = platform.system()
|
|
127
129
|
if system_name == "Darwin":
|
|
128
130
|
click.echo("🚀 正在启动 Docker Desktop...")
|
|
129
131
|
try:
|
|
130
|
-
subprocess.run([
|
|
132
|
+
subprocess.run(["open", "-a", "Docker"], check=True)
|
|
131
133
|
for i in range(60):
|
|
132
134
|
time.sleep(1)
|
|
133
135
|
try:
|
|
134
|
-
result = subprocess.run([
|
|
136
|
+
result = subprocess.run(["docker", "info"], capture_output=True, timeout=5)
|
|
135
137
|
if result.returncode == 0:
|
|
136
|
-
click.secho("✅ Docker Desktop 已启动", fg=
|
|
138
|
+
click.secho("✅ Docker Desktop 已启动", fg="green")
|
|
137
139
|
return True
|
|
138
|
-
except:
|
|
140
|
+
except (OSError, subprocess.SubprocessError):
|
|
139
141
|
pass
|
|
140
142
|
if i % 5 == 0 and i > 0:
|
|
141
143
|
click.echo(f" 等待 Docker 启动中... ({i}秒)")
|
|
142
|
-
click.secho("❌ Docker Desktop 启动超时", fg=
|
|
144
|
+
click.secho("❌ Docker Desktop 启动超时", fg="red")
|
|
143
145
|
return False
|
|
144
|
-
except:
|
|
145
|
-
click.secho("❌ 无法启动 Docker Desktop", fg=
|
|
146
|
+
except (OSError, subprocess.SubprocessError):
|
|
147
|
+
click.secho("❌ 无法启动 Docker Desktop", fg="red")
|
|
146
148
|
return False
|
|
147
149
|
elif system_name == "Windows":
|
|
148
150
|
click.echo("请启动 Docker Desktop,然后重试当前命令。")
|
|
@@ -154,81 +156,95 @@ def ensure_docker_running() -> bool:
|
|
|
154
156
|
|
|
155
157
|
class ContainerBuilder(BaseBuilder):
|
|
156
158
|
"""Docker 镜像构建器"""
|
|
157
|
-
|
|
158
|
-
def __init__(
|
|
159
|
-
|
|
159
|
+
|
|
160
|
+
def __init__(
|
|
161
|
+
self,
|
|
162
|
+
project_dir: Path,
|
|
163
|
+
config: Optional[dict] = None,
|
|
164
|
+
tag: Optional[str] = None,
|
|
165
|
+
registry: Optional[str] = None,
|
|
166
|
+
no_cache: bool = False,
|
|
167
|
+
):
|
|
160
168
|
super().__init__(project_dir, config)
|
|
161
169
|
self.tag = tag
|
|
162
170
|
self.registry = registry
|
|
163
171
|
self.no_cache = no_cache
|
|
164
|
-
|
|
172
|
+
|
|
165
173
|
def _get_smart_kcr_endpoint(self, region: str) -> str:
|
|
166
174
|
"""智能选择 KCR endpoint
|
|
167
|
-
|
|
175
|
+
|
|
168
176
|
使用企业版 KCR (hub.kce.ksyun.com/agentengine/)。
|
|
169
177
|
优先使用内网 VPC endpoint,如果内网不可达则使用公网。
|
|
170
178
|
"""
|
|
171
179
|
from ksadk.configs.settings import check_endpoint_reachable
|
|
172
|
-
|
|
180
|
+
|
|
173
181
|
# 企业版 KCR 地址 (带 agentengine 命名空间)
|
|
174
182
|
vpc_endpoint = "hub-vpc.kce.ksyun.com/agentengine"
|
|
175
183
|
public_endpoint = "hub.kce.ksyun.com/agentengine"
|
|
176
|
-
|
|
177
|
-
click.echo(
|
|
178
|
-
|
|
184
|
+
|
|
185
|
+
click.echo("🔍 检测 KCR 内网连通性...")
|
|
186
|
+
|
|
179
187
|
# 检测 VPC 内网是否可达 (端口 443 for HTTPS registry)
|
|
180
188
|
if check_endpoint_reachable("hub-vpc.kce.ksyun.com", port=443, timeout=2.0):
|
|
181
|
-
click.secho(f" ✅ 使用内网: {vpc_endpoint}", fg=
|
|
189
|
+
click.secho(f" ✅ 使用内网: {vpc_endpoint}", fg="green")
|
|
182
190
|
return vpc_endpoint
|
|
183
191
|
else:
|
|
184
192
|
click.echo(f" ℹ️ 使用公网: {public_endpoint}")
|
|
185
193
|
return public_endpoint
|
|
186
|
-
|
|
194
|
+
|
|
187
195
|
def _optimize_kcr_endpoint(self, registry: str) -> str:
|
|
188
196
|
"""优化 KCR endpoint
|
|
189
|
-
|
|
197
|
+
|
|
190
198
|
如果是金山云 KCR 公网地址,且内网可达,则替换为内网地址。
|
|
191
199
|
"""
|
|
192
200
|
from ksadk.configs.settings import check_endpoint_reachable
|
|
193
|
-
|
|
201
|
+
|
|
202
|
+
registry_text = str(registry).strip()
|
|
203
|
+
scheme, separator, reference = registry_text.partition("://")
|
|
204
|
+
prefix = f"{scheme}://" if separator else ""
|
|
205
|
+
target = reference if separator else registry_text
|
|
206
|
+
host, slash, remainder = target.partition("/")
|
|
207
|
+
normalized_host = host.lower()
|
|
208
|
+
|
|
194
209
|
# 已经是内网地址
|
|
195
|
-
if
|
|
210
|
+
if normalized_host == "hub-vpc.kce.ksyun.com":
|
|
196
211
|
return registry
|
|
197
|
-
|
|
198
|
-
#
|
|
199
|
-
if
|
|
200
|
-
click.echo(
|
|
212
|
+
|
|
213
|
+
# 仅匹配完整 registry host,避免改写路径或攻击者域名中的同名子串。
|
|
214
|
+
if normalized_host == "hub.kce.ksyun.com":
|
|
215
|
+
click.echo("🔍 检测 KCR 内网连通性...")
|
|
201
216
|
if check_endpoint_reachable("hub-vpc.kce.ksyun.com", port=443, timeout=2.0):
|
|
202
|
-
optimized =
|
|
203
|
-
click.secho(f" ✅ 优化为内网: {optimized}", fg=
|
|
217
|
+
optimized = f"{prefix}hub-vpc.kce.ksyun.com{slash}{remainder}"
|
|
218
|
+
click.secho(f" ✅ 优化为内网: {optimized}", fg="green")
|
|
204
219
|
return optimized
|
|
205
220
|
else:
|
|
206
221
|
click.echo(f" ℹ️ 使用公网: {registry}")
|
|
207
|
-
|
|
222
|
+
|
|
208
223
|
return registry
|
|
209
|
-
|
|
210
|
-
def _package(self, detection_result) ->
|
|
224
|
+
|
|
225
|
+
def _package(self, detection_result) -> "PackageInfo":
|
|
211
226
|
"""打包项目 - 复制文件并生成 Dockerfile/requirements/entrypoint"""
|
|
212
227
|
from ksadk.deployment.base import PackageInfo
|
|
213
|
-
|
|
228
|
+
|
|
214
229
|
project_path = self.project_dir
|
|
215
230
|
output_dir = project_path / ".agentengine" / "build"
|
|
216
231
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
217
|
-
|
|
232
|
+
|
|
218
233
|
package_name = Path(detection_result.package_path).name
|
|
219
234
|
is_container_first_template = (
|
|
220
235
|
getattr(getattr(detection_result, "type", None), "value", "") == "hermes"
|
|
221
236
|
and (project_path / "Dockerfile").exists()
|
|
222
237
|
and (project_path / "entrypoint.sh").exists()
|
|
223
238
|
)
|
|
224
|
-
|
|
239
|
+
|
|
225
240
|
# 复制项目文件。真实 .env 只通过 deploy payload 注入,不进入镜像上下文。
|
|
226
241
|
for item in project_path.iterdir():
|
|
227
242
|
if CodeBuilder._is_real_dotenv_file(item.name):
|
|
228
243
|
continue
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
244
|
+
if (item.name.startswith(".") and item.name != ".env.example") or item.name in (
|
|
245
|
+
"__pycache__",
|
|
246
|
+
".git",
|
|
247
|
+
"node_modules",
|
|
232
248
|
):
|
|
233
249
|
continue
|
|
234
250
|
dest = output_dir / item.name
|
|
@@ -249,9 +265,10 @@ class ContainerBuilder(BaseBuilder):
|
|
|
249
265
|
)
|
|
250
266
|
else:
|
|
251
267
|
shutil.copy2(item, dest)
|
|
252
|
-
|
|
268
|
+
|
|
253
269
|
# 复制 ksadk 源码 (确保容器内可用)
|
|
254
270
|
import ksadk
|
|
271
|
+
|
|
255
272
|
ksadk_src = Path(ksadk.__file__).parent
|
|
256
273
|
ksadk_dest = output_dir / "ksadk"
|
|
257
274
|
if ksadk_dest.exists():
|
|
@@ -274,14 +291,15 @@ class ContainerBuilder(BaseBuilder):
|
|
|
274
291
|
return ignored
|
|
275
292
|
|
|
276
293
|
shutil.copytree(
|
|
277
|
-
ksadk_src,
|
|
278
|
-
ksadk_dest,
|
|
294
|
+
ksadk_src,
|
|
295
|
+
ksadk_dest,
|
|
279
296
|
ignore=_ignore_ksadk_source,
|
|
280
297
|
)
|
|
281
298
|
|
|
282
299
|
# 复制 ksadk_runtime_common (如果存在)
|
|
283
300
|
try:
|
|
284
301
|
import ksadk_runtime_common
|
|
302
|
+
|
|
285
303
|
runtime_common_src = Path(ksadk_runtime_common.__file__).parent
|
|
286
304
|
runtime_common_dest = output_dir / "ksadk_runtime_common"
|
|
287
305
|
if runtime_common_dest.exists():
|
|
@@ -305,21 +323,22 @@ class ContainerBuilder(BaseBuilder):
|
|
|
305
323
|
ignore=shutil.ignore_patterns("__pycache__", "*.pyc"),
|
|
306
324
|
)
|
|
307
325
|
else:
|
|
308
|
-
click.echo(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
326
|
+
click.echo(
|
|
327
|
+
click.style(
|
|
328
|
+
"⚠️ 警告: 未找到 ksadk_runtime_common,镜像可能无法正常运行", fg="yellow"
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
|
|
313
332
|
dockerfile_path = output_dir / "Dockerfile"
|
|
314
333
|
if not is_container_first_template:
|
|
315
334
|
dockerfile = self._generate_dockerfile(detection_result)
|
|
316
335
|
dockerfile_path.write_text(dockerfile)
|
|
317
|
-
|
|
336
|
+
|
|
318
337
|
# 生成 requirements.txt (合并用户依赖)
|
|
319
338
|
requirements = self._generate_requirements(detection_result, project_path)
|
|
320
339
|
requirements_path = output_dir / "requirements.txt"
|
|
321
340
|
requirements_path.write_text(requirements)
|
|
322
|
-
|
|
341
|
+
|
|
323
342
|
# 生成启动脚本
|
|
324
343
|
if is_container_first_template:
|
|
325
344
|
entrypoint_path = output_dir / "entrypoint.sh"
|
|
@@ -327,7 +346,7 @@ class ContainerBuilder(BaseBuilder):
|
|
|
327
346
|
entrypoint = self._generate_entrypoint(detection_result, package_name)
|
|
328
347
|
entrypoint_path = output_dir / "entrypoint.py"
|
|
329
348
|
entrypoint_path.write_text(entrypoint)
|
|
330
|
-
|
|
349
|
+
|
|
331
350
|
return PackageInfo(
|
|
332
351
|
name=detection_result.name or project_path.name,
|
|
333
352
|
framework=detection_result.type.value,
|
|
@@ -339,14 +358,14 @@ class ContainerBuilder(BaseBuilder):
|
|
|
339
358
|
"package_name": package_name,
|
|
340
359
|
"requirements": str(requirements_path),
|
|
341
360
|
"entrypoint": str(entrypoint_path),
|
|
342
|
-
}
|
|
361
|
+
},
|
|
343
362
|
)
|
|
344
|
-
|
|
363
|
+
|
|
345
364
|
def _generate_dockerfile(self, detection_result) -> str:
|
|
346
365
|
"""生成优化的 Dockerfile"""
|
|
347
366
|
base_image = "python:3.12-slim"
|
|
348
|
-
|
|
349
|
-
return f
|
|
367
|
+
|
|
368
|
+
return f"""FROM {base_image}
|
|
350
369
|
|
|
351
370
|
# 设置环境变量
|
|
352
371
|
ENV PYTHONUNBUFFERED=1 \\
|
|
@@ -373,9 +392,9 @@ EXPOSE 8080
|
|
|
373
392
|
|
|
374
393
|
# 使用 exec 形式确保信号正确传递
|
|
375
394
|
CMD ["python", "entrypoint.py"]
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
def _generate_requirements(self, detection_result, project_path: Path = None) -> str:
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
def _generate_requirements(self, detection_result, project_path: Optional[Path] = None) -> str:
|
|
379
398
|
"""生成 requirements.txt"""
|
|
380
399
|
base_deps = [
|
|
381
400
|
# Core
|
|
@@ -392,7 +411,7 @@ CMD ["python", "entrypoint.py"]
|
|
|
392
411
|
"openinference-instrumentation-langchain>=0.1.0",
|
|
393
412
|
"langfuse>=2.0.0",
|
|
394
413
|
]
|
|
395
|
-
|
|
414
|
+
|
|
396
415
|
framework = detection_result.type.value
|
|
397
416
|
base_deps += requirements_for_framework(framework)
|
|
398
417
|
|
|
@@ -400,20 +419,26 @@ CMD ["python", "entrypoint.py"]
|
|
|
400
419
|
base_deps,
|
|
401
420
|
CodeBuilder(project_path or self.project_dir)._bundled_runtime_requirements(),
|
|
402
421
|
)
|
|
403
|
-
|
|
422
|
+
|
|
404
423
|
# 合并用户 requirements.txt (如果存在)
|
|
405
424
|
if project_path:
|
|
406
425
|
user_requirements = project_path / "requirements.txt"
|
|
407
426
|
if user_requirements.exists():
|
|
408
427
|
user_content = user_requirements.read_text()
|
|
428
|
+
parsed_user_requirements = parse_requirements_text(user_content)
|
|
429
|
+
bundled_builder = CodeBuilder(project_path or self.project_dir)
|
|
430
|
+
base_deps = merge_requirement_lists(
|
|
431
|
+
base_deps,
|
|
432
|
+
bundled_builder._bundled_ksadk_extra_requirements(parsed_user_requirements),
|
|
433
|
+
)
|
|
409
434
|
user_deps = exclude_requirement_names(
|
|
410
|
-
|
|
435
|
+
parsed_user_requirements,
|
|
411
436
|
excluded_names={"ksadk"},
|
|
412
437
|
)
|
|
413
438
|
base_deps = merge_requirement_lists(base_deps, user_deps)
|
|
414
|
-
|
|
439
|
+
|
|
415
440
|
return "\n".join(base_deps)
|
|
416
|
-
|
|
441
|
+
|
|
417
442
|
def _generate_entrypoint(self, detection_result, package_name: str) -> str:
|
|
418
443
|
"""生成 entrypoint.py"""
|
|
419
444
|
return f'''"""
|
|
@@ -504,14 +529,17 @@ detection_result = DetectionResult(
|
|
|
504
529
|
entry_point="{detection_result.entry_point}",
|
|
505
530
|
package_path="/app/{package_name}",
|
|
506
531
|
agent_variable="{detection_result.agent_variable}",
|
|
507
|
-
runner_class="{getattr(detection_result,
|
|
532
|
+
runner_class="{getattr(detection_result, "runner_class", "")}"
|
|
508
533
|
)
|
|
509
534
|
|
|
510
535
|
logger.info(f"框架: {{detection_result.name}}")
|
|
511
536
|
logger.info(f"入口: {{detection_result.entry_point}}")
|
|
512
537
|
|
|
513
538
|
# 初始化 Tracing (如果配置了 Langfuse、标准 OTLP HTTP 或 CloudMonitor OTLP)
|
|
514
|
-
has_otlp = bool(
|
|
539
|
+
has_otlp = bool(
|
|
540
|
+
os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
|
|
541
|
+
or os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
|
|
542
|
+
)
|
|
515
543
|
has_cloud_monitor_otlp = bool(
|
|
516
544
|
os.environ.get("CLOUD_MONITOR_APP_KEY")
|
|
517
545
|
or os.environ.get("CLOUD_MONITOR_OTLP_ENDPOINT")
|
|
@@ -522,10 +550,18 @@ has_cloud_monitor_langfuse = bool(
|
|
|
522
550
|
or os.environ.get("CLOUD_MONITOR_LANGFUSE_SECRET_KEY")
|
|
523
551
|
or os.environ.get("CLOUD_MONITOR_LANGFUSE_HOST")
|
|
524
552
|
)
|
|
525
|
-
if
|
|
553
|
+
if (
|
|
554
|
+
os.environ.get("LANGFUSE_PUBLIC_KEY")
|
|
555
|
+
or has_otlp
|
|
556
|
+
or has_cloud_monitor_otlp
|
|
557
|
+
or has_cloud_monitor_langfuse
|
|
558
|
+
):
|
|
526
559
|
try:
|
|
527
560
|
from ksadk.tracing import setup_tracing
|
|
528
|
-
use_callback_only =
|
|
561
|
+
use_callback_only = (
|
|
562
|
+
os.environ.get("LANGFUSE_USE_CALLBACK", "").strip().lower()
|
|
563
|
+
in ("1", "true", "yes", "on")
|
|
564
|
+
)
|
|
529
565
|
setup_tracing(use_callback_only=use_callback_only)
|
|
530
566
|
logger.info(
|
|
531
567
|
f"Tracing 已启用 (OTLP={{has_otlp}}, "
|
|
@@ -540,7 +576,7 @@ if os.environ.get("LANGFUSE_PUBLIC_KEY") or has_otlp or has_cloud_monitor_otlp o
|
|
|
540
576
|
logger.info("正在加载 Agent...")
|
|
541
577
|
runner = create_runner(detection_result, "/app")
|
|
542
578
|
runner.load_agent()
|
|
543
|
-
set_runner(runner)
|
|
579
|
+
set_runner(runner, loaded=True)
|
|
544
580
|
logger.info("Agent 加载成功!")
|
|
545
581
|
|
|
546
582
|
if __name__ == "__main__":
|
|
@@ -548,77 +584,69 @@ if __name__ == "__main__":
|
|
|
548
584
|
logger.info(f"启动 HTTP Server: 0.0.0.0:{{port}}")
|
|
549
585
|
uvicorn.run(app, host="0.0.0.0", port=port, log_level=LOG_LEVEL.lower())
|
|
550
586
|
'''
|
|
551
|
-
|
|
587
|
+
|
|
552
588
|
def build(self) -> BuildResult:
|
|
553
589
|
"""构建 Docker 镜像"""
|
|
554
590
|
from ksadk.detection import FrameworkDetector
|
|
555
|
-
|
|
591
|
+
|
|
556
592
|
self._load_dotenv()
|
|
557
593
|
config = self._load_config()
|
|
558
|
-
|
|
594
|
+
|
|
559
595
|
# 检测框架
|
|
560
596
|
detector = FrameworkDetector(str(self.project_dir))
|
|
561
597
|
result = detector.detect()
|
|
562
|
-
|
|
598
|
+
|
|
563
599
|
if result.type.value == "unknown":
|
|
564
|
-
return BuildResult(
|
|
565
|
-
|
|
566
|
-
error_message="未检测到支持的框架"
|
|
567
|
-
)
|
|
568
|
-
|
|
600
|
+
return BuildResult(success=False, error_message="未检测到支持的框架")
|
|
601
|
+
|
|
569
602
|
click.echo(f"📦 框架: {click.style(result.name, fg='green')}")
|
|
570
|
-
|
|
603
|
+
|
|
571
604
|
# 确定镜像名称
|
|
572
|
-
image_name = config.get(
|
|
573
|
-
|
|
605
|
+
image_name = config.get("name", self.project_dir.name).replace("-", "_").replace(".", "_")
|
|
606
|
+
|
|
574
607
|
# Tag 优先级: 命令行 > agentengine.yaml version > config image.tag > latest
|
|
575
608
|
image_tag = self.tag
|
|
576
609
|
if not image_tag:
|
|
577
|
-
image_tag = config.get(
|
|
610
|
+
image_tag = config.get("version", "") # 使用项目版本作为 tag
|
|
578
611
|
if not image_tag:
|
|
579
|
-
image_tag = config.get(
|
|
580
|
-
|
|
612
|
+
image_tag = config.get("image", {}).get("tag", "latest")
|
|
613
|
+
|
|
581
614
|
# Registry 优先级: 命令行 > .env KCR_REGISTRY > agentengine.yaml > 默认企业版 KCR
|
|
582
615
|
import os
|
|
616
|
+
|
|
583
617
|
image_registry = self.registry
|
|
584
618
|
if not image_registry:
|
|
585
|
-
image_registry = os.getenv(
|
|
619
|
+
image_registry = os.getenv("KCR_REGISTRY", "")
|
|
586
620
|
if not image_registry:
|
|
587
|
-
image_registry = config.get(
|
|
621
|
+
image_registry = config.get("image", {}).get("registry", "")
|
|
588
622
|
if not image_registry:
|
|
589
623
|
# 默认使用企业版 KCR,智能选择内网/公网
|
|
590
|
-
image_registry = self._get_smart_kcr_endpoint(os.getenv(
|
|
624
|
+
image_registry = self._get_smart_kcr_endpoint(os.getenv("KSYUN_REGION", "cn-beijing-6"))
|
|
591
625
|
else:
|
|
592
626
|
# 即使设置了 registry,如果是金山云公网地址,也尝试优化为内网
|
|
593
627
|
image_registry = self._optimize_kcr_endpoint(image_registry)
|
|
594
|
-
|
|
628
|
+
|
|
595
629
|
full_image = f"{image_registry}/{image_name}:{image_tag}"
|
|
596
|
-
|
|
630
|
+
|
|
597
631
|
click.echo(f"🏷️ 镜像名称: {full_image}")
|
|
598
|
-
|
|
632
|
+
|
|
599
633
|
# 打包 (内置打包逻辑,不再依赖 DockerProvider)
|
|
600
634
|
click.echo("\n📦 打包中...")
|
|
601
635
|
try:
|
|
602
636
|
package_info = self._package(result)
|
|
603
637
|
click.echo("✅ 打包完成")
|
|
604
638
|
except Exception as e:
|
|
605
|
-
return BuildResult(
|
|
606
|
-
|
|
607
|
-
error_message=f"打包失败: {e}"
|
|
608
|
-
)
|
|
609
|
-
|
|
639
|
+
return BuildResult(success=False, error_message=f"打包失败: {e}")
|
|
640
|
+
|
|
610
641
|
# Docker 构建
|
|
611
642
|
if not ensure_docker_running():
|
|
612
|
-
return BuildResult(
|
|
613
|
-
|
|
614
|
-
error_message="Docker 未运行"
|
|
615
|
-
)
|
|
616
|
-
|
|
643
|
+
return BuildResult(success=False, error_message="Docker 未运行")
|
|
644
|
+
|
|
617
645
|
click.echo("\n🔨 构建 Docker 镜像 (目标平台: linux/amd64)...")
|
|
618
646
|
try:
|
|
619
|
-
cmd = [
|
|
647
|
+
cmd = ["docker", "build", "--platform", "linux/amd64", "-t", full_image]
|
|
620
648
|
if self.no_cache:
|
|
621
|
-
cmd.append(
|
|
649
|
+
cmd.append("--no-cache")
|
|
622
650
|
cmd.append(package_info.build_dir)
|
|
623
651
|
|
|
624
652
|
quiet_mode = os.getenv("AGENTENGINE_OUTPUT_MODE", "").strip().lower() == "json"
|
|
@@ -628,16 +656,16 @@ if __name__ == "__main__":
|
|
|
628
656
|
capture_output=quiet_mode,
|
|
629
657
|
text=quiet_mode,
|
|
630
658
|
)
|
|
631
|
-
click.secho(f"\n✅ 镜像构建成功: {full_image}", fg=
|
|
632
|
-
|
|
659
|
+
click.secho(f"\n✅ 镜像构建成功: {full_image}", fg="green")
|
|
660
|
+
|
|
633
661
|
return BuildResult(
|
|
634
662
|
success=True,
|
|
635
663
|
artifact_path=None, # Docker 镜像没有本地文件路径
|
|
636
664
|
metadata={
|
|
637
665
|
"image": full_image,
|
|
638
666
|
"framework": result.type.value,
|
|
639
|
-
"build_dir": package_info.build_dir
|
|
640
|
-
}
|
|
667
|
+
"build_dir": package_info.build_dir,
|
|
668
|
+
},
|
|
641
669
|
)
|
|
642
670
|
except subprocess.CalledProcessError as e:
|
|
643
671
|
error_message = f"镜像构建失败: {e}"
|
|
@@ -647,138 +675,130 @@ if __name__ == "__main__":
|
|
|
647
675
|
detail = stderr or stdout
|
|
648
676
|
if detail:
|
|
649
677
|
error_message = f"{error_message}: {detail}"
|
|
650
|
-
return BuildResult(
|
|
651
|
-
|
|
652
|
-
error_message=error_message
|
|
653
|
-
)
|
|
654
|
-
|
|
678
|
+
return BuildResult(success=False, error_message=error_message)
|
|
679
|
+
|
|
655
680
|
def push(self, image_name: str) -> bool:
|
|
656
681
|
"""推送镜像到仓库"""
|
|
657
682
|
# 检查镜像仓库认证
|
|
658
683
|
registry = self._extract_registry(image_name)
|
|
659
|
-
|
|
684
|
+
|
|
660
685
|
# 尝试使用 .env 中的认证信息自动登录
|
|
661
686
|
if registry:
|
|
662
687
|
if not self._auto_login_from_env(registry):
|
|
663
688
|
# 自动登录失败,检查是否已有认证
|
|
664
689
|
if not self._check_registry_auth(registry):
|
|
665
690
|
return False
|
|
666
|
-
|
|
667
|
-
click.echo(
|
|
691
|
+
|
|
692
|
+
click.echo("\n📤 推送镜像...")
|
|
668
693
|
try:
|
|
669
|
-
result = subprocess.run(
|
|
670
|
-
['docker', 'push', image_name],
|
|
671
|
-
capture_output=True,
|
|
672
|
-
text=True
|
|
673
|
-
)
|
|
694
|
+
result = subprocess.run(["docker", "push", image_name], capture_output=True, text=True)
|
|
674
695
|
if result.returncode != 0:
|
|
675
696
|
# 检查是否是认证问题
|
|
676
|
-
if
|
|
677
|
-
self._print_auth_help(registry or
|
|
697
|
+
if "denied" in result.stderr.lower() or "unauthorized" in result.stderr.lower():
|
|
698
|
+
self._print_auth_help(registry or "docker.io")
|
|
678
699
|
return False
|
|
679
|
-
click.secho(f"❌ 镜像推送失败: {result.stderr}", fg=
|
|
700
|
+
click.secho(f"❌ 镜像推送失败: {result.stderr}", fg="red")
|
|
680
701
|
return False
|
|
681
|
-
|
|
682
|
-
click.secho(
|
|
702
|
+
|
|
703
|
+
click.secho("✅ 镜像推送成功", fg="green")
|
|
683
704
|
return True
|
|
684
705
|
except subprocess.CalledProcessError as e:
|
|
685
|
-
click.secho(f"❌ 镜像推送失败: {e}", fg=
|
|
706
|
+
click.secho(f"❌ 镜像推送失败: {e}", fg="red")
|
|
686
707
|
return False
|
|
687
|
-
|
|
708
|
+
|
|
688
709
|
def _auto_login_from_env(self, registry: str) -> bool:
|
|
689
710
|
"""尝试使用 .env 中的凭证自动登录"""
|
|
690
711
|
import os
|
|
712
|
+
|
|
691
713
|
from dotenv import load_dotenv
|
|
692
|
-
|
|
714
|
+
|
|
693
715
|
# 加载 .env
|
|
694
716
|
load_dotenv()
|
|
695
|
-
|
|
696
|
-
# KCR_REGISTRY is
|
|
697
|
-
kcr_registry = os.getenv(
|
|
717
|
+
|
|
718
|
+
# KCR_REGISTRY is the registry/namespace target for KCR and third parties.
|
|
719
|
+
kcr_registry = os.getenv("KCR_REGISTRY", "")
|
|
698
720
|
if not kcr_registry:
|
|
699
721
|
kcr_registry = "hub.kce.ksyun.com/agentengine"
|
|
700
|
-
|
|
722
|
+
|
|
701
723
|
kcr_username, kcr_password, registry_kind = resolve_registry_credentials(registry)
|
|
702
|
-
|
|
724
|
+
|
|
703
725
|
# 检查是否匹配当前 registry (支持部分匹配)
|
|
704
726
|
if registry not in kcr_registry and kcr_registry not in registry:
|
|
705
727
|
return False
|
|
706
|
-
|
|
728
|
+
|
|
707
729
|
if not kcr_username or not kcr_password:
|
|
708
730
|
print_registry_credentials_help(registry, kind=registry_kind)
|
|
709
731
|
return False
|
|
710
|
-
|
|
732
|
+
|
|
711
733
|
click.echo(f"🔐 使用 .env 中的凭证登录 {registry}...")
|
|
712
734
|
try:
|
|
713
735
|
result = subprocess.run(
|
|
714
|
-
[
|
|
736
|
+
["docker", "login", registry, "-u", kcr_username, "--password-stdin"],
|
|
715
737
|
input=kcr_password,
|
|
716
738
|
capture_output=True,
|
|
717
739
|
text=True,
|
|
718
|
-
timeout=30
|
|
740
|
+
timeout=30,
|
|
719
741
|
)
|
|
720
742
|
if result.returncode == 0:
|
|
721
|
-
click.secho(
|
|
743
|
+
click.secho("✅ 登录成功", fg="green")
|
|
722
744
|
return True
|
|
723
745
|
else:
|
|
724
|
-
click.secho(f"⚠️ 自动登录失败: {result.stderr.strip()}", fg=
|
|
746
|
+
click.secho(f"⚠️ 自动登录失败: {result.stderr.strip()}", fg="yellow")
|
|
725
747
|
return False
|
|
726
748
|
except Exception as e:
|
|
727
|
-
click.secho(f"⚠️ 自动登录异常: {e}", fg=
|
|
749
|
+
click.secho(f"⚠️ 自动登录异常: {e}", fg="yellow")
|
|
728
750
|
return False
|
|
729
|
-
|
|
751
|
+
|
|
730
752
|
def get_registry_credentials(self, registry: str | None = None) -> dict:
|
|
731
753
|
"""获取镜像仓库凭证 (用于传给 Serverless)
|
|
732
|
-
|
|
754
|
+
|
|
733
755
|
返回扁平化结构: {"username": "...", "password": "..."}
|
|
734
756
|
"""
|
|
735
757
|
import os
|
|
758
|
+
|
|
736
759
|
from dotenv import load_dotenv
|
|
737
|
-
|
|
760
|
+
|
|
738
761
|
load_dotenv()
|
|
739
|
-
|
|
762
|
+
|
|
740
763
|
registry = registry or os.getenv("KCR_REGISTRY", "")
|
|
741
764
|
username, password, _ = resolve_registry_credentials(registry)
|
|
742
|
-
|
|
765
|
+
|
|
743
766
|
if username and password:
|
|
744
|
-
return {
|
|
745
|
-
'username': username,
|
|
746
|
-
'password': password
|
|
747
|
-
}
|
|
767
|
+
return {"username": username, "password": password}
|
|
748
768
|
return {}
|
|
749
|
-
|
|
769
|
+
|
|
750
770
|
def _extract_registry(self, image_name: str) -> Optional[str]:
|
|
751
771
|
"""从镜像名称提取仓库地址"""
|
|
752
772
|
# 格式: registry/namespace/image:tag 或 namespace/image:tag (默认 docker.io)
|
|
753
|
-
parts = image_name.split(
|
|
754
|
-
if len(parts) >= 2 and (
|
|
773
|
+
parts = image_name.split("/")
|
|
774
|
+
if len(parts) >= 2 and ("." in parts[0] or ":" in parts[0]):
|
|
755
775
|
return parts[0]
|
|
756
776
|
return None # 使用默认 docker.io
|
|
757
|
-
|
|
777
|
+
|
|
758
778
|
def _check_registry_auth(self, registry: str) -> bool:
|
|
759
779
|
"""检查是否已登录镜像仓库"""
|
|
760
780
|
try:
|
|
761
781
|
# 尝试获取 docker 配置
|
|
762
782
|
import json
|
|
763
783
|
from pathlib import Path
|
|
764
|
-
|
|
765
|
-
docker_config = Path.home() /
|
|
784
|
+
|
|
785
|
+
docker_config = Path.home() / ".docker" / "config.json"
|
|
766
786
|
if docker_config.exists():
|
|
767
787
|
with open(docker_config) as f:
|
|
768
788
|
config = json.load(f)
|
|
769
|
-
auths = config.get(
|
|
789
|
+
auths = config.get("auths", {})
|
|
770
790
|
# 检查是否有该仓库的认证信息
|
|
771
|
-
if registry in auths or f
|
|
791
|
+
if registry in auths or f"https://{registry}" in auths:
|
|
772
792
|
return True
|
|
773
|
-
|
|
793
|
+
|
|
774
794
|
# 没有找到认证信息,提示用户
|
|
775
|
-
click.secho(f"\n⚠️ 未检测到 {registry} 的登录凭证", fg=
|
|
795
|
+
click.secho(f"\n⚠️ 未检测到 {registry} 的登录凭证", fg="yellow")
|
|
776
796
|
self._print_auth_help(registry)
|
|
777
797
|
return False
|
|
778
798
|
except Exception:
|
|
779
799
|
# 无法检查,继续尝试推送
|
|
780
800
|
return True
|
|
781
|
-
|
|
801
|
+
|
|
782
802
|
def _print_auth_help(self, registry: str):
|
|
783
803
|
"""打印认证帮助信息"""
|
|
784
804
|
print_registry_credentials_help(registry)
|