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/harness/sandbox.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""Invocation-owned execution policy for Harness sandbox tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import os
|
|
7
|
+
import shlex
|
|
8
|
+
import subprocess
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SandboxPolicyDenied(PermissionError):
|
|
14
|
+
"""Raised before execution when a Harness sandbox action violates policy."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
_READ_COMMANDS = frozenset({"cat", "head", "ls", "pwd", "stat", "tail", "wc"})
|
|
18
|
+
_NO_PATH_COMMANDS = frozenset({"pwd"})
|
|
19
|
+
_REQUIRE_PATH_COMMANDS = frozenset({"cat", "head", "stat", "tail", "wc"})
|
|
20
|
+
_VALUE_OPTIONS = frozenset({"-n", "--bytes", "--lines", "--max-unchanged-stats"})
|
|
21
|
+
_SHELL_OPERATORS = frozenset({"|", "||", "&", "&&", ";", ">", ">>", "<", "<<"})
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class HarnessSandboxExecutor:
|
|
25
|
+
"""Run a deliberately small read-only command surface inside one workspace.
|
|
26
|
+
|
|
27
|
+
Commands are executed without a shell. Path operands are resolved before the
|
|
28
|
+
child process starts, including symlinks, so reads cannot escape the configured
|
|
29
|
+
workspace. The narrow command surface also excludes network clients and process
|
|
30
|
+
launchers entirely.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, *, workspace_root: str | Path, read_only: bool = True) -> None:
|
|
34
|
+
self._workspace_root = Path(workspace_root).expanduser().resolve()
|
|
35
|
+
self._workspace_root.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
self._read_only = read_only
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def workspace_root(self) -> Path:
|
|
40
|
+
return self._workspace_root
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def read_only(self) -> bool:
|
|
44
|
+
return self._read_only
|
|
45
|
+
|
|
46
|
+
async def read_file(self, path: str) -> dict[str, Any]:
|
|
47
|
+
target = self._resolve_path(path)
|
|
48
|
+
content = await asyncio.to_thread(target.read_text, encoding="utf-8")
|
|
49
|
+
return {
|
|
50
|
+
"ok": True,
|
|
51
|
+
"path": target.relative_to(self._workspace_root).as_posix(),
|
|
52
|
+
"content": content,
|
|
53
|
+
"policy": "read-only",
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async def run_command(self, command: str) -> dict[str, Any]:
|
|
57
|
+
argv = self._validate_command(command)
|
|
58
|
+
completed = await asyncio.to_thread(
|
|
59
|
+
subprocess.run,
|
|
60
|
+
argv,
|
|
61
|
+
cwd=self._workspace_root,
|
|
62
|
+
env={"PATH": os.environ.get("PATH", "")},
|
|
63
|
+
capture_output=True,
|
|
64
|
+
text=True,
|
|
65
|
+
timeout=10,
|
|
66
|
+
check=False,
|
|
67
|
+
)
|
|
68
|
+
return {
|
|
69
|
+
"ok": completed.returncode == 0,
|
|
70
|
+
"command": " ".join(argv),
|
|
71
|
+
"stdout": completed.stdout,
|
|
72
|
+
"stderr": completed.stderr,
|
|
73
|
+
"exit_code": completed.returncode,
|
|
74
|
+
"policy": "read-only",
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def _validate_command(self, command: str) -> list[str]:
|
|
78
|
+
try:
|
|
79
|
+
argv = shlex.split(str(command or ""), posix=True)
|
|
80
|
+
except ValueError as exc:
|
|
81
|
+
raise SandboxPolicyDenied(f"read-only sandbox denied malformed command: {exc}") from exc
|
|
82
|
+
if not argv:
|
|
83
|
+
raise SandboxPolicyDenied("read-only sandbox denied empty command")
|
|
84
|
+
if any(argument in _SHELL_OPERATORS for argument in argv):
|
|
85
|
+
raise SandboxPolicyDenied(
|
|
86
|
+
"read-only sandbox denied shell redirection, pipelines, or command chaining"
|
|
87
|
+
)
|
|
88
|
+
executable = argv[0]
|
|
89
|
+
if executable not in _READ_COMMANDS:
|
|
90
|
+
raise SandboxPolicyDenied(
|
|
91
|
+
f"read-only sandbox denied command {executable!r}; network, write, and "
|
|
92
|
+
"dangerous process actions are not allowed"
|
|
93
|
+
)
|
|
94
|
+
if executable in _NO_PATH_COMMANDS:
|
|
95
|
+
if len(argv) != 1:
|
|
96
|
+
raise SandboxPolicyDenied(
|
|
97
|
+
f"read-only sandbox denied arguments for command {executable!r}"
|
|
98
|
+
)
|
|
99
|
+
return argv
|
|
100
|
+
|
|
101
|
+
normalized = [executable]
|
|
102
|
+
skip_option_value = False
|
|
103
|
+
saw_path = False
|
|
104
|
+
for argument in argv[1:]:
|
|
105
|
+
if skip_option_value:
|
|
106
|
+
normalized.append(argument)
|
|
107
|
+
skip_option_value = False
|
|
108
|
+
continue
|
|
109
|
+
if argument == "--":
|
|
110
|
+
normalized.append(argument)
|
|
111
|
+
continue
|
|
112
|
+
if argument in _VALUE_OPTIONS:
|
|
113
|
+
normalized.append(argument)
|
|
114
|
+
skip_option_value = True
|
|
115
|
+
continue
|
|
116
|
+
if argument.startswith("-"):
|
|
117
|
+
normalized.append(argument)
|
|
118
|
+
continue
|
|
119
|
+
target = self._resolve_path(argument)
|
|
120
|
+
normalized.append(str(target))
|
|
121
|
+
saw_path = True
|
|
122
|
+
if executable in _REQUIRE_PATH_COMMANDS and not saw_path:
|
|
123
|
+
raise SandboxPolicyDenied(
|
|
124
|
+
f"read-only sandbox denied command {executable!r} without a workspace path"
|
|
125
|
+
)
|
|
126
|
+
return normalized
|
|
127
|
+
|
|
128
|
+
def _resolve_path(self, path: str) -> Path:
|
|
129
|
+
raw = str(path or "").strip()
|
|
130
|
+
if not raw:
|
|
131
|
+
raise SandboxPolicyDenied("read-only sandbox requires a workspace path")
|
|
132
|
+
candidate = Path(raw)
|
|
133
|
+
if not candidate.is_absolute():
|
|
134
|
+
candidate = self._workspace_root / candidate
|
|
135
|
+
resolved = candidate.expanduser().resolve()
|
|
136
|
+
if resolved != self._workspace_root and self._workspace_root not in resolved.parents:
|
|
137
|
+
raise SandboxPolicyDenied(f"read-only sandbox denied path outside workspace: {raw!r}")
|
|
138
|
+
return resolved
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
__all__ = ["HarnessSandboxExecutor", "SandboxPolicyDenied"]
|
ksadk/harness/tools.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""Tool catalog for one Harness runner."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import uuid
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any, Awaitable, Callable
|
|
9
|
+
|
|
10
|
+
from ksadk.compat.adk_compat import Agent, InMemorySessionService, InvocationContext, ToolContext
|
|
11
|
+
from ksadk.harness.config import McpToolSpec
|
|
12
|
+
from ksadk.harness.sandbox import HarnessSandboxExecutor
|
|
13
|
+
from ksadk.mcp_runtime import MCPServerConfig, build_mcp_toolset
|
|
14
|
+
|
|
15
|
+
ToolHandler = Callable[[dict[str, Any], str | None], Awaitable[Any]]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class HarnessTool:
|
|
20
|
+
name: str
|
|
21
|
+
description: str
|
|
22
|
+
parameters: dict[str, Any]
|
|
23
|
+
handler: ToolHandler
|
|
24
|
+
source: str
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def openai_schema(self) -> dict[str, Any]:
|
|
28
|
+
return {
|
|
29
|
+
"type": "function",
|
|
30
|
+
"function": {
|
|
31
|
+
"name": self.name,
|
|
32
|
+
"description": self.description,
|
|
33
|
+
"parameters": self.parameters,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async def call(self, arguments: dict[str, Any], *, call_id: str | None = None) -> Any:
|
|
38
|
+
return await self.handler(arguments, call_id)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def sandbox_tools(sandbox: HarnessSandboxExecutor) -> list[HarnessTool]:
|
|
42
|
+
async def _read_file(arguments: dict[str, Any], call_id: str | None) -> Any:
|
|
43
|
+
del call_id
|
|
44
|
+
return await sandbox.read_file(str(arguments.get("path") or ""))
|
|
45
|
+
|
|
46
|
+
async def _run_command(arguments: dict[str, Any], call_id: str | None) -> Any:
|
|
47
|
+
del call_id
|
|
48
|
+
return await sandbox.run_command(str(arguments.get("command") or ""))
|
|
49
|
+
|
|
50
|
+
return [
|
|
51
|
+
HarnessTool(
|
|
52
|
+
name="sandbox_read_file",
|
|
53
|
+
description="Read one UTF-8 file inside the Harness workspace.",
|
|
54
|
+
parameters={
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {"path": {"type": "string"}},
|
|
57
|
+
"required": ["path"],
|
|
58
|
+
"additionalProperties": False,
|
|
59
|
+
},
|
|
60
|
+
handler=_read_file,
|
|
61
|
+
source="sandbox",
|
|
62
|
+
),
|
|
63
|
+
HarnessTool(
|
|
64
|
+
name="sandbox_run_command",
|
|
65
|
+
description=(
|
|
66
|
+
"Run an allowlisted read-only command inside the Harness workspace. "
|
|
67
|
+
"Writes, network access, and dangerous process actions are denied."
|
|
68
|
+
),
|
|
69
|
+
parameters={
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {"command": {"type": "string"}},
|
|
72
|
+
"required": ["command"],
|
|
73
|
+
"additionalProperties": False,
|
|
74
|
+
},
|
|
75
|
+
handler=_run_command,
|
|
76
|
+
source="sandbox",
|
|
77
|
+
),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def load_mcp_tools(spec: McpToolSpec) -> tuple[Any, list[HarnessTool]]:
|
|
82
|
+
config = MCPServerConfig(
|
|
83
|
+
name=spec.name,
|
|
84
|
+
url=spec.url,
|
|
85
|
+
api_key=spec.api_key,
|
|
86
|
+
tool_filter=spec.tool_filter,
|
|
87
|
+
tool_name_prefix=spec.tool_name_prefix,
|
|
88
|
+
)
|
|
89
|
+
toolset = build_mcp_toolset(config)
|
|
90
|
+
try:
|
|
91
|
+
native_tools = await toolset.get_tools_with_prefix()
|
|
92
|
+
except Exception as exc:
|
|
93
|
+
await toolset.close()
|
|
94
|
+
raise RuntimeError(
|
|
95
|
+
f"Harness MCP server {spec.name!r} at {spec.url!r} failed to start: {exc}"
|
|
96
|
+
) from exc
|
|
97
|
+
|
|
98
|
+
available_names = {str(tool.name) for tool in native_tools}
|
|
99
|
+
expected_names = {
|
|
100
|
+
f"{spec.tool_name_prefix}_{name}" if spec.tool_name_prefix else name
|
|
101
|
+
for name in spec.tool_filter
|
|
102
|
+
}
|
|
103
|
+
missing_names = sorted(expected_names - available_names)
|
|
104
|
+
if missing_names:
|
|
105
|
+
await toolset.close()
|
|
106
|
+
raise RuntimeError(
|
|
107
|
+
f"Harness MCP server {spec.name!r} at {spec.url!r} did not expose configured "
|
|
108
|
+
f"tool(s): {missing_names}"
|
|
109
|
+
)
|
|
110
|
+
if not native_tools:
|
|
111
|
+
await toolset.close()
|
|
112
|
+
raise RuntimeError(
|
|
113
|
+
f"Harness MCP server {spec.name!r} at {spec.url!r} exposed no callable tools"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
tools: list[HarnessTool] = []
|
|
117
|
+
for native_tool in native_tools:
|
|
118
|
+
# ADK's declaration builder is private and changed across 1.x/2.x.
|
|
119
|
+
# MCP exposes the original public tool schema, which is stable across
|
|
120
|
+
# the supported versions.
|
|
121
|
+
raw_tool = getattr(native_tool, "raw_mcp_tool", None)
|
|
122
|
+
parameters = getattr(raw_tool, "inputSchema", None)
|
|
123
|
+
if parameters is None:
|
|
124
|
+
parameters = getattr(raw_tool, "input_schema", None)
|
|
125
|
+
if parameters is None:
|
|
126
|
+
parameters = getattr(native_tool, "input_schema", None)
|
|
127
|
+
if not isinstance(parameters, dict):
|
|
128
|
+
parameters = {"type": "object", "properties": {}}
|
|
129
|
+
parameters = _normalize_json_schema(parameters)
|
|
130
|
+
|
|
131
|
+
async def _call(
|
|
132
|
+
arguments: dict[str, Any],
|
|
133
|
+
call_id: str | None,
|
|
134
|
+
*,
|
|
135
|
+
_native_tool=native_tool,
|
|
136
|
+
_tool_name=str(native_tool.name),
|
|
137
|
+
) -> Any:
|
|
138
|
+
try:
|
|
139
|
+
context = await _new_tool_context(call_id or _tool_name)
|
|
140
|
+
result = await _native_tool.run_async(args=arguments, tool_context=context)
|
|
141
|
+
return _normalize_tool_result(result, context)
|
|
142
|
+
except Exception as exc:
|
|
143
|
+
raise RuntimeError(
|
|
144
|
+
f"Harness MCP tool {_tool_name!r} on server {spec.name!r} failed: {exc}"
|
|
145
|
+
) from exc
|
|
146
|
+
|
|
147
|
+
tools.append(
|
|
148
|
+
HarnessTool(
|
|
149
|
+
name=str(native_tool.name),
|
|
150
|
+
description=str(getattr(native_tool, "description", None) or "MCP tool"),
|
|
151
|
+
parameters=parameters,
|
|
152
|
+
handler=_call,
|
|
153
|
+
source=f"mcp:{spec.name}",
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
return toolset, tools
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
async def _new_tool_context(tool_name: str) -> Any:
|
|
160
|
+
"""Build a real ADK ToolContext for a standalone MCP invocation."""
|
|
161
|
+
service = InMemorySessionService()
|
|
162
|
+
session = await service.create_session(
|
|
163
|
+
app_name="ksadk-harness",
|
|
164
|
+
user_id="harness",
|
|
165
|
+
session_id=f"tool-{uuid.uuid4().hex}",
|
|
166
|
+
)
|
|
167
|
+
invocation = InvocationContext(
|
|
168
|
+
session_service=service,
|
|
169
|
+
invocation_id=f"harness-tool-{tool_name}",
|
|
170
|
+
# ADK 1.34 requires an agent while 2.x makes it optional. Supplying a
|
|
171
|
+
# minimal public Agent keeps the same ToolContext construction on both.
|
|
172
|
+
agent=Agent(name="harness_tool", model="gemini-2.0-flash"),
|
|
173
|
+
session=session,
|
|
174
|
+
)
|
|
175
|
+
return ToolContext(invocation_context=invocation, function_call_id=tool_name)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _normalize_tool_result(result: Any, context: Any) -> Any:
|
|
179
|
+
"""Keep MCP failures structured so the reasoner can produce a final answer."""
|
|
180
|
+
confirmations = getattr(context.actions, "requested_tool_confirmations", {})
|
|
181
|
+
if confirmations:
|
|
182
|
+
error = result.get("error") if isinstance(result, dict) else None
|
|
183
|
+
return {
|
|
184
|
+
"ok": False,
|
|
185
|
+
"confirmation_required": True,
|
|
186
|
+
"confirmation_ids": sorted(str(item) for item in confirmations),
|
|
187
|
+
"error": str(error or "tool confirmation is required"),
|
|
188
|
+
}
|
|
189
|
+
if isinstance(result, dict) and result.get("error") is not None:
|
|
190
|
+
return {"ok": False, "error": str(result["error"])}
|
|
191
|
+
return result
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def tool_result_text(result: Any) -> str:
|
|
195
|
+
if isinstance(result, str):
|
|
196
|
+
return result
|
|
197
|
+
if isinstance(result, dict):
|
|
198
|
+
content = result.get("content")
|
|
199
|
+
if isinstance(content, list):
|
|
200
|
+
texts = [
|
|
201
|
+
str(item.get("text"))
|
|
202
|
+
for item in content
|
|
203
|
+
if isinstance(item, dict) and item.get("text") is not None
|
|
204
|
+
]
|
|
205
|
+
if texts:
|
|
206
|
+
return "\n".join(texts)
|
|
207
|
+
return json.dumps(result, ensure_ascii=False, default=str)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _normalize_json_schema(value: Any) -> Any:
|
|
211
|
+
if isinstance(value, dict):
|
|
212
|
+
normalized = {key: _normalize_json_schema(item) for key, item in value.items()}
|
|
213
|
+
schema_type = normalized.get("type")
|
|
214
|
+
if isinstance(schema_type, str):
|
|
215
|
+
normalized["type"] = schema_type.lower()
|
|
216
|
+
return normalized
|
|
217
|
+
if isinstance(value, list):
|
|
218
|
+
return [_normalize_json_schema(item) for item in value]
|
|
219
|
+
return value
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
__all__ = ["HarnessTool", "load_mcp_tools", "sandbox_tools", "tool_result_text"]
|
ksadk/hermes_terminal.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import contextlib
|
|
7
7
|
import ctypes
|
|
8
|
+
import importlib
|
|
8
9
|
import io
|
|
9
10
|
import json
|
|
10
11
|
import os
|
|
@@ -89,6 +90,7 @@ def build_start_frame(
|
|
|
89
90
|
argv: Sequence[str],
|
|
90
91
|
cols: int,
|
|
91
92
|
rows: int,
|
|
93
|
+
session_id: str | None = None,
|
|
92
94
|
cwd: str | None = None,
|
|
93
95
|
options: Mapping[str, Any] | None = None,
|
|
94
96
|
) -> str:
|
|
@@ -105,6 +107,9 @@ def build_start_frame(
|
|
|
105
107
|
normalized_cwd = str(cwd or "").strip()
|
|
106
108
|
if normalized_cwd:
|
|
107
109
|
payload["cwd"] = normalized_cwd
|
|
110
|
+
normalized_session_id = str(session_id or "").strip()
|
|
111
|
+
if normalized_session_id:
|
|
112
|
+
payload["session_id"] = normalized_session_id
|
|
108
113
|
if options:
|
|
109
114
|
payload["options"] = dict(options)
|
|
110
115
|
return json.dumps(payload, ensure_ascii=False)
|
|
@@ -123,7 +128,9 @@ def validate_terminal_exec_argv(argv: Iterable[str]) -> list[str]:
|
|
|
123
128
|
return validate_exec_argv_with_policy(argv, policy=GENERIC_TERMINAL_EXEC_POLICY)
|
|
124
129
|
|
|
125
130
|
|
|
126
|
-
def build_terminal_exec_validator(
|
|
131
|
+
def build_terminal_exec_validator(
|
|
132
|
+
policy: TerminalExecPolicy,
|
|
133
|
+
) -> Callable[[Iterable[str]], list[str]]:
|
|
127
134
|
def _validator(argv: Iterable[str]) -> list[str]:
|
|
128
135
|
return validate_exec_argv_with_policy(argv, policy=policy)
|
|
129
136
|
|
|
@@ -190,30 +197,34 @@ def _raw_terminal(stdin: Any):
|
|
|
190
197
|
|
|
191
198
|
|
|
192
199
|
@contextlib.contextmanager
|
|
193
|
-
def _windows_raw_terminal(
|
|
200
|
+
def _windows_raw_terminal(
|
|
201
|
+
stdin: Any, *, kernel32: Any | None = None, msvcrt_module: Any | None = None
|
|
202
|
+
):
|
|
194
203
|
if not hasattr(stdin, "fileno") or not hasattr(stdin, "isatty") or not stdin.isatty():
|
|
195
204
|
yield
|
|
196
205
|
return
|
|
197
206
|
|
|
207
|
+
resolved_kernel32: Any = kernel32
|
|
208
|
+
resolved_msvcrt: Any = msvcrt_module
|
|
198
209
|
try:
|
|
199
|
-
if
|
|
200
|
-
|
|
201
|
-
if
|
|
202
|
-
|
|
210
|
+
if resolved_kernel32 is None:
|
|
211
|
+
resolved_kernel32 = getattr(ctypes, "windll").kernel32
|
|
212
|
+
if resolved_msvcrt is None:
|
|
213
|
+
resolved_msvcrt = importlib.import_module("msvcrt")
|
|
203
214
|
except Exception:
|
|
204
215
|
yield
|
|
205
216
|
return
|
|
206
217
|
|
|
207
218
|
try:
|
|
208
219
|
fd = stdin.fileno()
|
|
209
|
-
handle =
|
|
220
|
+
handle = resolved_msvcrt.get_osfhandle(fd)
|
|
210
221
|
except Exception:
|
|
211
222
|
yield
|
|
212
223
|
return
|
|
213
224
|
|
|
214
225
|
original_mode = wintypes.DWORD()
|
|
215
226
|
try:
|
|
216
|
-
if not
|
|
227
|
+
if not resolved_kernel32.GetConsoleMode(handle, ctypes.byref(original_mode)):
|
|
217
228
|
yield
|
|
218
229
|
return
|
|
219
230
|
except Exception:
|
|
@@ -233,7 +244,7 @@ def _windows_raw_terminal(stdin: Any, *, kernel32: Any | None = None, msvcrt_mod
|
|
|
233
244
|
)
|
|
234
245
|
|
|
235
246
|
try:
|
|
236
|
-
if not
|
|
247
|
+
if not resolved_kernel32.SetConsoleMode(handle, raw_mode):
|
|
237
248
|
yield
|
|
238
249
|
return
|
|
239
250
|
except Exception:
|
|
@@ -244,14 +255,18 @@ def _windows_raw_terminal(stdin: Any, *, kernel32: Any | None = None, msvcrt_mod
|
|
|
244
255
|
yield
|
|
245
256
|
finally:
|
|
246
257
|
with contextlib.suppress(Exception):
|
|
247
|
-
|
|
258
|
+
resolved_kernel32.SetConsoleMode(handle, int(original_mode.value))
|
|
248
259
|
|
|
249
260
|
|
|
250
|
-
async def _connect_websocket(
|
|
261
|
+
async def _connect_websocket(
|
|
262
|
+
ws_url: str, headers: dict[str, str], ssl_context: ssl.SSLContext | None
|
|
263
|
+
):
|
|
251
264
|
try:
|
|
252
265
|
import websockets
|
|
253
266
|
except ImportError as e:
|
|
254
|
-
raise RuntimeError(
|
|
267
|
+
raise RuntimeError(
|
|
268
|
+
"missing dependency websockets, please install ksadk with websocket support"
|
|
269
|
+
) from e
|
|
255
270
|
|
|
256
271
|
kwargs: dict[str, Any] = {"subprotocols": [TERMINAL_SUBPROTOCOL]}
|
|
257
272
|
if ssl_context is not None:
|
|
@@ -404,6 +419,7 @@ async def run_hermes_terminal_session(
|
|
|
404
419
|
argv=normalized_argv,
|
|
405
420
|
cols=size.cols,
|
|
406
421
|
rows=size.rows,
|
|
422
|
+
session_id=session_id,
|
|
407
423
|
cwd=cwd,
|
|
408
424
|
options=options,
|
|
409
425
|
)
|
ksadk/identity/resolver.py
CHANGED
|
@@ -31,11 +31,11 @@ _KRN_ACCOUNT_RE = re.compile(r"krn:ksc:iam::([^:]+):user/")
|
|
|
31
31
|
class ResolvedIdentity:
|
|
32
32
|
"""AK/SK 反查到的身份信息。"""
|
|
33
33
|
|
|
34
|
-
user_uuid: Optional[str]
|
|
34
|
+
user_uuid: Optional[str] # 子账号 UserId(X-Ksc-User-uuid 值);主账号 AK 时 None
|
|
35
35
|
main_account_id: Optional[str] # 从 Krn 提取的主账号 ID
|
|
36
|
-
user_name: Optional[str]
|
|
37
|
-
krn: Optional[str]
|
|
38
|
-
ak_fingerprint: str
|
|
36
|
+
user_name: Optional[str] # 子账号 UserName(调试用)
|
|
37
|
+
krn: Optional[str] # 原始 Krn(调试用)
|
|
38
|
+
ak_fingerprint: str # sha256(AK)[:16],缓存 key
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
# ---------------------------------------------------------------------------
|
|
@@ -107,14 +107,20 @@ def _should_retry_intranet(error: Exception | None) -> bool:
|
|
|
107
107
|
def _import_iam_sdk():
|
|
108
108
|
"""惰性导入 ksyun IAM SDK,失败返回 None。"""
|
|
109
109
|
try:
|
|
110
|
-
from ksyun.client.iam.v20151101.client import
|
|
111
|
-
|
|
110
|
+
from ksyun.client.iam.v20151101.client import ( # type: ignore[import-untyped]
|
|
111
|
+
IamClient,
|
|
112
|
+
)
|
|
113
|
+
from ksyun.client.iam.v20151101.models import ( # type: ignore[import-untyped]
|
|
112
114
|
GetUserRequest,
|
|
113
115
|
ListAllUserAccessKeysRequest,
|
|
114
116
|
)
|
|
115
|
-
from ksyun.common.credential import Credential
|
|
116
|
-
from ksyun.common.profile.client_profile import
|
|
117
|
-
|
|
117
|
+
from ksyun.common.credential import Credential # type: ignore[import-untyped]
|
|
118
|
+
from ksyun.common.profile.client_profile import ( # type: ignore[import-untyped]
|
|
119
|
+
ClientProfile,
|
|
120
|
+
)
|
|
121
|
+
from ksyun.common.profile.http_profile import ( # type: ignore[import-untyped]
|
|
122
|
+
HttpProfile,
|
|
123
|
+
)
|
|
118
124
|
except Exception as exc:
|
|
119
125
|
logger.warning("导入 ksyun IAM SDK 失败: %s", exc)
|
|
120
126
|
return None
|
ksadk/ids.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""统一 id 铸造规范。
|
|
2
|
+
|
|
3
|
+
历史上 session / run(invocation) id 各层格式混杂:
|
|
4
|
+
|
|
5
|
+
- agentengine-server hosted 会话: ``sess-<16 hex>``(conversation_service)
|
|
6
|
+
- ksadk 本地 session: 裸 ``<16 hex>``(sessions/base.generate_id)
|
|
7
|
+
- ksadk 后台 run: ``inv_<32 hex>``(server/app RunAgent)
|
|
8
|
+
- ksadk conversation turn: 裸 ``uuid4``(conversations/runtime)
|
|
9
|
+
- research-ui run_agent 模式: ``run_<session段>``(由 session id 推导)
|
|
10
|
+
|
|
11
|
+
新代码统一走这里:
|
|
12
|
+
|
|
13
|
+
- session id: ``sess-<16 hex>``,与 agentengine-server 对齐。
|
|
14
|
+
- run/invocation id: ``run_<32 hex>``,每次 run 唯一且固定长度。
|
|
15
|
+
|
|
16
|
+
id 均为不透明字符串,仅在铸造时保证格式,消费方不做结构解析。
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import uuid
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def new_session_id() -> str:
|
|
25
|
+
"""铸造 session id:``sess-<16 hex>``。"""
|
|
26
|
+
return f"sess-{uuid.uuid4().hex[:16]}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def new_run_id(session_id: str | None = None) -> str:
|
|
30
|
+
"""铸造固定长度 opaque run/invocation id:``run_<32 hex>``。"""
|
|
31
|
+
del session_id
|
|
32
|
+
return f"run_{uuid.uuid4().hex}"
|
ksadk/knowledge_base/adk_tool.py
CHANGED