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
ksadk/studio/service.py
ADDED
|
@@ -0,0 +1,1141 @@
|
|
|
1
|
+
"""Application service composing Studio modules behind one local API boundary."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Callable, Literal, cast
|
|
9
|
+
from urllib.parse import urlparse
|
|
10
|
+
|
|
11
|
+
from ksadk.evaluation import (
|
|
12
|
+
EvaluationConfig as PublicEvaluationConfig,
|
|
13
|
+
)
|
|
14
|
+
from ksadk.evaluation import (
|
|
15
|
+
EvaluationExecutionError,
|
|
16
|
+
EvaluationNotImplementedError,
|
|
17
|
+
EvaluationStorage,
|
|
18
|
+
EvaluationStorageError,
|
|
19
|
+
TargetKind,
|
|
20
|
+
TargetRef,
|
|
21
|
+
execute_evaluation,
|
|
22
|
+
load_evalset,
|
|
23
|
+
)
|
|
24
|
+
from ksadk.evaluation import (
|
|
25
|
+
EvaluationRequest as PublicEvaluationRequest,
|
|
26
|
+
)
|
|
27
|
+
from ksadk.evaluation.evalset import EvalSetParseError
|
|
28
|
+
from ksadk.runtime import RuntimeExecutor, build_default_runtime_registry
|
|
29
|
+
from ksadk.studio.agent_avatar_assets import AgentAvatarAssetStore
|
|
30
|
+
from ksadk.studio.agent_lifecycle import delete_framework_agent
|
|
31
|
+
from ksadk.studio.authoring_coordinator import StudioAuthoringCoordinator
|
|
32
|
+
from ksadk.studio.builder import AgentBundleBuilder
|
|
33
|
+
from ksadk.studio.capabilities import builtin_tool_contracts
|
|
34
|
+
from ksadk.studio.cloud import (
|
|
35
|
+
CloudDeploymentGateway,
|
|
36
|
+
CloudDeploymentService,
|
|
37
|
+
UnavailableCloudGateway,
|
|
38
|
+
)
|
|
39
|
+
from ksadk.studio.codex_agent_service import CodexAgentService, CodexDraftRepository
|
|
40
|
+
from ksadk.studio.codex_builder import (
|
|
41
|
+
CodexBuildRecord,
|
|
42
|
+
CodexBuildRepository,
|
|
43
|
+
CodexStudioBuilder,
|
|
44
|
+
RuntimeInspector,
|
|
45
|
+
)
|
|
46
|
+
from ksadk.studio.codex_manifest import (
|
|
47
|
+
CodexAgentManifest,
|
|
48
|
+
CodexManifestRepository,
|
|
49
|
+
)
|
|
50
|
+
from ksadk.studio.codex_run import CodexRunSpecResolver
|
|
51
|
+
from ksadk.studio.compiler import AgentCompiler
|
|
52
|
+
from ksadk.studio.contracts import (
|
|
53
|
+
AgentAppearance,
|
|
54
|
+
AgentBindings,
|
|
55
|
+
AgentDraft,
|
|
56
|
+
AgentSpec,
|
|
57
|
+
AgentTemplateComposeRequest,
|
|
58
|
+
AgentTemplateComposition,
|
|
59
|
+
DeploymentRequest,
|
|
60
|
+
Operation,
|
|
61
|
+
OperationKind,
|
|
62
|
+
RunEvent,
|
|
63
|
+
RunStatus,
|
|
64
|
+
RuntimeRef,
|
|
65
|
+
)
|
|
66
|
+
from ksadk.studio.errors import StudioError
|
|
67
|
+
from ksadk.studio.evaluation import EvaluationRunner
|
|
68
|
+
from ksadk.studio.event_store import RunEventStore
|
|
69
|
+
from ksadk.studio.framework_run import FrameworkRunSpecResolver
|
|
70
|
+
from ksadk.studio.mcp_runtime import MCPRuntimeAdapter
|
|
71
|
+
from ksadk.studio.model_client import CredentialResolver, OpenAICompatibleModelClient
|
|
72
|
+
from ksadk.studio.model_profile_service import test_model_profile_connection
|
|
73
|
+
from ksadk.studio.operations import OperationManager
|
|
74
|
+
from ksadk.studio.repository import AgentDraftRepository, BuildRepository, load_yaml_file
|
|
75
|
+
from ksadk.studio.resource_catalog import LocalResourceCatalog
|
|
76
|
+
from ksadk.studio.run_service import StudioRunService
|
|
77
|
+
from ksadk.studio.runtime_catalog import inspect_runtime_catalog
|
|
78
|
+
from ksadk.studio.runtime_source import materialize_generated_runtime_source
|
|
79
|
+
from ksadk.studio.templates import (
|
|
80
|
+
compose_blank_agent,
|
|
81
|
+
compose_research_agent,
|
|
82
|
+
default_agent_spec,
|
|
83
|
+
list_agent_templates,
|
|
84
|
+
)
|
|
85
|
+
from ksadk.studio.validator import AgentValidator
|
|
86
|
+
from ksadk.studio.workspace import Workspace
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class StudioService:
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
root: Path | str,
|
|
93
|
+
*,
|
|
94
|
+
model_client: OpenAICompatibleModelClient | None = None,
|
|
95
|
+
credential_resolver: CredentialResolver | None = None,
|
|
96
|
+
cloud_gateway: CloudDeploymentGateway | None = None,
|
|
97
|
+
codex_runtime_inspector: RuntimeInspector | None = None,
|
|
98
|
+
runtime_executor: RuntimeExecutor | None = None,
|
|
99
|
+
) -> None:
|
|
100
|
+
self.workspace = Workspace(root)
|
|
101
|
+
self.workspace.initialize()
|
|
102
|
+
self._apply_persisted_settings()
|
|
103
|
+
self.avatar_assets = AgentAvatarAssetStore(self.workspace)
|
|
104
|
+
self.drafts = AgentDraftRepository(self.workspace)
|
|
105
|
+
self.catalog = LocalResourceCatalog(self.workspace)
|
|
106
|
+
self.builds = BuildRepository(self.workspace)
|
|
107
|
+
self.validator = AgentValidator()
|
|
108
|
+
self.builder = AgentBundleBuilder(
|
|
109
|
+
self.workspace,
|
|
110
|
+
compiler=AgentCompiler(
|
|
111
|
+
self.workspace,
|
|
112
|
+
validator=self.validator,
|
|
113
|
+
catalog=self.catalog,
|
|
114
|
+
),
|
|
115
|
+
repository=self.builds,
|
|
116
|
+
)
|
|
117
|
+
self.event_store = RunEventStore(self.workspace)
|
|
118
|
+
self.event_store.recover_interrupted()
|
|
119
|
+
self.codex_manifests = CodexManifestRepository(self.workspace)
|
|
120
|
+
self.codex_builds = CodexBuildRepository(self.workspace)
|
|
121
|
+
self.codex_drafts = CodexDraftRepository(self.workspace)
|
|
122
|
+
codex_builder_kwargs = {}
|
|
123
|
+
if codex_runtime_inspector is not None:
|
|
124
|
+
codex_builder_kwargs["runtime_inspector"] = codex_runtime_inspector
|
|
125
|
+
self.codex_builder = CodexStudioBuilder(
|
|
126
|
+
self.workspace,
|
|
127
|
+
manifest_repository=self.codex_manifests,
|
|
128
|
+
build_repository=self.codex_builds,
|
|
129
|
+
resource_catalog=self.catalog,
|
|
130
|
+
draft_repository=self.codex_drafts,
|
|
131
|
+
**codex_builder_kwargs,
|
|
132
|
+
)
|
|
133
|
+
self.runtime_executor = runtime_executor or RuntimeExecutor(
|
|
134
|
+
build_default_runtime_registry()
|
|
135
|
+
)
|
|
136
|
+
self.run_service = StudioRunService(
|
|
137
|
+
self.workspace,
|
|
138
|
+
self.runtime_executor,
|
|
139
|
+
event_store=self.event_store,
|
|
140
|
+
)
|
|
141
|
+
self.credentials = (
|
|
142
|
+
credential_resolver
|
|
143
|
+
or getattr(model_client, "credential_resolver", None)
|
|
144
|
+
or CredentialResolver(self.workspace)
|
|
145
|
+
)
|
|
146
|
+
self.codex_runs = CodexRunSpecResolver(
|
|
147
|
+
self.workspace,
|
|
148
|
+
build_repository=self.codex_builds,
|
|
149
|
+
manifest_repository=self.codex_manifests,
|
|
150
|
+
credential_resolver=self.credentials,
|
|
151
|
+
resource_catalog=self.catalog,
|
|
152
|
+
)
|
|
153
|
+
self.framework_runs = FrameworkRunSpecResolver(
|
|
154
|
+
self.workspace,
|
|
155
|
+
build_repository=self.builds,
|
|
156
|
+
)
|
|
157
|
+
runtime_model_client = model_client or OpenAICompatibleModelClient(
|
|
158
|
+
credential_resolver=self.credentials
|
|
159
|
+
)
|
|
160
|
+
self.model_client = runtime_model_client
|
|
161
|
+
self.mcp_runtime = MCPRuntimeAdapter(self.workspace, credentials=self.credentials)
|
|
162
|
+
self.evaluations = EvaluationRunner(
|
|
163
|
+
self.workspace,
|
|
164
|
+
run_agent=self.run_build,
|
|
165
|
+
event_store=self.event_store,
|
|
166
|
+
build_repository=self.builds,
|
|
167
|
+
)
|
|
168
|
+
self.cloud = CloudDeploymentService(
|
|
169
|
+
self.workspace,
|
|
170
|
+
gateway=cloud_gateway or UnavailableCloudGateway(),
|
|
171
|
+
build_repository=self.builds,
|
|
172
|
+
)
|
|
173
|
+
self.operations = OperationManager(self.workspace)
|
|
174
|
+
self.evaluation_storage = EvaluationStorage(
|
|
175
|
+
self.workspace.resolve(".agentkit/evaluations")
|
|
176
|
+
)
|
|
177
|
+
self.authoring = StudioAuthoringCoordinator(self)
|
|
178
|
+
self.codex_agents = CodexAgentService(self)
|
|
179
|
+
|
|
180
|
+
def runtime_catalog(self) -> list[dict]:
|
|
181
|
+
return inspect_runtime_catalog(self.runtime_executor)
|
|
182
|
+
|
|
183
|
+
def codex_manifest_state(self, agent_id: str | None = None) -> dict:
|
|
184
|
+
return self.codex_agents.manifest_state(agent_id)
|
|
185
|
+
|
|
186
|
+
def save_codex_manifest(self, manifest: CodexAgentManifest) -> dict:
|
|
187
|
+
return self.codex_agents.save_manifest(manifest)
|
|
188
|
+
|
|
189
|
+
def list_codex_agents(self, *, query: str = "", limit: int = 50) -> list[AgentDraft]:
|
|
190
|
+
return self.codex_agents.list(query=query, limit=limit)
|
|
191
|
+
|
|
192
|
+
def create_codex_agent(
|
|
193
|
+
self,
|
|
194
|
+
*,
|
|
195
|
+
agent_id: str,
|
|
196
|
+
spec: AgentSpec | None,
|
|
197
|
+
name: str | None = None,
|
|
198
|
+
labels: dict[str, str] | None = None,
|
|
199
|
+
) -> AgentDraft:
|
|
200
|
+
return self.codex_agents.create(
|
|
201
|
+
agent_id=agent_id,
|
|
202
|
+
spec=spec,
|
|
203
|
+
name=name,
|
|
204
|
+
labels=labels,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
def update_codex_agent(
|
|
208
|
+
self,
|
|
209
|
+
agent_id: str,
|
|
210
|
+
spec: AgentSpec,
|
|
211
|
+
*,
|
|
212
|
+
expected_revision: int,
|
|
213
|
+
) -> AgentDraft:
|
|
214
|
+
return self.codex_agents.update(
|
|
215
|
+
agent_id,
|
|
216
|
+
spec,
|
|
217
|
+
expected_revision=expected_revision,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def delete_codex_agent(self, agent_id: str, *, purge: bool = False) -> None:
|
|
221
|
+
self.codex_agents.delete(agent_id, purge=purge)
|
|
222
|
+
|
|
223
|
+
def codex_agent_detail(self, agent_id: str | None = None) -> dict:
|
|
224
|
+
return self.codex_agents.detail(agent_id)
|
|
225
|
+
|
|
226
|
+
@staticmethod
|
|
227
|
+
def codex_build_view(record: CodexBuildRecord) -> dict:
|
|
228
|
+
return CodexAgentService.build_view(record)
|
|
229
|
+
|
|
230
|
+
def submit_codex_build(
|
|
231
|
+
self,
|
|
232
|
+
*,
|
|
233
|
+
idempotency_key: str,
|
|
234
|
+
agent_id: str | None = None,
|
|
235
|
+
) -> Operation:
|
|
236
|
+
return self.codex_agents.submit_build(
|
|
237
|
+
idempotency_key=idempotency_key,
|
|
238
|
+
agent_id=agent_id,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
def submit_codex_run(
|
|
242
|
+
self,
|
|
243
|
+
build_id: str,
|
|
244
|
+
user_input: str,
|
|
245
|
+
*,
|
|
246
|
+
session_id: str | None,
|
|
247
|
+
model: str | None = None,
|
|
248
|
+
sandbox: str | None = None,
|
|
249
|
+
approval_mode: str | None = None,
|
|
250
|
+
collaboration_mode: str | None = None,
|
|
251
|
+
goal_objective: str | None = None,
|
|
252
|
+
runtime_input: Any = None,
|
|
253
|
+
idempotency_key: str,
|
|
254
|
+
on_event: Callable[[RunEvent], None] | None = None,
|
|
255
|
+
) -> Operation:
|
|
256
|
+
return self.codex_agents.submit_run(
|
|
257
|
+
build_id,
|
|
258
|
+
user_input,
|
|
259
|
+
session_id=session_id,
|
|
260
|
+
model=model,
|
|
261
|
+
sandbox=sandbox,
|
|
262
|
+
approval_mode=approval_mode,
|
|
263
|
+
collaboration_mode=collaboration_mode,
|
|
264
|
+
goal_objective=goal_objective,
|
|
265
|
+
runtime_input=runtime_input,
|
|
266
|
+
idempotency_key=idempotency_key,
|
|
267
|
+
on_event=on_event,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
def delete_session(self, session_id: str) -> None:
|
|
271
|
+
from ksadk.studio.errors import not_found
|
|
272
|
+
|
|
273
|
+
runs = self.event_store.list_runs(session_id=session_id)
|
|
274
|
+
if not runs:
|
|
275
|
+
raise not_found("session", session_id)
|
|
276
|
+
if any(run.status == RunStatus.RUNNING for run in runs):
|
|
277
|
+
raise StudioError(
|
|
278
|
+
"SESSION_RUN_ACTIVE",
|
|
279
|
+
"会话仍在运行,请先停止运行后再删除",
|
|
280
|
+
status_code=409,
|
|
281
|
+
details={"sessionId": session_id},
|
|
282
|
+
)
|
|
283
|
+
self.event_store.delete_session(session_id)
|
|
284
|
+
|
|
285
|
+
async def test_model_profile(self, resource_id: str) -> dict:
|
|
286
|
+
return await test_model_profile_connection(
|
|
287
|
+
catalog=self.catalog,
|
|
288
|
+
model_client=self.model_client,
|
|
289
|
+
resource_id=resource_id,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
def create_agent(
|
|
293
|
+
self,
|
|
294
|
+
*,
|
|
295
|
+
agent_id: str,
|
|
296
|
+
name: str,
|
|
297
|
+
description: str = "",
|
|
298
|
+
template: str = "blank",
|
|
299
|
+
spec: AgentSpec | None = None,
|
|
300
|
+
labels: dict[str, str] | None = None,
|
|
301
|
+
):
|
|
302
|
+
if self.codex_manifests.exists(agent_id):
|
|
303
|
+
from ksadk.studio.errors import StudioError
|
|
304
|
+
|
|
305
|
+
raise StudioError(
|
|
306
|
+
"AGENT_ALREADY_EXISTS",
|
|
307
|
+
"Agent ID 已存在",
|
|
308
|
+
status_code=409,
|
|
309
|
+
details={"id": agent_id},
|
|
310
|
+
)
|
|
311
|
+
resolved_spec = spec or default_agent_spec(
|
|
312
|
+
template,
|
|
313
|
+
description=description,
|
|
314
|
+
)
|
|
315
|
+
self._validate_bindings(resolved_spec.bindings)
|
|
316
|
+
draft = self.drafts.create(
|
|
317
|
+
agent_id=agent_id,
|
|
318
|
+
name=name,
|
|
319
|
+
description=description,
|
|
320
|
+
template=template,
|
|
321
|
+
spec=resolved_spec,
|
|
322
|
+
labels=labels,
|
|
323
|
+
)
|
|
324
|
+
materialize_generated_runtime_source(self.workspace, draft)
|
|
325
|
+
return draft
|
|
326
|
+
|
|
327
|
+
def create_authored_agent(
|
|
328
|
+
self,
|
|
329
|
+
*,
|
|
330
|
+
name: str,
|
|
331
|
+
slug: str | None = None,
|
|
332
|
+
runtime_type: str,
|
|
333
|
+
template: str = "blank",
|
|
334
|
+
description: str = "",
|
|
335
|
+
spec: AgentSpec | None = None,
|
|
336
|
+
) -> AgentDraft:
|
|
337
|
+
return self.authoring.create(
|
|
338
|
+
name=name,
|
|
339
|
+
slug=slug,
|
|
340
|
+
runtime_type=runtime_type,
|
|
341
|
+
description=description,
|
|
342
|
+
template=template,
|
|
343
|
+
spec=spec,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
def inspect_agent_import(self, content: bytes, *, filename: str) -> dict:
|
|
347
|
+
return self.authoring.inspect_import(content, filename=filename)
|
|
348
|
+
|
|
349
|
+
def commit_agent_import(
|
|
350
|
+
self,
|
|
351
|
+
inspection_token: str,
|
|
352
|
+
*,
|
|
353
|
+
name: str | None = None,
|
|
354
|
+
slug: str | None = None,
|
|
355
|
+
) -> AgentDraft:
|
|
356
|
+
return self.authoring.commit_import(
|
|
357
|
+
inspection_token,
|
|
358
|
+
name=name,
|
|
359
|
+
slug=slug,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
def inspect_agent_project(self, project_path: str) -> dict:
|
|
363
|
+
return self.authoring.inspect_project(project_path)
|
|
364
|
+
|
|
365
|
+
def commit_agent_project(
|
|
366
|
+
self,
|
|
367
|
+
inspection_token: str,
|
|
368
|
+
*,
|
|
369
|
+
name: str | None = None,
|
|
370
|
+
slug: str | None = None,
|
|
371
|
+
model_profile_id: str | None = None,
|
|
372
|
+
) -> AgentDraft:
|
|
373
|
+
return self.authoring.commit_project(
|
|
374
|
+
inspection_token,
|
|
375
|
+
name=name,
|
|
376
|
+
slug=slug,
|
|
377
|
+
model_profile_id=model_profile_id,
|
|
378
|
+
)
|
|
379
|
+
|
|
380
|
+
async def compose_agent_conversation(
|
|
381
|
+
self,
|
|
382
|
+
*,
|
|
383
|
+
messages: list[dict[str, str]],
|
|
384
|
+
model_profile_id: str,
|
|
385
|
+
) -> dict:
|
|
386
|
+
return await self.authoring.compose_conversation(
|
|
387
|
+
messages=messages,
|
|
388
|
+
model_profile_id=model_profile_id,
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
def is_codex_agent(self, agent_id: str) -> bool:
|
|
392
|
+
"""Return whether one Agent is backed by the Codex YAML contract."""
|
|
393
|
+
|
|
394
|
+
return self.codex_manifests.exists(agent_id)
|
|
395
|
+
|
|
396
|
+
def agent_runtime_type(self, agent_id: str) -> str:
|
|
397
|
+
"""Resolve runtime from the Agent itself, never from Studio process state."""
|
|
398
|
+
|
|
399
|
+
if self.is_codex_agent(agent_id):
|
|
400
|
+
return "codex"
|
|
401
|
+
draft = self.drafts.get(agent_id)
|
|
402
|
+
runtime = draft.spec.runtime
|
|
403
|
+
if runtime is None:
|
|
404
|
+
# Read compatibility for Agent drafts written before RuntimeRef existed.
|
|
405
|
+
framework = draft.metadata.labels.get("agentkit.ksyun.com/framework", "")
|
|
406
|
+
return framework.strip().lower() or "adk"
|
|
407
|
+
return runtime.type
|
|
408
|
+
|
|
409
|
+
def list_agents(self, *, query: str = "", limit: int = 50) -> list[AgentDraft]:
|
|
410
|
+
"""List all local Agents from one registry view across runtime types."""
|
|
411
|
+
|
|
412
|
+
if limit < 1:
|
|
413
|
+
return []
|
|
414
|
+
normalized = query.strip().lower()
|
|
415
|
+
combined: dict[str, AgentDraft] = {
|
|
416
|
+
draft.metadata.id: draft for draft in self.list_codex_agents(query=query, limit=limit)
|
|
417
|
+
}
|
|
418
|
+
for draft in self.drafts.list(query=query, limit=limit):
|
|
419
|
+
combined.setdefault(draft.metadata.id, draft)
|
|
420
|
+
values = list(combined.values())
|
|
421
|
+
if normalized:
|
|
422
|
+
values = [
|
|
423
|
+
item
|
|
424
|
+
for item in values
|
|
425
|
+
if normalized in item.metadata.id.lower()
|
|
426
|
+
or normalized in item.metadata.name.lower()
|
|
427
|
+
]
|
|
428
|
+
return values[:limit]
|
|
429
|
+
|
|
430
|
+
def agent_detail(self, agent_id: str) -> dict:
|
|
431
|
+
if self.is_codex_agent(agent_id):
|
|
432
|
+
return self.codex_agent_detail(agent_id)
|
|
433
|
+
draft = self.drafts.get(agent_id)
|
|
434
|
+
return {
|
|
435
|
+
"draft": draft,
|
|
436
|
+
"builds": self.builds.list_for_agent(agent_id)[:10],
|
|
437
|
+
"validation": self.validator.validate(draft),
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
def create_studio_agent(
|
|
441
|
+
self,
|
|
442
|
+
*,
|
|
443
|
+
agent_id: str,
|
|
444
|
+
name: str,
|
|
445
|
+
description: str = "",
|
|
446
|
+
template: str = "blank",
|
|
447
|
+
spec: AgentSpec | None = None,
|
|
448
|
+
runtime: RuntimeRef | None = None,
|
|
449
|
+
labels: dict[str, str] | None = None,
|
|
450
|
+
) -> AgentDraft:
|
|
451
|
+
"""Create one Agent and dispatch from its RuntimeRef."""
|
|
452
|
+
|
|
453
|
+
resolved_spec = (spec or default_agent_spec(template, description=description)).model_copy(
|
|
454
|
+
deep=True
|
|
455
|
+
)
|
|
456
|
+
selected = runtime or resolved_spec.runtime
|
|
457
|
+
resolved_spec.runtime = selected
|
|
458
|
+
if selected is not None and selected.type == "codex":
|
|
459
|
+
return cast(
|
|
460
|
+
AgentDraft,
|
|
461
|
+
self.create_codex_agent(
|
|
462
|
+
agent_id=agent_id,
|
|
463
|
+
spec=resolved_spec,
|
|
464
|
+
name=name,
|
|
465
|
+
labels=labels,
|
|
466
|
+
),
|
|
467
|
+
)
|
|
468
|
+
return cast(
|
|
469
|
+
AgentDraft,
|
|
470
|
+
self.create_agent(
|
|
471
|
+
agent_id=agent_id,
|
|
472
|
+
name=name,
|
|
473
|
+
description=description,
|
|
474
|
+
template=template,
|
|
475
|
+
spec=resolved_spec,
|
|
476
|
+
labels=labels,
|
|
477
|
+
),
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
def update_studio_agent(
|
|
481
|
+
self,
|
|
482
|
+
agent_id: str,
|
|
483
|
+
spec: AgentSpec,
|
|
484
|
+
*,
|
|
485
|
+
expected_revision: int,
|
|
486
|
+
) -> AgentDraft:
|
|
487
|
+
if self.is_codex_agent(agent_id):
|
|
488
|
+
spec.runtime = self.agent_detail(agent_id)["draft"].spec.runtime
|
|
489
|
+
return cast(
|
|
490
|
+
AgentDraft,
|
|
491
|
+
self.update_codex_agent(
|
|
492
|
+
agent_id,
|
|
493
|
+
spec,
|
|
494
|
+
expected_revision=expected_revision,
|
|
495
|
+
),
|
|
496
|
+
)
|
|
497
|
+
current = self.drafts.get(agent_id)
|
|
498
|
+
if spec.runtime is None:
|
|
499
|
+
spec.runtime = current.spec.runtime
|
|
500
|
+
elif current.spec.runtime is not None and spec.runtime.type != current.spec.runtime.type:
|
|
501
|
+
from ksadk.studio.errors import StudioError
|
|
502
|
+
|
|
503
|
+
raise StudioError(
|
|
504
|
+
"AGENT_RUNTIME_IMMUTABLE",
|
|
505
|
+
"编辑 Agent 时不能直接切换 Runtime;请通过导入/迁移创建新 Agent",
|
|
506
|
+
status_code=422,
|
|
507
|
+
field="runtime.type",
|
|
508
|
+
)
|
|
509
|
+
return cast(
|
|
510
|
+
AgentDraft,
|
|
511
|
+
self.update_agent(agent_id, spec, expected_revision=expected_revision),
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
def update_studio_agent_bindings(
|
|
515
|
+
self,
|
|
516
|
+
agent_id: str,
|
|
517
|
+
bindings: AgentBindings,
|
|
518
|
+
*,
|
|
519
|
+
expected_revision: int,
|
|
520
|
+
) -> AgentDraft:
|
|
521
|
+
detail = self.agent_detail(agent_id)
|
|
522
|
+
spec = detail["draft"].spec.model_copy(deep=True)
|
|
523
|
+
spec.bindings = bindings
|
|
524
|
+
return self.update_studio_agent(
|
|
525
|
+
agent_id,
|
|
526
|
+
spec,
|
|
527
|
+
expected_revision=expected_revision,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
def update_studio_agent_appearance(
|
|
531
|
+
self,
|
|
532
|
+
agent_id: str,
|
|
533
|
+
appearance: AgentAppearance,
|
|
534
|
+
*,
|
|
535
|
+
expected_revision: int,
|
|
536
|
+
) -> AgentDraft:
|
|
537
|
+
if self.is_codex_agent(agent_id):
|
|
538
|
+
return self.codex_agents.update_appearance(
|
|
539
|
+
agent_id,
|
|
540
|
+
appearance,
|
|
541
|
+
expected_revision=expected_revision,
|
|
542
|
+
)
|
|
543
|
+
return self.drafts.update_appearance(
|
|
544
|
+
agent_id,
|
|
545
|
+
appearance,
|
|
546
|
+
expected_revision=expected_revision,
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
def delete_studio_agent(self, agent_id: str, *, purge: bool = False) -> None:
|
|
550
|
+
if self.is_codex_agent(agent_id):
|
|
551
|
+
self.delete_codex_agent(agent_id, purge=purge)
|
|
552
|
+
return
|
|
553
|
+
delete_framework_agent(self, agent_id, purge=purge)
|
|
554
|
+
|
|
555
|
+
def validate_studio_agent(
|
|
556
|
+
self,
|
|
557
|
+
agent_id: str,
|
|
558
|
+
*,
|
|
559
|
+
revision: int,
|
|
560
|
+
level: Literal["schema", "build", "release"] = "build",
|
|
561
|
+
):
|
|
562
|
+
detail = self.agent_detail(agent_id)
|
|
563
|
+
draft = detail["draft"]
|
|
564
|
+
if draft.metadata.revision != revision:
|
|
565
|
+
from ksadk.studio.errors import StudioError
|
|
566
|
+
|
|
567
|
+
raise StudioError(
|
|
568
|
+
"AGENT_REVISION_CONFLICT",
|
|
569
|
+
"Validation revision 与当前 Agent 不一致",
|
|
570
|
+
status_code=409,
|
|
571
|
+
)
|
|
572
|
+
if self.is_codex_agent(agent_id):
|
|
573
|
+
return detail["validation"]
|
|
574
|
+
return self.validator.validate(draft, level=level)
|
|
575
|
+
|
|
576
|
+
def submit_studio_build(
|
|
577
|
+
self,
|
|
578
|
+
agent_id: str,
|
|
579
|
+
*,
|
|
580
|
+
revision: int,
|
|
581
|
+
idempotency_key: str,
|
|
582
|
+
) -> Operation:
|
|
583
|
+
runtime_type = self.agent_runtime_type(agent_id)
|
|
584
|
+
runtime = next(
|
|
585
|
+
(item for item in self.runtime_catalog() if item["runtimeType"] == runtime_type),
|
|
586
|
+
None,
|
|
587
|
+
)
|
|
588
|
+
if runtime is None:
|
|
589
|
+
from ksadk.studio.errors import StudioError
|
|
590
|
+
|
|
591
|
+
raise StudioError(
|
|
592
|
+
"RUNTIME_NOT_REGISTERED",
|
|
593
|
+
"Agent 引用的 RuntimeAdapter 未注册",
|
|
594
|
+
status_code=422,
|
|
595
|
+
details={"runtimeType": runtime_type},
|
|
596
|
+
)
|
|
597
|
+
if runtime["status"] != "ready":
|
|
598
|
+
from ksadk.studio.errors import StudioError
|
|
599
|
+
|
|
600
|
+
raise StudioError(
|
|
601
|
+
"RUNTIME_DEPENDENCY_MISSING",
|
|
602
|
+
f"{runtime['displayName']} Runtime 依赖未安装",
|
|
603
|
+
status_code=422,
|
|
604
|
+
details={
|
|
605
|
+
"runtimeType": runtime_type,
|
|
606
|
+
"installCommand": runtime["installCommand"],
|
|
607
|
+
},
|
|
608
|
+
)
|
|
609
|
+
if self.is_codex_agent(agent_id):
|
|
610
|
+
detail = self.agent_detail(agent_id)
|
|
611
|
+
if revision != detail["draft"].metadata.revision:
|
|
612
|
+
from ksadk.studio.errors import StudioError
|
|
613
|
+
|
|
614
|
+
raise StudioError(
|
|
615
|
+
"AGENT_REVISION_CONFLICT",
|
|
616
|
+
"Build revision 与当前 Agent 不一致",
|
|
617
|
+
status_code=409,
|
|
618
|
+
)
|
|
619
|
+
return self.submit_codex_build(
|
|
620
|
+
idempotency_key=idempotency_key,
|
|
621
|
+
agent_id=agent_id,
|
|
622
|
+
)
|
|
623
|
+
return self.submit_build(
|
|
624
|
+
agent_id,
|
|
625
|
+
revision=revision,
|
|
626
|
+
idempotency_key=idempotency_key,
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
def build_view(self, build_id: str):
|
|
630
|
+
try:
|
|
631
|
+
return self.codex_build_view(self.codex_builds.get(build_id))
|
|
632
|
+
except Exception as exc: # repository not-found is the only fallback contract
|
|
633
|
+
if getattr(exc, "status_code", None) != 404:
|
|
634
|
+
raise
|
|
635
|
+
return self.builds.get(build_id)
|
|
636
|
+
|
|
637
|
+
def submit_studio_run(
|
|
638
|
+
self,
|
|
639
|
+
build_id: str,
|
|
640
|
+
user_input: str,
|
|
641
|
+
*,
|
|
642
|
+
session_id: str | None,
|
|
643
|
+
model: str | None,
|
|
644
|
+
idempotency_key: str,
|
|
645
|
+
sandbox: str | None = None,
|
|
646
|
+
approval_mode: str | None = None,
|
|
647
|
+
collaboration_mode: str | None = None,
|
|
648
|
+
goal_objective: str | None = None,
|
|
649
|
+
runtime_input: Any = None,
|
|
650
|
+
on_event: Callable[[RunEvent], None] | None = None,
|
|
651
|
+
) -> Operation:
|
|
652
|
+
try:
|
|
653
|
+
self.codex_builds.get(build_id)
|
|
654
|
+
except Exception as exc:
|
|
655
|
+
if getattr(exc, "status_code", None) != 404:
|
|
656
|
+
raise
|
|
657
|
+
else:
|
|
658
|
+
return self.submit_codex_run(
|
|
659
|
+
build_id,
|
|
660
|
+
user_input,
|
|
661
|
+
session_id=session_id,
|
|
662
|
+
model=model,
|
|
663
|
+
sandbox=sandbox,
|
|
664
|
+
approval_mode=approval_mode,
|
|
665
|
+
collaboration_mode=collaboration_mode,
|
|
666
|
+
goal_objective=goal_objective,
|
|
667
|
+
runtime_input=runtime_input,
|
|
668
|
+
idempotency_key=idempotency_key,
|
|
669
|
+
on_event=on_event,
|
|
670
|
+
)
|
|
671
|
+
return self.submit_run(
|
|
672
|
+
build_id,
|
|
673
|
+
user_input,
|
|
674
|
+
session_id=session_id,
|
|
675
|
+
model=model,
|
|
676
|
+
sandbox=sandbox,
|
|
677
|
+
approval_mode=approval_mode,
|
|
678
|
+
collaboration_mode=collaboration_mode,
|
|
679
|
+
goal_objective=goal_objective,
|
|
680
|
+
runtime_input=runtime_input,
|
|
681
|
+
idempotency_key=idempotency_key,
|
|
682
|
+
on_event=on_event,
|
|
683
|
+
)
|
|
684
|
+
|
|
685
|
+
def _draft_exists(self, agent_id: str) -> bool:
|
|
686
|
+
try:
|
|
687
|
+
self.drafts.get(agent_id)
|
|
688
|
+
except Exception as exc:
|
|
689
|
+
if getattr(exc, "status_code", None) == 404:
|
|
690
|
+
return False
|
|
691
|
+
raise
|
|
692
|
+
return True
|
|
693
|
+
|
|
694
|
+
@staticmethod
|
|
695
|
+
def list_agent_templates() -> list[dict]:
|
|
696
|
+
return list_agent_templates()
|
|
697
|
+
|
|
698
|
+
def compose_agent_template(
|
|
699
|
+
self,
|
|
700
|
+
template_id: str,
|
|
701
|
+
request: AgentTemplateComposeRequest,
|
|
702
|
+
) -> AgentTemplateComposition:
|
|
703
|
+
composers = {
|
|
704
|
+
"blank": compose_blank_agent,
|
|
705
|
+
"research": compose_research_agent,
|
|
706
|
+
}
|
|
707
|
+
composer = composers.get(template_id)
|
|
708
|
+
if composer is None:
|
|
709
|
+
from ksadk.studio.errors import StudioError
|
|
710
|
+
|
|
711
|
+
raise StudioError(
|
|
712
|
+
"AGENT_TEMPLATE_UNSUPPORTED",
|
|
713
|
+
"当前模板不支持自动编排",
|
|
714
|
+
status_code=422,
|
|
715
|
+
field="templateId",
|
|
716
|
+
details={"templateId": template_id},
|
|
717
|
+
)
|
|
718
|
+
composition = composer(self.workspace, self.catalog, request)
|
|
719
|
+
self._validate_bindings(composition.spec.bindings)
|
|
720
|
+
return composition
|
|
721
|
+
|
|
722
|
+
def update_agent(
|
|
723
|
+
self,
|
|
724
|
+
agent_id: str,
|
|
725
|
+
spec: AgentSpec,
|
|
726
|
+
*,
|
|
727
|
+
expected_revision: int,
|
|
728
|
+
):
|
|
729
|
+
self._validate_bindings(spec.bindings)
|
|
730
|
+
updated = self.drafts.update(
|
|
731
|
+
agent_id,
|
|
732
|
+
spec,
|
|
733
|
+
expected_revision=expected_revision,
|
|
734
|
+
)
|
|
735
|
+
materialize_generated_runtime_source(self.workspace, updated)
|
|
736
|
+
return updated
|
|
737
|
+
|
|
738
|
+
def update_agent_bindings(
|
|
739
|
+
self,
|
|
740
|
+
agent_id: str,
|
|
741
|
+
bindings: AgentBindings,
|
|
742
|
+
*,
|
|
743
|
+
expected_revision: int,
|
|
744
|
+
):
|
|
745
|
+
self._validate_bindings(bindings)
|
|
746
|
+
draft = self.drafts.get(agent_id)
|
|
747
|
+
spec = draft.spec.model_copy(deep=True)
|
|
748
|
+
spec.bindings = bindings
|
|
749
|
+
return self.drafts.update(
|
|
750
|
+
agent_id,
|
|
751
|
+
spec,
|
|
752
|
+
expected_revision=expected_revision,
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
def _validate_bindings(self, bindings: AgentBindings) -> None:
|
|
756
|
+
self.catalog.resolve_model(bindings)
|
|
757
|
+
self.catalog.resolve_models(bindings)
|
|
758
|
+
self.catalog.policy_preview(bindings)
|
|
759
|
+
self.catalog.resolve_mcp_servers(bindings)
|
|
760
|
+
self.catalog.resolve_mcp_tools(bindings)
|
|
761
|
+
self.catalog.resolve_skills(bindings)
|
|
762
|
+
|
|
763
|
+
def validate_agent(
|
|
764
|
+
self,
|
|
765
|
+
agent_id: str,
|
|
766
|
+
*,
|
|
767
|
+
level: Literal["schema", "build", "release"] = "build",
|
|
768
|
+
):
|
|
769
|
+
return self.validator.validate(self.drafts.get(agent_id), level=level)
|
|
770
|
+
|
|
771
|
+
def submit_build(
|
|
772
|
+
self,
|
|
773
|
+
agent_id: str,
|
|
774
|
+
*,
|
|
775
|
+
revision: int,
|
|
776
|
+
idempotency_key: str,
|
|
777
|
+
) -> Operation:
|
|
778
|
+
draft = self.drafts.get(agent_id)
|
|
779
|
+
if draft.metadata.revision != revision:
|
|
780
|
+
from ksadk.studio.errors import StudioError
|
|
781
|
+
|
|
782
|
+
raise StudioError(
|
|
783
|
+
"AGENT_REVISION_CONFLICT",
|
|
784
|
+
"Build revision 与当前 Agent 不一致",
|
|
785
|
+
status_code=409,
|
|
786
|
+
details={"expected": revision, "actual": draft.metadata.revision},
|
|
787
|
+
)
|
|
788
|
+
snapshot = draft.model_copy(deep=True)
|
|
789
|
+
|
|
790
|
+
async def runner():
|
|
791
|
+
return await asyncio.to_thread(self.builder.build, snapshot)
|
|
792
|
+
|
|
793
|
+
return self.operations.submit(
|
|
794
|
+
kind=OperationKind.BUILD,
|
|
795
|
+
resource_id=agent_id,
|
|
796
|
+
idempotency_key=idempotency_key,
|
|
797
|
+
runner=runner,
|
|
798
|
+
)
|
|
799
|
+
|
|
800
|
+
def submit_run(
|
|
801
|
+
self,
|
|
802
|
+
build_id: str,
|
|
803
|
+
user_input: str,
|
|
804
|
+
*,
|
|
805
|
+
session_id: str | None,
|
|
806
|
+
model: str | None = None,
|
|
807
|
+
sandbox: str | None = None,
|
|
808
|
+
approval_mode: str | None = None,
|
|
809
|
+
collaboration_mode: str | None = None,
|
|
810
|
+
goal_objective: str | None = None,
|
|
811
|
+
runtime_input: Any = None,
|
|
812
|
+
idempotency_key: str,
|
|
813
|
+
on_event: Callable[[RunEvent], None] | None = None,
|
|
814
|
+
) -> Operation:
|
|
815
|
+
async def runner():
|
|
816
|
+
return await self.run_build(
|
|
817
|
+
build_id,
|
|
818
|
+
user_input,
|
|
819
|
+
session_id,
|
|
820
|
+
model=model,
|
|
821
|
+
sandbox=sandbox,
|
|
822
|
+
approval_mode=approval_mode,
|
|
823
|
+
collaboration_mode=collaboration_mode,
|
|
824
|
+
goal_objective=goal_objective,
|
|
825
|
+
runtime_input=runtime_input,
|
|
826
|
+
on_event=on_event,
|
|
827
|
+
)
|
|
828
|
+
|
|
829
|
+
return self.operations.submit(
|
|
830
|
+
kind=OperationKind.RUN,
|
|
831
|
+
resource_id=build_id,
|
|
832
|
+
idempotency_key=idempotency_key,
|
|
833
|
+
runner=runner,
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
async def run_build(
|
|
837
|
+
self,
|
|
838
|
+
build_id: str,
|
|
839
|
+
user_input: str,
|
|
840
|
+
session_id: str | None,
|
|
841
|
+
*,
|
|
842
|
+
model: str | None = None,
|
|
843
|
+
sandbox: str | None = None,
|
|
844
|
+
approval_mode: str | None = None,
|
|
845
|
+
collaboration_mode: str | None = None,
|
|
846
|
+
goal_objective: str | None = None,
|
|
847
|
+
runtime_input: Any = None,
|
|
848
|
+
on_event: Callable[[RunEvent], None] | None = None,
|
|
849
|
+
):
|
|
850
|
+
"""Execute any immutable Studio Build through the canonical executor."""
|
|
851
|
+
|
|
852
|
+
try:
|
|
853
|
+
spec = self.codex_runs.resolve(
|
|
854
|
+
build_id,
|
|
855
|
+
model=model,
|
|
856
|
+
sandbox=sandbox,
|
|
857
|
+
approval_mode=approval_mode,
|
|
858
|
+
)
|
|
859
|
+
except Exception as exc:
|
|
860
|
+
if getattr(exc, "status_code", None) != 404:
|
|
861
|
+
raise
|
|
862
|
+
spec = self.framework_runs.resolve(
|
|
863
|
+
build_id,
|
|
864
|
+
model=model,
|
|
865
|
+
approval_mode=approval_mode,
|
|
866
|
+
)
|
|
867
|
+
if collaboration_mode or goal_objective:
|
|
868
|
+
from dataclasses import replace
|
|
869
|
+
|
|
870
|
+
request_config = dict(spec.request_config)
|
|
871
|
+
if collaboration_mode:
|
|
872
|
+
request_config["collaboration_mode"] = collaboration_mode
|
|
873
|
+
if goal_objective:
|
|
874
|
+
request_config["goal_objective"] = goal_objective
|
|
875
|
+
request_config["ephemeral"] = False
|
|
876
|
+
spec = replace(spec, request_config=request_config)
|
|
877
|
+
return await self.run_service.run(
|
|
878
|
+
spec,
|
|
879
|
+
user_input,
|
|
880
|
+
runtime_input=runtime_input,
|
|
881
|
+
session_id=session_id,
|
|
882
|
+
on_event=on_event,
|
|
883
|
+
)
|
|
884
|
+
|
|
885
|
+
def submit_evaluation(
|
|
886
|
+
self,
|
|
887
|
+
build_id: str,
|
|
888
|
+
suite_refs: list[str],
|
|
889
|
+
*,
|
|
890
|
+
fail_fast: bool,
|
|
891
|
+
idempotency_key: str,
|
|
892
|
+
) -> Operation:
|
|
893
|
+
async def runner():
|
|
894
|
+
return await self.evaluations.run(
|
|
895
|
+
build_id,
|
|
896
|
+
suite_refs,
|
|
897
|
+
fail_fast=fail_fast,
|
|
898
|
+
)
|
|
899
|
+
|
|
900
|
+
return self.operations.submit(
|
|
901
|
+
kind=OperationKind.EVALUATION,
|
|
902
|
+
resource_id=build_id,
|
|
903
|
+
idempotency_key=idempotency_key,
|
|
904
|
+
runner=runner,
|
|
905
|
+
)
|
|
906
|
+
|
|
907
|
+
def submit_public_evaluation(
|
|
908
|
+
self,
|
|
909
|
+
evalset_file: str,
|
|
910
|
+
target: TargetRef,
|
|
911
|
+
config: PublicEvaluationConfig,
|
|
912
|
+
*,
|
|
913
|
+
idempotency_key: str,
|
|
914
|
+
) -> Operation:
|
|
915
|
+
"""Queue the public CLI/Studio handoff without exposing adapter internals."""
|
|
916
|
+
|
|
917
|
+
try:
|
|
918
|
+
path = self.workspace.resolve(evalset_file, must_exist=True)
|
|
919
|
+
except StudioError:
|
|
920
|
+
raise
|
|
921
|
+
if not path.is_file():
|
|
922
|
+
raise StudioError(
|
|
923
|
+
"EVALSET_FILE_INVALID",
|
|
924
|
+
"EvalSet 必须是工作区内的文件",
|
|
925
|
+
status_code=422,
|
|
926
|
+
field="evalsetFile",
|
|
927
|
+
)
|
|
928
|
+
try:
|
|
929
|
+
evalset = load_evalset(path)
|
|
930
|
+
except EvalSetParseError as exc:
|
|
931
|
+
raise StudioError(
|
|
932
|
+
exc.code,
|
|
933
|
+
str(exc),
|
|
934
|
+
status_code=422,
|
|
935
|
+
field="evalsetFile",
|
|
936
|
+
) from exc
|
|
937
|
+
target = self._normalize_public_evaluation_target(target)
|
|
938
|
+
request = PublicEvaluationRequest(
|
|
939
|
+
evalset=evalset,
|
|
940
|
+
target=target,
|
|
941
|
+
config=config,
|
|
942
|
+
report_dir=str(self.evaluation_storage.root),
|
|
943
|
+
)
|
|
944
|
+
|
|
945
|
+
async def runner():
|
|
946
|
+
try:
|
|
947
|
+
report = await execute_evaluation(request)
|
|
948
|
+
except EvaluationNotImplementedError as exc:
|
|
949
|
+
raise StudioError(
|
|
950
|
+
"EVALUATION_EXECUTOR_UNAVAILABLE",
|
|
951
|
+
str(exc),
|
|
952
|
+
status_code=501,
|
|
953
|
+
) from exc
|
|
954
|
+
except EvaluationExecutionError as exc:
|
|
955
|
+
raise StudioError(
|
|
956
|
+
"EVALUATION_EXECUTION_FAILED",
|
|
957
|
+
str(exc),
|
|
958
|
+
status_code=502,
|
|
959
|
+
) from exc
|
|
960
|
+
try:
|
|
961
|
+
self.evaluation_storage.write_report(report)
|
|
962
|
+
except EvaluationStorageError as exc:
|
|
963
|
+
raise StudioError(
|
|
964
|
+
"EVALUATION_REPORT_WRITE_FAILED",
|
|
965
|
+
"评测报告写入失败",
|
|
966
|
+
status_code=500,
|
|
967
|
+
) from exc
|
|
968
|
+
return report
|
|
969
|
+
|
|
970
|
+
return self.operations.submit(
|
|
971
|
+
kind=OperationKind.EVALUATION,
|
|
972
|
+
resource_id=evalset.content_digest,
|
|
973
|
+
idempotency_key=idempotency_key,
|
|
974
|
+
runner=runner,
|
|
975
|
+
)
|
|
976
|
+
|
|
977
|
+
def list_public_evaluations(self):
|
|
978
|
+
return self.evaluation_storage.list_reports()
|
|
979
|
+
|
|
980
|
+
def get_public_evaluation(self, evaluation_id: str):
|
|
981
|
+
try:
|
|
982
|
+
return self.evaluation_storage.read_report(evaluation_id)
|
|
983
|
+
except EvaluationStorageError as exc:
|
|
984
|
+
raise StudioError(
|
|
985
|
+
"EVALUATION_NOT_FOUND",
|
|
986
|
+
"Evaluation 不存在",
|
|
987
|
+
status_code=404,
|
|
988
|
+
details={"id": evaluation_id},
|
|
989
|
+
) from exc
|
|
990
|
+
|
|
991
|
+
def _normalize_public_evaluation_target(self, target: TargetRef) -> TargetRef:
|
|
992
|
+
if target.kind == TargetKind.A2A:
|
|
993
|
+
parsed = urlparse(target.locator)
|
|
994
|
+
if parsed.scheme not in {"http", "https"} or not parsed.netloc:
|
|
995
|
+
raise StudioError(
|
|
996
|
+
"EVALUATION_A2A_URL_INVALID",
|
|
997
|
+
"A2A target 必须是 http 或 https URL",
|
|
998
|
+
status_code=422,
|
|
999
|
+
field="target.locator",
|
|
1000
|
+
)
|
|
1001
|
+
return target
|
|
1002
|
+
path = self.workspace.resolve(target.locator, must_exist=True)
|
|
1003
|
+
if not path.is_dir():
|
|
1004
|
+
raise StudioError(
|
|
1005
|
+
"EVALUATION_TARGET_INVALID",
|
|
1006
|
+
"本地 target 必须是工作区内的目录",
|
|
1007
|
+
status_code=422,
|
|
1008
|
+
field="target.locator",
|
|
1009
|
+
)
|
|
1010
|
+
return target.model_copy(update={"locator": str(path)})
|
|
1011
|
+
|
|
1012
|
+
def submit_deployment(
|
|
1013
|
+
self,
|
|
1014
|
+
build_id: str,
|
|
1015
|
+
request: DeploymentRequest,
|
|
1016
|
+
*,
|
|
1017
|
+
idempotency_key: str,
|
|
1018
|
+
) -> Operation:
|
|
1019
|
+
async def runner():
|
|
1020
|
+
return await self.cloud.deploy(build_id, request)
|
|
1021
|
+
|
|
1022
|
+
return self.operations.submit(
|
|
1023
|
+
kind=OperationKind.DEPLOYMENT,
|
|
1024
|
+
resource_id=build_id,
|
|
1025
|
+
idempotency_key=idempotency_key,
|
|
1026
|
+
runner=runner,
|
|
1027
|
+
)
|
|
1028
|
+
|
|
1029
|
+
def submit_rollback(
|
|
1030
|
+
self,
|
|
1031
|
+
deployment_id: str,
|
|
1032
|
+
*,
|
|
1033
|
+
target_build_id: str,
|
|
1034
|
+
idempotency_key: str,
|
|
1035
|
+
) -> Operation:
|
|
1036
|
+
async def runner():
|
|
1037
|
+
return await self.cloud.rollback(
|
|
1038
|
+
deployment_id,
|
|
1039
|
+
target_build_id=target_build_id,
|
|
1040
|
+
)
|
|
1041
|
+
|
|
1042
|
+
return self.operations.submit(
|
|
1043
|
+
kind=OperationKind.DEPLOYMENT,
|
|
1044
|
+
resource_id=deployment_id,
|
|
1045
|
+
idempotency_key=idempotency_key,
|
|
1046
|
+
runner=runner,
|
|
1047
|
+
)
|
|
1048
|
+
|
|
1049
|
+
def get_settings(self) -> dict[str, Any]:
|
|
1050
|
+
path = self.workspace.resolve(".agentkit/settings.yaml")
|
|
1051
|
+
data: dict[str, Any] = {}
|
|
1052
|
+
if path.is_file():
|
|
1053
|
+
try:
|
|
1054
|
+
data = load_yaml_file(path) or {}
|
|
1055
|
+
except Exception:
|
|
1056
|
+
data = {}
|
|
1057
|
+
defaults = {
|
|
1058
|
+
"sandbox": os.environ.get("KSADK_CODEX_SANDBOX", "read_only"),
|
|
1059
|
+
"buildAfterCreate": True,
|
|
1060
|
+
"codexProxy": os.environ.get("KSADK_CODEX_USE_PROXY", "auto"),
|
|
1061
|
+
"cloudAccessKey": os.environ.get("KINGSOFTCLOUD_ACCESS_KEY", ""),
|
|
1062
|
+
"cloudSecretKey": os.environ.get("KINGSOFTCLOUD_SECRET_KEY", ""),
|
|
1063
|
+
"cloudRegion": os.environ.get("KSYUN_REGION", "cn-beijing-6"),
|
|
1064
|
+
"traceContent": os.environ.get("KSADK_STUDIO_TRACE_CONTENT", "1") != "0",
|
|
1065
|
+
}
|
|
1066
|
+
defaults.update({k: v for k, v in data.items() if v is not None})
|
|
1067
|
+
return defaults
|
|
1068
|
+
|
|
1069
|
+
def update_settings(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
1070
|
+
allowed = {
|
|
1071
|
+
"sandbox",
|
|
1072
|
+
"buildAfterCreate",
|
|
1073
|
+
"codexProxy",
|
|
1074
|
+
"cloudAccessKey",
|
|
1075
|
+
"cloudSecretKey",
|
|
1076
|
+
"cloudRegion",
|
|
1077
|
+
"traceContent",
|
|
1078
|
+
}
|
|
1079
|
+
data = {k: payload[k] for k in allowed if k in payload}
|
|
1080
|
+
if data.get("sandbox") and data["sandbox"] not in {
|
|
1081
|
+
"read-only",
|
|
1082
|
+
"workspace-write",
|
|
1083
|
+
"workspace-write-auto",
|
|
1084
|
+
"full-access",
|
|
1085
|
+
"read_only",
|
|
1086
|
+
"workspace_write",
|
|
1087
|
+
"workspace_write_auto",
|
|
1088
|
+
"full_access",
|
|
1089
|
+
}:
|
|
1090
|
+
raise StudioError("SETTINGS_INVALID", "sandbox 取值非法", status_code=422)
|
|
1091
|
+
path = self.workspace.resolve(".agentkit/settings.yaml")
|
|
1092
|
+
self.workspace.atomic_write_yaml(path, data)
|
|
1093
|
+
self._apply_settings_to_env(data)
|
|
1094
|
+
return self.get_settings()
|
|
1095
|
+
|
|
1096
|
+
def _apply_persisted_settings(self) -> None:
|
|
1097
|
+
"""启动时把 settings.yaml 回填到进程环境。
|
|
1098
|
+
|
|
1099
|
+
update_settings 只在 PUT 时桥接 env;重启后 env 丢失,运行解析
|
|
1100
|
+
(如 _resolve_sandbox 读 KSADK_CODEX_SANDBOX)会回落默认,表现为
|
|
1101
|
+
「设置页显示 workspace-write-auto,实际运行 read-only」。
|
|
1102
|
+
"""
|
|
1103
|
+
path = self.workspace.resolve(".agentkit/settings.yaml")
|
|
1104
|
+
if not path.is_file():
|
|
1105
|
+
return
|
|
1106
|
+
try:
|
|
1107
|
+
data = load_yaml_file(path) or {}
|
|
1108
|
+
except Exception:
|
|
1109
|
+
return
|
|
1110
|
+
if isinstance(data, dict):
|
|
1111
|
+
self._apply_settings_to_env(data)
|
|
1112
|
+
|
|
1113
|
+
@staticmethod
|
|
1114
|
+
def _apply_settings_to_env(data: dict[str, Any]) -> None:
|
|
1115
|
+
if data.get("sandbox"):
|
|
1116
|
+
os.environ["KSADK_CODEX_SANDBOX"] = data["sandbox"]
|
|
1117
|
+
if data.get("codexProxy"):
|
|
1118
|
+
os.environ["KSADK_CODEX_USE_PROXY"] = data["codexProxy"]
|
|
1119
|
+
if data.get("cloudAccessKey"):
|
|
1120
|
+
os.environ["KINGSOFTCLOUD_ACCESS_KEY"] = data["cloudAccessKey"]
|
|
1121
|
+
if data.get("cloudSecretKey"):
|
|
1122
|
+
os.environ["KINGSOFTCLOUD_SECRET_KEY"] = data["cloudSecretKey"]
|
|
1123
|
+
if data.get("cloudRegion"):
|
|
1124
|
+
os.environ["KSYUN_REGION"] = data["cloudRegion"]
|
|
1125
|
+
if "traceContent" in data:
|
|
1126
|
+
os.environ["KSADK_STUDIO_TRACE_CONTENT"] = "1" if data["traceContent"] else "0"
|
|
1127
|
+
|
|
1128
|
+
@staticmethod
|
|
1129
|
+
def builtin_capabilities():
|
|
1130
|
+
return list(builtin_tool_contracts().values())
|
|
1131
|
+
|
|
1132
|
+
def list_capabilities(
|
|
1133
|
+
self,
|
|
1134
|
+
*,
|
|
1135
|
+
kind: str | None = None,
|
|
1136
|
+
query: str = "",
|
|
1137
|
+
) -> list[dict]:
|
|
1138
|
+
return [
|
|
1139
|
+
item.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
1140
|
+
for item in self.catalog.list(kind=kind, query=query, limit=200)
|
|
1141
|
+
]
|