agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.1__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.1.dist-info}/METADATA +52 -20
- agentengine_sdk_python-0.8.1.dist-info/RECORD +644 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/WHEEL +1 -1
- ksadk/a2a/__init__.py +180 -11
- ksadk/a2a/bootstrap.py +332 -0
- ksadk/a2a/card.py +15 -0
- ksadk/a2a/context_store.py +203 -0
- ksadk/a2a/control_plane.py +1056 -0
- ksadk/a2a/credential.py +99 -0
- ksadk/a2a/event_adapter.py +149 -0
- ksadk/a2a/executor.py +361 -137
- 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 +112 -0
- ksadk/a2a/server.py +102 -62
- ksadk/a2a/service_env.py +33 -0
- ksadk/a2a/space_client.py +1122 -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/a2a_card.py +101 -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 +872 -0
- ksadk/agui/config.py +92 -0
- ksadk/agui/routes.py +47 -0
- ksadk/api/client.py +238 -204
- ksadk/api/environment.py +27 -0
- ksadk/builders/__init__.py +2 -0
- ksadk/builders/base.py +16 -14
- ksadk/builders/code_builder.py +375 -270
- ksadk/builders/container_builder.py +240 -200
- ksadk/builders/framework_requirements.py +31 -12
- ksadk/builders/ks3_uploader.py +60 -29
- ksadk/builders/managed_runtime_builder.py +173 -0
- ksadk/builders/mcp_builder.py +91 -92
- ksadk/builders/requirements_utils.py +1 -5
- ksadk/cli/__init__.py +97 -171
- ksadk/cli/cmd_a2a.py +255 -84
- 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 +507 -740
- ksadk/cli/cmd_dashboard.py +120 -45
- ksadk/cli/cmd_deploy.py +135 -59
- ksadk/cli/cmd_destroy.py +44 -14
- ksadk/cli/cmd_eval.py +386 -0
- ksadk/cli/cmd_files.py +63 -24
- ksadk/cli/cmd_hermes.py +313 -135
- ksadk/cli/cmd_invoke.py +184 -122
- ksadk/cli/cmd_launch.py +76 -28
- ksadk/cli/cmd_mcp.py +98 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +564 -268
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +58 -73
- ksadk/cli/cmd_status.py +80 -31
- ksadk/cli/cmd_studio.py +110 -0
- ksadk/cli/cmd_version.py +20 -13
- ksadk/cli/cmd_web.py +95 -18
- ksadk/cli/deploy_utils.py +20 -20
- ksadk/cli/dry_run.py +7 -4
- ksadk/cli/env_options.py +83 -0
- ksadk/cli/error_utils.py +37 -12
- ksadk/cli/global_options.py +4 -3
- ksadk/cli/local_runtime.py +1 -2
- ksadk/cli/model_catalog.py +6 -2
- ksadk/cli/network_options.py +41 -19
- ksadk/cli/resource_common.py +6 -2
- ksadk/cli/runtime_bootstrap.py +51 -0
- ksadk/cli/storage.py +0 -1
- ksadk/cli/ui.py +11 -3
- ksadk/cli/workflow_common.py +52 -18
- ksadk/codex/__init__.py +12 -0
- ksadk/codex/client.py +1042 -0
- ksadk/codex/phase.py +143 -0
- ksadk/codex/runtime.py +940 -0
- ksadk/common/aicp_env.py +0 -1
- ksadk/common/auth.py +2 -2
- ksadk/common/constants.py +1 -3
- ksadk/common/kop_client.py +232 -0
- 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 -14
- ksadk/configs/env_registry.py +661 -116
- ksadk/configs/global_config.py +3 -2
- ksadk/configs/settings.py +133 -209
- ksadk/conversations/__init__.py +85 -92
- 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 +660 -0
- ksadk/conversations/runtime_invocation.py +395 -0
- ksadk/conversations/runtime_metadata.py +475 -0
- ksadk/conversations/runtime_observability.py +367 -0
- ksadk/conversations/runtime_payloads.py +272 -0
- ksadk/conversations/runtime_persistence.py +440 -0
- ksadk/conversations/runtime_preparation.py +426 -0
- ksadk/conversations/runtime_resume.py +836 -0
- ksadk/conversations/runtime_stream_events.py +902 -0
- ksadk/conversations/runtime_streaming.py +700 -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/managed_runtime.py +33 -0
- ksadk/deployment/manager.py +85 -71
- ksadk/deployment/providers/serverless.py +379 -210
- 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/evaluation/__init__.py +84 -0
- ksadk/evaluation/a2a_adapter.py +444 -0
- ksadk/evaluation/adapters.py +54 -0
- ksadk/evaluation/contracts.py +409 -0
- ksadk/evaluation/evalset.py +351 -0
- ksadk/evaluation/evaluators.py +461 -0
- ksadk/evaluation/executor.py +118 -0
- ksadk/evaluation/storage.py +68 -0
- ksadk/evaluation/target.py +73 -0
- ksadk/events/__init__.py +25 -0
- ksadk/events/parser.py +191 -0
- ksadk/events/replay.py +37 -0
- ksadk/events/runtime_event.py +273 -0
- ksadk/events/store.py +317 -0
- ksadk/harness/__init__.py +35 -0
- ksadk/harness/app.py +269 -0
- ksadk/harness/config.py +181 -0
- ksadk/harness/reasoner.py +105 -0
- ksadk/harness/runtime.py +364 -0
- ksadk/harness/sandbox.py +141 -0
- ksadk/harness/tools.py +222 -0
- ksadk/hermes_terminal.py +28 -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 +38 -33
- ksadk/managed_a2a_card.py +160 -0
- ksadk/managed_runtime.py +195 -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 +36 -36
- ksadk/memory/adk/long_term_memory.py +34 -37
- 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 +16 -6
- ksadk/memory/tool.py +4 -0
- 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 +66 -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 +201 -0
- ksadk/model_proxy/protocol_proxy.py +22 -0
- ksadk/model_proxy/server.py +443 -0
- ksadk/model_proxy/transform.py +735 -0
- ksadk/openclaw_gateway.py +29 -14
- ksadk/runners/adk_runner.py +354 -146
- ksadk/runners/base_runner.py +71 -29
- ksadk/runners/deepagents_runner.py +0 -1
- ksadk/runners/factory.py +18 -5
- ksadk/runners/langchain_runner.py +29 -742
- ksadk/runners/langgraph_runner.py +417 -97
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +134 -33
- ksadk/runners/usage_accumulator.py +1 -0
- ksadk/runners/utils/__init__.py +0 -10
- ksadk/runners/utils/loader.py +23 -7
- ksadk/runtime/__init__.py +67 -0
- ksadk/runtime/adapter.py +412 -0
- ksadk/runtime/conversation_execution.py +553 -0
- ksadk/runtime/executor.py +251 -0
- ksadk/runtime/factory.py +156 -0
- ksadk/runtime/framework_adapters.py +118 -0
- ksadk/runtime/launch.py +48 -0
- ksadk/runtime/preprocessing.py +131 -0
- ksadk/runtime/runner_adapter.py +1032 -0
- ksadk/runtime/runner_loading.py +36 -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/__init__.py +39 -4
- ksadk/server/api_models.py +15 -5
- ksadk/server/app.py +24 -3928
- ksadk/server/composition.py +47 -0
- ksadk/server/factory.py +622 -0
- ksadk/server/routes/__init__.py +1 -0
- ksadk/server/routes/checkpoint_resolution.py +116 -0
- ksadk/server/routes/common.py +682 -0
- ksadk/server/routes/control.py +331 -0
- ksadk/server/routes/dependencies.py +98 -0
- ksadk/server/routes/misc.py +425 -0
- ksadk/server/routes/models.py +451 -0
- ksadk/server/routes/openai_compat.py +229 -0
- ksadk/server/routes/projection.py +848 -0
- ksadk/server/routes/routers.py +52 -0
- ksadk/server/routes/run.py +519 -0
- ksadk/server/routes/sessions.py +644 -0
- ksadk/server/routes/streaming.py +265 -0
- ksadk/server/routes/workspace.py +414 -0
- ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-CakCqxEN.js} +1 -1
- ksadk/server/static/assets/CodeBlock-CynLknyO.js +9 -0
- ksadk/server/static/assets/MathMessageMarkdown-3sQdOysS.js +8 -0
- ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +1 -0
- ksadk/server/static/assets/{arc-BA13sHc9.js → arc-DrgjcKhl.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-BXoVRbQ6.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-BnaB3Ywv.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-Dw4weZcp.js} +1 -1
- ksadk/server/static/assets/channel-Dt3rQTFI.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-ChjpLK7j.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-B9drTgOW.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-CK4ROATy.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B9KtTTgw.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-1O1mki3m.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-B_fH2YuH.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D6rFLaVV.js} +1 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-ChNs_Mdk.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-D0QXg_MQ.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-DBDDKwBQ.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-BkwDOxmO.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Bv8waYvY.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-e1VECDdu.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-Ds9adfRl.js} +1 -1
- ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-4N2NMVYg.js} +1 -1
- ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-B-jNR6Vn.js} +1 -1
- ksadk/server/static/assets/{dist-D57wnGWd.js → dist-B5J2uhNk.js} +1 -1
- ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-B5oS1zcj.js} +1 -1
- ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BB3-OwTQ.js} +1 -1
- ksadk/server/static/assets/{dist-2hInLS_J.js → dist-BIlKoW0k.js} +1 -1
- ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-BjOdlDjj.js} +1 -1
- ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-C1sz5Eo3.js} +1 -1
- ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-CWV4lDr1.js} +1 -1
- ksadk/server/static/assets/{dist-D-xOD048.js → dist-CmZHzlwZ.js} +1 -1
- ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-D6MpCZtz.js} +1 -1
- ksadk/server/static/assets/{dist-DyOkZmze.js → dist-DJN_6Y39.js} +1 -1
- ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-DQU9EWw-.js} +1 -1
- ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-DWKByxWV.js} +1 -1
- ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-Dli7qW-B.js} +1 -1
- ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-DsHPdk3W.js} +1 -1
- ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-X4TnqwOK.js} +1 -1
- ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-_pHPTyZ-.js} +1 -1
- ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-fhOuWds5.js} +1 -1
- ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-gLnrGsoU.js} +1 -1
- ksadk/server/static/assets/{dist-BssVmjIo.js → dist-j6Dxmf_j.js} +1 -1
- ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-o2OVmKvt.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-BPItFKH6.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-BbYB9w5Y.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-TQXa0KXv.js} +1 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-bKblCnpa.js} +1 -1
- ksadk/server/static/assets/index-R52pJJvg.js +177 -0
- ksadk/server/static/assets/index-jJr3_955.css +2 -0
- ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +1 -0
- ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-BGVT7J_i.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-K0OOfVna.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-8LeOJaZp.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-C6uCgZrW.js} +1 -1
- ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-CYWseY5E.js} +1 -1
- ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-hdBcYzM8.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-BWrDjSZM.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-Bjy_2v4_.js} +1 -1
- ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +1 -0
- ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-GmmqNiVH.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-BmkRbwCg.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DSWFqL7c.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-l6iXmU65.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-Cq6UBeQB.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-qzTQpg3Y.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +1 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-DEz24vV0.js} +1 -1
- ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +1 -0
- ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-CMCixki2.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-CVzB8F9K.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-BFBqBLc1.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 +47 -16
- ksadk/skills/tool_defs.py +15 -10
- ksadk/studio/__init__.py +5 -0
- ksadk/studio/agent_avatar_assets.py +120 -0
- ksadk/studio/agent_lifecycle.py +51 -0
- ksadk/studio/api.py +1046 -0
- ksadk/studio/api_catalog_routes.py +324 -0
- ksadk/studio/api_contracts.py +177 -0
- ksadk/studio/api_helpers.py +132 -0
- ksadk/studio/authoring.py +524 -0
- ksadk/studio/authoring_coordinator.py +285 -0
- ksadk/studio/builder.py +320 -0
- ksadk/studio/capabilities.py +351 -0
- ksadk/studio/cloud.py +278 -0
- ksadk/studio/codex_agent_service.py +583 -0
- ksadk/studio/codex_builder.py +324 -0
- ksadk/studio/codex_manifest.py +278 -0
- ksadk/studio/codex_run.py +352 -0
- ksadk/studio/compiler.py +189 -0
- ksadk/studio/contracts.py +644 -0
- ksadk/studio/errors.py +47 -0
- ksadk/studio/evaluation.py +192 -0
- ksadk/studio/event_store.py +284 -0
- ksadk/studio/framework_run.py +114 -0
- ksadk/studio/identifiers.py +33 -0
- ksadk/studio/mcp_runtime.py +229 -0
- ksadk/studio/model_client.py +543 -0
- ksadk/studio/model_profile_service.py +214 -0
- ksadk/studio/operations.py +243 -0
- ksadk/studio/otel_trace.py +754 -0
- ksadk/studio/pagination.py +182 -0
- ksadk/studio/python_tool_inspection.py +183 -0
- ksadk/studio/repository.py +306 -0
- ksadk/studio/resource_catalog.py +1217 -0
- ksadk/studio/run_service.py +707 -0
- ksadk/studio/runtime_catalog.py +74 -0
- ksadk/studio/runtime_source.py +339 -0
- ksadk/studio/service.py +1141 -0
- ksadk/studio/shared_web.py +994 -0
- ksadk/studio/skill_discovery.py +628 -0
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
- ksadk/studio/static/assets/index-CaEN0eTR.css +1 -0
- ksadk/studio/static/assets/index-DI2eY_NH.js +252 -0
- ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
- ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- ksadk/studio/static/index.html +15 -0
- ksadk/studio/templates.py +630 -0
- ksadk/studio/validator.py +246 -0
- ksadk/studio/workspace.py +137 -0
- ksadk/terminal_exec_policy.py +3 -4
- ksadk/tools/gateway.py +101 -15
- ksadk/tools/result_budget.py +12 -4
- ksadk/toolsets/__init__.py +161 -37
- ksadk/toolsets/a2a.py +426 -0
- 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/__init__.py +19 -21
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/setup.py +135 -506
- ksadk/tracing/span_utils.py +0 -41
- 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/memory_backend/registry.py +56 -56
- ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
- ksadk_runtime_common/workspace_files/router.py +8 -2
- agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
- ksadk/a2a/card_builder.py +0 -64
- ksadk/a2a/client.py +0 -309
- ksadk/runners/utils/langfuse.py +0 -230
- 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
- ksadk/tracing/exporters/langfuse_exporter.py +0 -445
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.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
|
|
@@ -385,14 +404,14 @@ CMD ["python", "entrypoint.py"]
|
|
|
385
404
|
"pydantic>=2.0.0",
|
|
386
405
|
"pyyaml>=6.0.0",
|
|
387
406
|
"httpx>=0.24.0",
|
|
388
|
-
# Tracing
|
|
407
|
+
# Tracing — OTLP 双写收敛:只用 OTel + openinference 自动插桩,
|
|
408
|
+
# 不再安装 Langfuse SDK(callback 路径已删除,Langfuse 通过标准 OTLP 接收)。
|
|
389
409
|
"opentelemetry-api>=1.37.0",
|
|
390
410
|
"opentelemetry-sdk>=1.37.0",
|
|
391
411
|
"opentelemetry-exporter-otlp>=1.37.0",
|
|
392
412
|
"openinference-instrumentation-langchain>=0.1.0",
|
|
393
|
-
"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'''"""
|
|
@@ -464,15 +489,11 @@ except ImportError:
|
|
|
464
489
|
|
|
465
490
|
env_keys = [
|
|
466
491
|
"AGENT_RUNTIME_NAME", "AGENT_RUNTIME_ID", "ACCOUNT_ID", "PORT",
|
|
467
|
-
"LANGFUSE_BASE_URL", "LANGFUSE_HOST", "LANGFUSE_PUBLIC_KEY",
|
|
468
|
-
"LANGFUSE_SECRET_KEY", "LANGFUSE_USE_CALLBACK",
|
|
469
492
|
"OTEL_EXPORTER_OTLP_ENDPOINT", "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT",
|
|
470
493
|
"OTEL_EXPORTER_OTLP_HEADERS", "OTEL_EXPORTER_OTLP_TRACES_HEADERS",
|
|
471
|
-
"OTEL_SERVICE_NAME",
|
|
472
|
-
"
|
|
473
|
-
"
|
|
474
|
-
"CLOUD_MONITOR_LANGFUSE_HOST", "CLOUD_MONITOR_LANGFUSE_PUBLIC_KEY",
|
|
475
|
-
"CLOUD_MONITOR_LANGFUSE_SECRET_KEY", "CLOUD_MONITOR_LANGFUSE_ENABLED",
|
|
494
|
+
"OTEL_SERVICE_NAME",
|
|
495
|
+
"CLOUD_MONITOR_OTLP_ENDPOINT", "CLOUD_MONITOR_OTLP_TRACES_ENDPOINT",
|
|
496
|
+
"CLOUD_MONITOR_OTLP_HEADERS", "CLOUD_MONITOR_OTLP_TRACES_HEADERS",
|
|
476
497
|
"LANGCHAIN_TRACING_V2", "MODEL_NAME",
|
|
477
498
|
]
|
|
478
499
|
for key in env_keys:
|
|
@@ -486,15 +507,9 @@ for key in env_keys:
|
|
|
486
507
|
from ksadk.configs import setup_environment
|
|
487
508
|
setup_environment(Path("/app"))
|
|
488
509
|
|
|
489
|
-
try:
|
|
490
|
-
from ksadk.runners.patch_langchain import apply_patch as apply_langchain_patch
|
|
491
|
-
apply_langchain_patch()
|
|
492
|
-
except ImportError:
|
|
493
|
-
pass
|
|
494
|
-
|
|
495
|
-
from ksadk.runners import create_runner
|
|
496
510
|
from ksadk.detection import DetectionResult, FrameworkType
|
|
497
|
-
from ksadk.
|
|
511
|
+
from ksadk.runtime import RuntimeExecutor, RuntimeLaunchContext, build_default_runtime_registry
|
|
512
|
+
from ksadk.server import RuntimeAppConfig, configure_runtime_app, create_runtime_app
|
|
498
513
|
import uvicorn
|
|
499
514
|
|
|
500
515
|
# 检测结果 (构建时固化)
|
|
@@ -504,121 +519,154 @@ detection_result = DetectionResult(
|
|
|
504
519
|
entry_point="{detection_result.entry_point}",
|
|
505
520
|
package_path="/app/{package_name}",
|
|
506
521
|
agent_variable="{detection_result.agent_variable}",
|
|
507
|
-
runner_class="{getattr(detection_result,
|
|
522
|
+
runner_class="{getattr(detection_result, "runner_class", "")}"
|
|
508
523
|
)
|
|
509
524
|
|
|
510
525
|
logger.info(f"框架: {{detection_result.name}}")
|
|
511
526
|
logger.info(f"入口: {{detection_result.entry_point}}")
|
|
512
527
|
|
|
513
|
-
# 初始化 Tracing (
|
|
514
|
-
has_otlp = bool(
|
|
528
|
+
# 初始化 Tracing (如果配置了标准 OTLP HTTP 或 CloudMonitor OTLP)
|
|
529
|
+
has_otlp = bool(
|
|
530
|
+
os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
|
|
531
|
+
or os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT")
|
|
532
|
+
)
|
|
515
533
|
has_cloud_monitor_otlp = bool(
|
|
516
|
-
os.environ.get("
|
|
534
|
+
os.environ.get("CLOUD_MONITOR_OTLP_TRACES_HEADERS")
|
|
535
|
+
or os.environ.get("CLOUD_MONITOR_OTLP_HEADERS")
|
|
517
536
|
or os.environ.get("CLOUD_MONITOR_OTLP_ENDPOINT")
|
|
518
537
|
or os.environ.get("CLOUD_MONITOR_OTLP_TRACES_ENDPOINT")
|
|
538
|
+
or os.environ.get("CLOUD_MONITOR_APP_KEY")
|
|
519
539
|
)
|
|
520
|
-
|
|
521
|
-
os.environ.get("CLOUD_MONITOR_LANGFUSE_PUBLIC_KEY")
|
|
522
|
-
or os.environ.get("CLOUD_MONITOR_LANGFUSE_SECRET_KEY")
|
|
523
|
-
or os.environ.get("CLOUD_MONITOR_LANGFUSE_HOST")
|
|
524
|
-
)
|
|
525
|
-
if os.environ.get("LANGFUSE_PUBLIC_KEY") or has_otlp or has_cloud_monitor_otlp or has_cloud_monitor_langfuse:
|
|
540
|
+
if has_otlp or has_cloud_monitor_otlp:
|
|
526
541
|
try:
|
|
527
542
|
from ksadk.tracing import setup_tracing
|
|
528
|
-
|
|
529
|
-
setup_tracing(use_callback_only=use_callback_only)
|
|
543
|
+
setup_tracing()
|
|
530
544
|
logger.info(
|
|
531
545
|
f"Tracing 已启用 (OTLP={{has_otlp}}, "
|
|
532
|
-
f"CloudMonitorOTLP={{has_cloud_monitor_otlp}}
|
|
533
|
-
f"CloudMonitorLangfuse={{has_cloud_monitor_langfuse}}, "
|
|
534
|
-
f"CallbackOnly={{use_callback_only}})"
|
|
546
|
+
f"CloudMonitorOTLP={{has_cloud_monitor_otlp}})"
|
|
535
547
|
)
|
|
536
548
|
except Exception as e:
|
|
537
549
|
logger.warning(f"Tracing 初始化失败: {{e}}")
|
|
538
550
|
|
|
539
|
-
#
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
551
|
+
# 只装配统一 RuntimeAdapter 执行链;具体 Adapter 在请求开始时由 Registry 创建。
|
|
552
|
+
runtime_context = RuntimeLaunchContext(
|
|
553
|
+
runtime_type=detection_result.type.value,
|
|
554
|
+
project_dir=Path("/app"),
|
|
555
|
+
detection=detection_result,
|
|
556
|
+
config=dict(getattr(detection_result, "raw_config", None) or {{}}),
|
|
557
|
+
)
|
|
558
|
+
# managed A2A:KSADK_A2A_RUNTIME_ID 非空时挂 discovery card + 完整数据面 route。
|
|
559
|
+
# discovery card 让 server 探测;数据面 route 让 gateway 转发的 JSON-RPC/REST
|
|
560
|
+
# 能真正落到本 runtime 的 A2A 协议端点(路线 C 直连)。
|
|
561
|
+
_a2a_config = None
|
|
562
|
+
_a2a_adapter = None
|
|
563
|
+
if os.environ.get("KSADK_A2A_RUNTIME_ID", "").strip():
|
|
564
|
+
from ksadk.managed_a2a_card import build_managed_a2a_card_if_configured
|
|
565
|
+
|
|
566
|
+
_managed_a2a_card = build_managed_a2a_card_if_configured()
|
|
567
|
+
try:
|
|
568
|
+
from ksadk.a2a.routes import A2AConfig
|
|
569
|
+
from ksadk.runtime.factory import create_runtime_adapter
|
|
570
|
+
|
|
571
|
+
_a2a_adapter = create_runtime_adapter(runtime_context)
|
|
572
|
+
_base = (
|
|
573
|
+
os.environ.get("KSADK_A2A_INTERNAL_BASE_URL", "").strip()
|
|
574
|
+
or "http://localhost:8080"
|
|
575
|
+
)
|
|
576
|
+
_a2a_config = A2AConfig(
|
|
577
|
+
enabled=True,
|
|
578
|
+
base_url=_base,
|
|
579
|
+
agent_name=(
|
|
580
|
+
os.environ.get("KSADK_A2A_AGENT_NAME", "").strip()
|
|
581
|
+
or os.environ.get("KSADK_A2A_RUNTIME_ID", "").strip()
|
|
582
|
+
),
|
|
583
|
+
streaming=True,
|
|
584
|
+
task_store_dsn="sqlite+aiosqlite:///.agentengine/a2a_tasks.db",
|
|
585
|
+
)
|
|
586
|
+
except Exception as _e:
|
|
587
|
+
logger.warning(f"managed A2A 数据面装配失败,回退 discovery-only: {{_e}}")
|
|
588
|
+
_a2a_config = None
|
|
589
|
+
_a2a_adapter = None
|
|
590
|
+
app = create_runtime_app(
|
|
591
|
+
RuntimeAppConfig(
|
|
592
|
+
runtime_type=detection_result.type.value,
|
|
593
|
+
runtime_executor=RuntimeExecutor(build_default_runtime_registry()),
|
|
594
|
+
launch_context=runtime_context,
|
|
595
|
+
a2a=_a2a_config or _managed_a2a_card,
|
|
596
|
+
a2a_runtime_adapter=_a2a_adapter,
|
|
597
|
+
),
|
|
598
|
+
configure_runtime_app,
|
|
599
|
+
)
|
|
600
|
+
logger.info("RuntimeAdapter 执行链装配成功!")
|
|
545
601
|
|
|
546
602
|
if __name__ == "__main__":
|
|
547
603
|
port = int(os.environ.get("PORT", 8080))
|
|
548
604
|
logger.info(f"启动 HTTP Server: 0.0.0.0:{{port}}")
|
|
549
605
|
uvicorn.run(app, host="0.0.0.0", port=port, log_level=LOG_LEVEL.lower())
|
|
550
606
|
'''
|
|
551
|
-
|
|
607
|
+
|
|
552
608
|
def build(self) -> BuildResult:
|
|
553
609
|
"""构建 Docker 镜像"""
|
|
554
610
|
from ksadk.detection import FrameworkDetector
|
|
555
|
-
|
|
611
|
+
|
|
556
612
|
self._load_dotenv()
|
|
557
613
|
config = self._load_config()
|
|
558
|
-
|
|
614
|
+
|
|
559
615
|
# 检测框架
|
|
560
616
|
detector = FrameworkDetector(str(self.project_dir))
|
|
561
617
|
result = detector.detect()
|
|
562
|
-
|
|
618
|
+
|
|
563
619
|
if result.type.value == "unknown":
|
|
564
|
-
return BuildResult(
|
|
565
|
-
|
|
566
|
-
error_message="未检测到支持的框架"
|
|
567
|
-
)
|
|
568
|
-
|
|
620
|
+
return BuildResult(success=False, error_message="未检测到支持的框架")
|
|
621
|
+
|
|
569
622
|
click.echo(f"📦 框架: {click.style(result.name, fg='green')}")
|
|
570
|
-
|
|
623
|
+
|
|
571
624
|
# 确定镜像名称
|
|
572
|
-
image_name = config.get(
|
|
573
|
-
|
|
625
|
+
image_name = config.get("name", self.project_dir.name).replace("-", "_").replace(".", "_")
|
|
626
|
+
|
|
574
627
|
# Tag 优先级: 命令行 > agentengine.yaml version > config image.tag > latest
|
|
575
628
|
image_tag = self.tag
|
|
576
629
|
if not image_tag:
|
|
577
|
-
image_tag = config.get(
|
|
630
|
+
image_tag = config.get("version", "") # 使用项目版本作为 tag
|
|
578
631
|
if not image_tag:
|
|
579
|
-
image_tag = config.get(
|
|
580
|
-
|
|
632
|
+
image_tag = config.get("image", {}).get("tag", "latest")
|
|
633
|
+
|
|
581
634
|
# Registry 优先级: 命令行 > .env KCR_REGISTRY > agentengine.yaml > 默认企业版 KCR
|
|
582
635
|
import os
|
|
636
|
+
|
|
583
637
|
image_registry = self.registry
|
|
584
638
|
if not image_registry:
|
|
585
|
-
image_registry = os.getenv(
|
|
639
|
+
image_registry = os.getenv("KCR_REGISTRY", "")
|
|
586
640
|
if not image_registry:
|
|
587
|
-
image_registry = config.get(
|
|
641
|
+
image_registry = config.get("image", {}).get("registry", "")
|
|
588
642
|
if not image_registry:
|
|
589
643
|
# 默认使用企业版 KCR,智能选择内网/公网
|
|
590
|
-
image_registry = self._get_smart_kcr_endpoint(os.getenv(
|
|
644
|
+
image_registry = self._get_smart_kcr_endpoint(os.getenv("KSYUN_REGION", "cn-beijing-6"))
|
|
591
645
|
else:
|
|
592
646
|
# 即使设置了 registry,如果是金山云公网地址,也尝试优化为内网
|
|
593
647
|
image_registry = self._optimize_kcr_endpoint(image_registry)
|
|
594
|
-
|
|
648
|
+
|
|
595
649
|
full_image = f"{image_registry}/{image_name}:{image_tag}"
|
|
596
|
-
|
|
650
|
+
|
|
597
651
|
click.echo(f"🏷️ 镜像名称: {full_image}")
|
|
598
|
-
|
|
652
|
+
|
|
599
653
|
# 打包 (内置打包逻辑,不再依赖 DockerProvider)
|
|
600
654
|
click.echo("\n📦 打包中...")
|
|
601
655
|
try:
|
|
602
656
|
package_info = self._package(result)
|
|
603
657
|
click.echo("✅ 打包完成")
|
|
604
658
|
except Exception as e:
|
|
605
|
-
return BuildResult(
|
|
606
|
-
|
|
607
|
-
error_message=f"打包失败: {e}"
|
|
608
|
-
)
|
|
609
|
-
|
|
659
|
+
return BuildResult(success=False, error_message=f"打包失败: {e}")
|
|
660
|
+
|
|
610
661
|
# Docker 构建
|
|
611
662
|
if not ensure_docker_running():
|
|
612
|
-
return BuildResult(
|
|
613
|
-
|
|
614
|
-
error_message="Docker 未运行"
|
|
615
|
-
)
|
|
616
|
-
|
|
663
|
+
return BuildResult(success=False, error_message="Docker 未运行")
|
|
664
|
+
|
|
617
665
|
click.echo("\n🔨 构建 Docker 镜像 (目标平台: linux/amd64)...")
|
|
618
666
|
try:
|
|
619
|
-
cmd = [
|
|
667
|
+
cmd = ["docker", "build", "--platform", "linux/amd64", "-t", full_image]
|
|
620
668
|
if self.no_cache:
|
|
621
|
-
cmd.append(
|
|
669
|
+
cmd.append("--no-cache")
|
|
622
670
|
cmd.append(package_info.build_dir)
|
|
623
671
|
|
|
624
672
|
quiet_mode = os.getenv("AGENTENGINE_OUTPUT_MODE", "").strip().lower() == "json"
|
|
@@ -628,16 +676,16 @@ if __name__ == "__main__":
|
|
|
628
676
|
capture_output=quiet_mode,
|
|
629
677
|
text=quiet_mode,
|
|
630
678
|
)
|
|
631
|
-
click.secho(f"\n✅ 镜像构建成功: {full_image}", fg=
|
|
632
|
-
|
|
679
|
+
click.secho(f"\n✅ 镜像构建成功: {full_image}", fg="green")
|
|
680
|
+
|
|
633
681
|
return BuildResult(
|
|
634
682
|
success=True,
|
|
635
683
|
artifact_path=None, # Docker 镜像没有本地文件路径
|
|
636
684
|
metadata={
|
|
637
685
|
"image": full_image,
|
|
638
686
|
"framework": result.type.value,
|
|
639
|
-
"build_dir": package_info.build_dir
|
|
640
|
-
}
|
|
687
|
+
"build_dir": package_info.build_dir,
|
|
688
|
+
},
|
|
641
689
|
)
|
|
642
690
|
except subprocess.CalledProcessError as e:
|
|
643
691
|
error_message = f"镜像构建失败: {e}"
|
|
@@ -647,138 +695,130 @@ if __name__ == "__main__":
|
|
|
647
695
|
detail = stderr or stdout
|
|
648
696
|
if detail:
|
|
649
697
|
error_message = f"{error_message}: {detail}"
|
|
650
|
-
return BuildResult(
|
|
651
|
-
|
|
652
|
-
error_message=error_message
|
|
653
|
-
)
|
|
654
|
-
|
|
698
|
+
return BuildResult(success=False, error_message=error_message)
|
|
699
|
+
|
|
655
700
|
def push(self, image_name: str) -> bool:
|
|
656
701
|
"""推送镜像到仓库"""
|
|
657
702
|
# 检查镜像仓库认证
|
|
658
703
|
registry = self._extract_registry(image_name)
|
|
659
|
-
|
|
704
|
+
|
|
660
705
|
# 尝试使用 .env 中的认证信息自动登录
|
|
661
706
|
if registry:
|
|
662
707
|
if not self._auto_login_from_env(registry):
|
|
663
708
|
# 自动登录失败,检查是否已有认证
|
|
664
709
|
if not self._check_registry_auth(registry):
|
|
665
710
|
return False
|
|
666
|
-
|
|
667
|
-
click.echo(
|
|
711
|
+
|
|
712
|
+
click.echo("\n📤 推送镜像...")
|
|
668
713
|
try:
|
|
669
|
-
result = subprocess.run(
|
|
670
|
-
['docker', 'push', image_name],
|
|
671
|
-
capture_output=True,
|
|
672
|
-
text=True
|
|
673
|
-
)
|
|
714
|
+
result = subprocess.run(["docker", "push", image_name], capture_output=True, text=True)
|
|
674
715
|
if result.returncode != 0:
|
|
675
716
|
# 检查是否是认证问题
|
|
676
|
-
if
|
|
677
|
-
self._print_auth_help(registry or
|
|
717
|
+
if "denied" in result.stderr.lower() or "unauthorized" in result.stderr.lower():
|
|
718
|
+
self._print_auth_help(registry or "docker.io")
|
|
678
719
|
return False
|
|
679
|
-
click.secho(f"❌ 镜像推送失败: {result.stderr}", fg=
|
|
720
|
+
click.secho(f"❌ 镜像推送失败: {result.stderr}", fg="red")
|
|
680
721
|
return False
|
|
681
|
-
|
|
682
|
-
click.secho(
|
|
722
|
+
|
|
723
|
+
click.secho("✅ 镜像推送成功", fg="green")
|
|
683
724
|
return True
|
|
684
725
|
except subprocess.CalledProcessError as e:
|
|
685
|
-
click.secho(f"❌ 镜像推送失败: {e}", fg=
|
|
726
|
+
click.secho(f"❌ 镜像推送失败: {e}", fg="red")
|
|
686
727
|
return False
|
|
687
|
-
|
|
728
|
+
|
|
688
729
|
def _auto_login_from_env(self, registry: str) -> bool:
|
|
689
730
|
"""尝试使用 .env 中的凭证自动登录"""
|
|
690
731
|
import os
|
|
732
|
+
|
|
691
733
|
from dotenv import load_dotenv
|
|
692
|
-
|
|
734
|
+
|
|
693
735
|
# 加载 .env
|
|
694
736
|
load_dotenv()
|
|
695
|
-
|
|
696
|
-
# KCR_REGISTRY is
|
|
697
|
-
kcr_registry = os.getenv(
|
|
737
|
+
|
|
738
|
+
# KCR_REGISTRY is the registry/namespace target for KCR and third parties.
|
|
739
|
+
kcr_registry = os.getenv("KCR_REGISTRY", "")
|
|
698
740
|
if not kcr_registry:
|
|
699
741
|
kcr_registry = "hub.kce.ksyun.com/agentengine"
|
|
700
|
-
|
|
742
|
+
|
|
701
743
|
kcr_username, kcr_password, registry_kind = resolve_registry_credentials(registry)
|
|
702
|
-
|
|
744
|
+
|
|
703
745
|
# 检查是否匹配当前 registry (支持部分匹配)
|
|
704
746
|
if registry not in kcr_registry and kcr_registry not in registry:
|
|
705
747
|
return False
|
|
706
|
-
|
|
748
|
+
|
|
707
749
|
if not kcr_username or not kcr_password:
|
|
708
750
|
print_registry_credentials_help(registry, kind=registry_kind)
|
|
709
751
|
return False
|
|
710
|
-
|
|
752
|
+
|
|
711
753
|
click.echo(f"🔐 使用 .env 中的凭证登录 {registry}...")
|
|
712
754
|
try:
|
|
713
755
|
result = subprocess.run(
|
|
714
|
-
[
|
|
756
|
+
["docker", "login", registry, "-u", kcr_username, "--password-stdin"],
|
|
715
757
|
input=kcr_password,
|
|
716
758
|
capture_output=True,
|
|
717
759
|
text=True,
|
|
718
|
-
timeout=30
|
|
760
|
+
timeout=30,
|
|
719
761
|
)
|
|
720
762
|
if result.returncode == 0:
|
|
721
|
-
click.secho(
|
|
763
|
+
click.secho("✅ 登录成功", fg="green")
|
|
722
764
|
return True
|
|
723
765
|
else:
|
|
724
|
-
click.secho(f"⚠️ 自动登录失败: {result.stderr.strip()}", fg=
|
|
766
|
+
click.secho(f"⚠️ 自动登录失败: {result.stderr.strip()}", fg="yellow")
|
|
725
767
|
return False
|
|
726
768
|
except Exception as e:
|
|
727
|
-
click.secho(f"⚠️ 自动登录异常: {e}", fg=
|
|
769
|
+
click.secho(f"⚠️ 自动登录异常: {e}", fg="yellow")
|
|
728
770
|
return False
|
|
729
|
-
|
|
771
|
+
|
|
730
772
|
def get_registry_credentials(self, registry: str | None = None) -> dict:
|
|
731
773
|
"""获取镜像仓库凭证 (用于传给 Serverless)
|
|
732
|
-
|
|
774
|
+
|
|
733
775
|
返回扁平化结构: {"username": "...", "password": "..."}
|
|
734
776
|
"""
|
|
735
777
|
import os
|
|
778
|
+
|
|
736
779
|
from dotenv import load_dotenv
|
|
737
|
-
|
|
780
|
+
|
|
738
781
|
load_dotenv()
|
|
739
|
-
|
|
782
|
+
|
|
740
783
|
registry = registry or os.getenv("KCR_REGISTRY", "")
|
|
741
784
|
username, password, _ = resolve_registry_credentials(registry)
|
|
742
|
-
|
|
785
|
+
|
|
743
786
|
if username and password:
|
|
744
|
-
return {
|
|
745
|
-
'username': username,
|
|
746
|
-
'password': password
|
|
747
|
-
}
|
|
787
|
+
return {"username": username, "password": password}
|
|
748
788
|
return {}
|
|
749
|
-
|
|
789
|
+
|
|
750
790
|
def _extract_registry(self, image_name: str) -> Optional[str]:
|
|
751
791
|
"""从镜像名称提取仓库地址"""
|
|
752
792
|
# 格式: registry/namespace/image:tag 或 namespace/image:tag (默认 docker.io)
|
|
753
|
-
parts = image_name.split(
|
|
754
|
-
if len(parts) >= 2 and (
|
|
793
|
+
parts = image_name.split("/")
|
|
794
|
+
if len(parts) >= 2 and ("." in parts[0] or ":" in parts[0]):
|
|
755
795
|
return parts[0]
|
|
756
796
|
return None # 使用默认 docker.io
|
|
757
|
-
|
|
797
|
+
|
|
758
798
|
def _check_registry_auth(self, registry: str) -> bool:
|
|
759
799
|
"""检查是否已登录镜像仓库"""
|
|
760
800
|
try:
|
|
761
801
|
# 尝试获取 docker 配置
|
|
762
802
|
import json
|
|
763
803
|
from pathlib import Path
|
|
764
|
-
|
|
765
|
-
docker_config = Path.home() /
|
|
804
|
+
|
|
805
|
+
docker_config = Path.home() / ".docker" / "config.json"
|
|
766
806
|
if docker_config.exists():
|
|
767
807
|
with open(docker_config) as f:
|
|
768
808
|
config = json.load(f)
|
|
769
|
-
auths = config.get(
|
|
809
|
+
auths = config.get("auths", {})
|
|
770
810
|
# 检查是否有该仓库的认证信息
|
|
771
|
-
if registry in auths or f
|
|
811
|
+
if registry in auths or f"https://{registry}" in auths:
|
|
772
812
|
return True
|
|
773
|
-
|
|
813
|
+
|
|
774
814
|
# 没有找到认证信息,提示用户
|
|
775
|
-
click.secho(f"\n⚠️ 未检测到 {registry} 的登录凭证", fg=
|
|
815
|
+
click.secho(f"\n⚠️ 未检测到 {registry} 的登录凭证", fg="yellow")
|
|
776
816
|
self._print_auth_help(registry)
|
|
777
817
|
return False
|
|
778
818
|
except Exception:
|
|
779
819
|
# 无法检查,继续尝试推送
|
|
780
820
|
return True
|
|
781
|
-
|
|
821
|
+
|
|
782
822
|
def _print_auth_help(self, registry: str):
|
|
783
823
|
"""打印认证帮助信息"""
|
|
784
824
|
print_registry_credentials_help(registry)
|