agentengine-sdk-python 0.6.9__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +41 -23
- agentengine_sdk_python-0.8.0.dist-info/RECORD +578 -0
- ksadk/a2a/__init__.py +178 -11
- ksadk/a2a/bootstrap.py +334 -0
- ksadk/a2a/card.py +120 -0
- ksadk/a2a/context_store.py +203 -0
- ksadk/a2a/control_plane.py +818 -0
- ksadk/a2a/credential.py +99 -0
- ksadk/a2a/event_adapter.py +149 -0
- ksadk/a2a/executor.py +406 -89
- ksadk/a2a/external_transport.py +516 -0
- ksadk/a2a/identity.py +304 -0
- ksadk/a2a/ids.py +22 -0
- ksadk/a2a/langgraph.py +285 -0
- ksadk/a2a/resume_store.py +201 -0
- ksadk/a2a/routes.py +105 -0
- ksadk/a2a/server.py +107 -60
- ksadk/a2a/space_client.py +1101 -0
- ksadk/a2a/task_adapter.py +423 -0
- ksadk/a2a/task_event_dispatcher.py +167 -0
- ksadk/a2a/task_event_outbox.py +326 -0
- ksadk/a2a/task_store.py +206 -0
- ksadk/a2ui/__init__.py +27 -0
- ksadk/a2ui/core.py +186 -0
- ksadk/a2ui/models.py +166 -0
- ksadk/a2ui/renderer.py +198 -0
- ksadk/agui/__init__.py +9 -0
- ksadk/agui/a2ui_projection.py +92 -0
- ksadk/agui/agent.py +857 -0
- ksadk/agui/config.py +86 -0
- ksadk/agui/routes.py +55 -0
- ksadk/api/client.py +252 -191
- ksadk/builders/__init__.py +2 -0
- ksadk/builders/base.py +16 -14
- ksadk/builders/code_builder.py +318 -236
- ksadk/builders/container_builder.py +187 -167
- ksadk/builders/framework_requirements.py +29 -11
- ksadk/builders/ks3_uploader.py +58 -27
- ksadk/builders/managed_runtime_builder.py +145 -0
- ksadk/builders/mcp_builder.py +91 -92
- ksadk/builders/requirements_utils.py +1 -5
- ksadk/cli/__init__.py +89 -171
- ksadk/cli/cmd_a2a.py +254 -70
- ksadk/cli/cmd_agent.py +19 -5
- ksadk/cli/cmd_build.py +158 -29
- ksadk/cli/cmd_completion.py +47 -35
- ksadk/cli/cmd_config.py +267 -198
- ksadk/cli/cmd_create.py +533 -726
- ksadk/cli/cmd_dashboard.py +120 -45
- ksadk/cli/cmd_deploy.py +117 -58
- ksadk/cli/cmd_destroy.py +44 -14
- ksadk/cli/cmd_files.py +63 -24
- ksadk/cli/cmd_hermes.py +173 -90
- ksadk/cli/cmd_invoke.py +388 -159
- ksadk/cli/cmd_launch.py +64 -28
- ksadk/cli/cmd_mcp.py +103 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +488 -228
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +44 -14
- ksadk/cli/cmd_status.py +80 -31
- ksadk/cli/cmd_version.py +20 -13
- ksadk/cli/cmd_web.py +89 -13
- ksadk/cli/deploy_utils.py +20 -20
- ksadk/cli/dry_run.py +5 -3
- ksadk/cli/error_utils.py +37 -12
- ksadk/cli/global_options.py +1 -2
- ksadk/cli/local_runtime.py +1 -2
- ksadk/cli/model_catalog.py +6 -2
- ksadk/cli/network_options.py +38 -16
- ksadk/cli/resource_common.py +6 -2
- ksadk/cli/storage.py +0 -1
- ksadk/cli/ui.py +5 -3
- ksadk/cli/workflow_common.py +51 -17
- ksadk/codex/__init__.py +12 -0
- ksadk/codex/client.py +408 -0
- ksadk/codex/phase.py +143 -0
- ksadk/codex/runtime.py +449 -0
- ksadk/common/aicp_env.py +0 -1
- ksadk/common/auth.py +2 -2
- ksadk/common/constants.py +1 -3
- ksadk/common/llm_utils.py +17 -13
- ksadk/compat/__init__.py +5 -0
- ksadk/compat/adk_compat.py +200 -0
- ksadk/compat/copilotkit_a2ui.py +330 -0
- ksadk/configs/__init__.py +12 -12
- ksadk/configs/env_registry.py +501 -100
- ksadk/configs/global_config.py +2 -1
- ksadk/configs/settings.py +151 -124
- ksadk/conversations/__init__.py +7 -5
- ksadk/conversations/attachment_storage.py +16 -11
- ksadk/conversations/attachments.py +44 -36
- ksadk/conversations/compaction_pipeline.py +12 -12
- ksadk/conversations/compaction_prompt.py +9 -5
- ksadk/conversations/context.py +221 -6
- ksadk/conversations/message_projection.py +656 -0
- ksadk/conversations/model_context.py +22 -6
- ksadk/conversations/model_options.py +0 -1
- ksadk/conversations/normalize.py +20 -16
- ksadk/conversations/reasoning_markup.py +1 -1
- ksadk/conversations/runtime.py +339 -5187
- ksadk/conversations/runtime_compaction.py +333 -0
- ksadk/conversations/runtime_constants.py +27 -0
- ksadk/conversations/runtime_governance.py +185 -0
- ksadk/conversations/runtime_input.py +652 -0
- ksadk/conversations/runtime_invocation.py +395 -0
- ksadk/conversations/runtime_metadata.py +475 -0
- ksadk/conversations/runtime_observability.py +355 -0
- ksadk/conversations/runtime_payloads.py +272 -0
- ksadk/conversations/runtime_persistence.py +440 -0
- ksadk/conversations/runtime_preparation.py +418 -0
- ksadk/conversations/runtime_resume.py +816 -0
- ksadk/conversations/runtime_stream_events.py +902 -0
- ksadk/conversations/runtime_streaming.py +547 -0
- ksadk/conversations/semantic_summary.py +17 -5
- ksadk/conversations/session_title.py +6 -3
- ksadk/deployment/__init__.py +15 -16
- ksadk/deployment/agent_access.py +12 -23
- ksadk/deployment/base.py +52 -39
- ksadk/deployment/manager.py +63 -65
- ksadk/deployment/providers/serverless.py +326 -209
- ksadk/deployment/registry.py +38 -32
- ksadk/deployment/state.py +11 -11
- ksadk/deployment/ui_config.py +1 -1
- ksadk/detection/__init__.py +1 -1
- ksadk/detection/detector.py +146 -83
- ksadk/detection/mcp_detector.py +9 -6
- ksadk/events/__init__.py +25 -0
- ksadk/events/parser.py +191 -0
- ksadk/events/replay.py +37 -0
- ksadk/events/runtime_event.py +264 -0
- ksadk/events/store.py +317 -0
- ksadk/harness/__init__.py +34 -0
- ksadk/harness/app.py +278 -0
- ksadk/harness/config.py +181 -0
- ksadk/harness/reasoner.py +105 -0
- ksadk/harness/runner.py +211 -0
- ksadk/harness/sandbox.py +141 -0
- ksadk/harness/tools.py +222 -0
- ksadk/hermes_terminal.py +23 -12
- ksadk/identity/resolver.py +15 -9
- ksadk/ids.py +32 -0
- ksadk/knowledge_base/adk_tool.py +1 -1
- ksadk/knowledge_base/client.py +23 -29
- ksadk/managed_runtime.py +188 -0
- ksadk/markdown.py +5 -2
- ksadk/mcp_runtime/__init__.py +9 -6
- ksadk/memory/__init__.py +1 -1
- ksadk/memory/adk/__init__.py +2 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
- ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
- ksadk/memory/adk/backends/sdk_ltm_backend.py +26 -33
- ksadk/memory/adk/long_term_memory.py +31 -35
- ksadk/memory/adk/resilient_session_service.py +267 -0
- ksadk/memory/adk/short_term_memory.py +33 -27
- ksadk/memory/adk_tool.py +3 -2
- ksadk/memory/backends/base.py +19 -19
- ksadk/memory/backends/memory.py +24 -25
- ksadk/memory/backends/redis.py +31 -30
- ksadk/memory/langchain_tool.py +2 -1
- ksadk/memory/manager.py +52 -47
- ksadk/memory/service.py +10 -8
- ksadk/model_policy.py +15 -7
- ksadk/model_proxy/__init__.py +51 -0
- ksadk/model_proxy/bootstrap.py +80 -0
- ksadk/model_proxy/cache.py +165 -0
- ksadk/model_proxy/config.py +45 -0
- ksadk/model_proxy/demo_webui.py +115 -0
- ksadk/model_proxy/detect.py +145 -0
- ksadk/model_proxy/gate.py +68 -0
- ksadk/model_proxy/namespace.py +173 -0
- ksadk/model_proxy/protocol_proxy.py +22 -0
- ksadk/model_proxy/server.py +300 -0
- ksadk/model_proxy/transform.py +691 -0
- ksadk/openclaw_gateway.py +29 -14
- ksadk/runners/adk_runner.py +1248 -164
- ksadk/runners/base_runner.py +46 -29
- ksadk/runners/codex_runner.py +132 -0
- ksadk/runners/deepagents_runner.py +0 -1
- ksadk/runners/factory.py +17 -5
- ksadk/runners/langchain_runner.py +29 -530
- ksadk/runners/langgraph_runner.py +490 -95
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +264 -38
- ksadk/runners/usage_accumulator.py +1 -0
- ksadk/runners/utils/langfuse.py +3 -3
- ksadk/runners/utils/loader.py +7 -7
- ksadk/runtime/__init__.py +41 -0
- ksadk/runtime/adapter.py +345 -0
- ksadk/runtime/framework_adapters.py +124 -0
- ksadk/runtime/preprocessing.py +118 -0
- ksadk/runtime/runner_adapter.py +873 -0
- ksadk/runtime_context.py +18 -3
- ksadk/runtime_state.py +0 -1
- ksadk/sandbox/__init__.py +4 -1
- ksadk/sandbox/backends/__init__.py +4 -1
- ksadk/sandbox/backends/e2b.py +13 -5
- ksadk/sandbox/backends/local_process.py +11 -3
- ksadk/sandbox/base.py +10 -15
- ksadk/sandbox/factory.py +14 -4
- ksadk/sandbox/registry.py +57 -6
- ksadk/server/api_models.py +15 -5
- ksadk/server/app.py +455 -3743
- ksadk/server/composition.py +21 -0
- ksadk/server/factory.py +624 -0
- ksadk/server/routes/__init__.py +1 -0
- ksadk/server/routes/checkpoint_resolution.py +116 -0
- ksadk/server/routes/common.py +713 -0
- ksadk/server/routes/control.py +327 -0
- ksadk/server/routes/dependencies.py +98 -0
- ksadk/server/routes/misc.py +448 -0
- ksadk/server/routes/models.py +443 -0
- ksadk/server/routes/openai_compat.py +207 -0
- ksadk/server/routes/projection.py +795 -0
- ksadk/server/routes/routers.py +52 -0
- ksadk/server/routes/run.py +726 -0
- ksadk/server/routes/sessions.py +649 -0
- ksadk/server/routes/streaming.py +223 -0
- ksadk/server/routes/workspace.py +381 -0
- ksadk/server/static/assets/{ArtifactsPanel-C0meuOdi.js → ArtifactsPanel-Cjnqt-8W.js} +1 -1
- ksadk/server/static/assets/CodeBlock-BqyqZfuB.js +9 -0
- ksadk/server/static/assets/MathMessageMarkdown-BpH7jiFM.js +8 -0
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +1 -0
- ksadk/server/static/assets/{arc-bj2rZnP5.js → arc-CFKwSk_B.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-2u1ltDIj.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-D6fvdK20.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-BK82L5n5.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
- ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-DLVdkeyQ.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-BbwsYcbW.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-DOairxzw.js → chunk-55IACEB6-BK8paA20.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-hCO487gs.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-XU8vDOuG.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-PrapyfMu.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-CboKhTZ3.js → chunk-ND2GUHAM-D98vPd-E.js} +1 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-_N8bJ-EU.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-FoDlo5J2.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BBp6ebBw.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-CqOvG1PR.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-O9T3t6ba.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-CGG8ekBO.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-4BmH1EEg.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
- ksadk/server/static/assets/{dist-CiZHB6ZW.js → dist-6CVKuTAe.js} +1 -1
- ksadk/server/static/assets/{dist-BMKM66B4.js → dist-BUHRxvDG.js} +1 -1
- ksadk/server/static/assets/{dist-CZ6C3x8B.js → dist-BZ9n9AjO.js} +1 -1
- ksadk/server/static/assets/{dist-DbaH3p5h.js → dist-BibcG1V9.js} +1 -1
- ksadk/server/static/assets/{dist-BVzcWa6D.js → dist-Bs-jQcRX.js} +1 -1
- ksadk/server/static/assets/{dist-D99wf6_X.js → dist-C2xjE7cO.js} +1 -1
- ksadk/server/static/assets/{dist-DLMjL01k.js → dist-C7-3jInC.js} +1 -1
- ksadk/server/static/assets/{dist-DI-oVAXw.js → dist-C99THtIA.js} +1 -1
- ksadk/server/static/assets/{dist-BkJjNih3.js → dist-CGcp2ex8.js} +1 -1
- ksadk/server/static/assets/{dist-D5JGcxBx.js → dist-CVQRZjPu.js} +1 -1
- ksadk/server/static/assets/{dist-CWiTDN_V.js → dist-Cf23NY4L.js} +1 -1
- ksadk/server/static/assets/{dist-DLeM1OCK.js → dist-CgF3fj15.js} +1 -1
- ksadk/server/static/assets/{dist-BmuTWcm7.js → dist-Cwt7koer.js} +1 -1
- ksadk/server/static/assets/{dist-C2DKRFVK.js → dist-D82mtD2s.js} +1 -1
- ksadk/server/static/assets/{dist-B67uF2uK.js → dist-DF06ORQo.js} +1 -1
- ksadk/server/static/assets/{dist-Cwhk4lwI.js → dist-DHn6nBzr.js} +1 -1
- ksadk/server/static/assets/{dist-S4klkK5W.js → dist-Djgl2wVZ.js} +1 -1
- ksadk/server/static/assets/{dist-DCpZrjaK.js → dist-DlzCRy0S.js} +1 -1
- ksadk/server/static/assets/{dist-Cp1_jKwf.js → dist-DqNnNFrw.js} +1 -1
- ksadk/server/static/assets/{dist-6kSZvCZh.js → dist-DyvYLMW9.js} +1 -1
- ksadk/server/static/assets/{dist-DM0rEQPk.js → dist-eoW6tZXA.js} +1 -1
- ksadk/server/static/assets/{dist-Bk1l05Ni.js → dist-ivOya1LD.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-oJhaci7S.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-DtTmUan-.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BSsb_eij.js → ganttDiagram-6RSMTGT7-DpCoB2g9.js} +1 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-BR5s6Pws.js → gitGraphDiagram-PVQCEYII-9IKVFBVT.js} +1 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +177 -0
- ksadk/server/static/assets/index-jOPmTOZH.css +2 -0
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +1 -0
- ksadk/server/static/assets/{infoDiagram-5YYISTIA-DYPc5cvh.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-MoBdALDg.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-DgLiQT8l.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-CsFx112F.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
- ksadk/server/static/assets/{katex-DRsiwpM2.js → katex-DATssjp1.js} +1 -1
- ksadk/server/static/assets/{linear-TNRQ5Orv.js → linear-CvMBw9cA.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-D2eMVOgo.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-BtByYFhL.js → mindmap-definition-RKZ34NQL-CSAQxEAe.js} +1 -1
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +1 -0
- ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPnuCB8c.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-miFpCPv4.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-mjB_yYkW.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-D7hSlZZZ.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-D9Cx6hC3.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-D_zrg47o.js → stateDiagram-AJRCARHV-DGpd9yFG.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +1 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-CwSec0Wa.js → timeline-definition-PNZ67QCA-jqoYs3jQ.js} +1 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +1 -0
- ksadk/server/static/assets/{vennDiagram-CIIHVFJN-agCVobiF.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-TmrlhWNt.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-DV71V-ah.js → xychartDiagram-2RQKCTM6-SkiH8GsK.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +111 -58
- ksadk/sessions/__init__.py +86 -40
- ksadk/sessions/base.py +31 -11
- ksadk/sessions/continuity.py +28 -5
- ksadk/sessions/in_memory.py +46 -2
- ksadk/sessions/local_service.py +148 -17
- ksadk/sessions/postgres_service.py +216 -35
- ksadk/sessions/resilience.py +52 -0
- ksadk/sessions/resilient.py +388 -0
- ksadk/skills/models.py +17 -5
- ksadk/skills/package_store.py +5 -2
- ksadk/skills/runtime/agent.py +20 -5
- ksadk/skills/runtime/artifacts.py +1 -5
- ksadk/skills/runtime/backends/e2b.py +10 -4
- ksadk/skills/runtime/backends/local.py +15 -3
- ksadk/skills/runtime/base.py +1 -2
- ksadk/skills/runtime/executor.py +10 -3
- ksadk/skills/runtime/factory.py +4 -2
- ksadk/skills/runtime/loader.py +1 -2
- ksadk/skills/runtime/registry.py +15 -10
- ksadk/skills/runtime/request.py +3 -1
- ksadk/skills/service_client.py +38 -17
- ksadk/skills/tool_defs.py +15 -10
- ksadk/terminal_exec_policy.py +3 -4
- ksadk/tools/gateway.py +92 -15
- ksadk/tools/result_budget.py +12 -4
- ksadk/toolsets/__init__.py +136 -36
- ksadk/toolsets/platform.py +21 -5
- ksadk/toolsets/sandbox.py +82 -16
- ksadk/toolsets/skills.py +200 -39
- ksadk/toolsets/web.py +123 -26
- ksadk/toolsets/workspace.py +264 -114
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/exporters/langfuse_exporter.py +91 -76
- ksadk/tracing/setup.py +132 -53
- ksadk/tracing/span_utils.py +5 -2
- ksadk/tui/__init__.py +22 -7
- ksadk/tui/loop.py +1925 -0
- ksadk/tui/stream_render.py +69 -0
- ksadk/ui_config.py +5 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
- agentengine_sdk_python-0.6.9.dist-info/RECORD +0 -487
- ksadk/server/static/assets/CodeBlock-BbI4HPtJ.js +0 -9
- ksadk/server/static/assets/MathMessageMarkdown-DMLQYoLp.js +0 -8
- ksadk/server/static/assets/MermaidBlock-DCR8WZ17.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-CKUvWhUz.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-Cr6Xz1_c.js +0 -1
- ksadk/server/static/assets/channel-BSSOwFIb.js +0 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-XXpdiwUL.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-C5HvGiyK.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-C5HvGiyK.js +0 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-CIgwHJLL.js +0 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BVAJ7uo0.js +0 -1
- ksadk/server/static/assets/index-BH7-pC0B.js +0 -165
- ksadk/server/static/assets/index-DAURbCsP.css +0 -1
- ksadk/server/static/assets/info-J43DQDTF-MT80V4ge.js +0 -1
- ksadk/server/static/assets/packet-YPE3B663-BLKhbXZB.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-DFOikjSY.js +0 -1
- ksadk/server/static/assets/radar-GUYGQ44K-095b1Ikw.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-J9kCb0nC.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-yinfJEY6.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-DosUqN1Q.js +0 -1
- ksadk/server/static/assets/wardley-L42UT6IY-Bvp7-5uH.js +0 -1
- ksadk/tui/app.py +0 -400
- ksadk/tui/clipboard.py +0 -100
- ksadk/tui/widgets/__init__.py +0 -22
- ksadk/tui/widgets/assistant.py +0 -89
- ksadk/tui/widgets/base.py +0 -54
- ksadk/tui/widgets/chat_input.py +0 -246
- ksadk/tui/widgets/history.py +0 -156
- ksadk/tui/widgets/system.py +0 -87
- ksadk/tui/widgets/thinking.py +0 -110
- ksadk/tui/widgets/tool_call.py +0 -161
- ksadk/tui/widgets/user.py +0 -37
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.6.9.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Any, Optional, cast
|
|
6
|
+
|
|
7
|
+
from ksadk.sessions.base import BaseSessionService, Session, SessionEvent, SessionState
|
|
8
|
+
from ksadk.sessions.in_memory import InMemorySessionService
|
|
9
|
+
from ksadk.sessions.resilience import is_session_backend_failure
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ResilientSessionService(BaseSessionService):
|
|
15
|
+
"""Keep live agent sessions available when durable persistence is unavailable.
|
|
16
|
+
|
|
17
|
+
The in-memory service is authoritative for the lifetime of this process. The
|
|
18
|
+
configured durable service is used as a read-through source and a best-effort
|
|
19
|
+
write-through sink. After its first failure it stays disabled until a
|
|
20
|
+
background probe confirms the durable backend is reachable again, at which
|
|
21
|
+
point it is re-enabled and an INFO log is emitted.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_probe_interval_seconds: float = 30.0
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
primary: BaseSessionService,
|
|
29
|
+
fallback: InMemorySessionService | None = None,
|
|
30
|
+
) -> None:
|
|
31
|
+
self.primary = primary
|
|
32
|
+
self.fallback = fallback or InMemorySessionService()
|
|
33
|
+
self._primary_enabled = True
|
|
34
|
+
self._hydrate_lock = asyncio.Lock()
|
|
35
|
+
self._primary_session_lock = asyncio.Lock()
|
|
36
|
+
self._primary_session_ids: set[str] = set()
|
|
37
|
+
self._probe_task: asyncio.Task[None] | None = None
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def degraded(self) -> bool:
|
|
41
|
+
return not self._primary_enabled
|
|
42
|
+
|
|
43
|
+
async def _call_primary(self, method_name: str, *args: Any, **kwargs: Any) -> tuple[bool, Any]:
|
|
44
|
+
if not self._primary_enabled:
|
|
45
|
+
return False, None
|
|
46
|
+
try:
|
|
47
|
+
method = getattr(self.primary, method_name)
|
|
48
|
+
return True, await method(*args, **kwargs)
|
|
49
|
+
except Exception as exc:
|
|
50
|
+
if not is_session_backend_failure(exc):
|
|
51
|
+
raise
|
|
52
|
+
self._disable_primary(exc)
|
|
53
|
+
return False, None
|
|
54
|
+
|
|
55
|
+
def _disable_primary(self, exc: Exception) -> None:
|
|
56
|
+
if not self._primary_enabled:
|
|
57
|
+
return
|
|
58
|
+
self._primary_enabled = False
|
|
59
|
+
logger.error(
|
|
60
|
+
"KSADK session persistence degraded; using in-memory live session: %s",
|
|
61
|
+
exc,
|
|
62
|
+
extra={
|
|
63
|
+
"session_backend_state": "degraded",
|
|
64
|
+
"session_backend": type(self.primary).__name__,
|
|
65
|
+
},
|
|
66
|
+
)
|
|
67
|
+
self._start_probe()
|
|
68
|
+
|
|
69
|
+
def _start_probe(self) -> None:
|
|
70
|
+
if self._probe_task is not None and not self._probe_task.done():
|
|
71
|
+
return
|
|
72
|
+
self._probe_task = asyncio.create_task(self._probe_loop())
|
|
73
|
+
|
|
74
|
+
async def _probe_loop(self) -> None:
|
|
75
|
+
while not self._primary_enabled:
|
|
76
|
+
await asyncio.sleep(self._probe_interval_seconds)
|
|
77
|
+
if self._primary_enabled:
|
|
78
|
+
break
|
|
79
|
+
try:
|
|
80
|
+
await self.primary.get_session("__ksadk_probe__")
|
|
81
|
+
except Exception:
|
|
82
|
+
continue
|
|
83
|
+
self._primary_enabled = True
|
|
84
|
+
logger.info(
|
|
85
|
+
"KSADK session persistence recovered; durable backend re-enabled",
|
|
86
|
+
extra={
|
|
87
|
+
"session_backend_state": "recovered",
|
|
88
|
+
"session_backend": type(self.primary).__name__,
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def _hydrate(self, session: Session) -> Session:
|
|
93
|
+
async with self._hydrate_lock:
|
|
94
|
+
self._primary_session_ids.add(session.id)
|
|
95
|
+
existing = await self.fallback.get_session(session.id)
|
|
96
|
+
if existing is None:
|
|
97
|
+
await self.fallback.create_session(
|
|
98
|
+
session.agent_id,
|
|
99
|
+
session.user_id,
|
|
100
|
+
session_id=session.id,
|
|
101
|
+
)
|
|
102
|
+
existing_events = await self.fallback.get_events(session.id)
|
|
103
|
+
existing_ids = {event.id for event in existing_events}
|
|
104
|
+
for event in sorted(session.events, key=lambda item: item.seq_id):
|
|
105
|
+
if event.id not in existing_ids:
|
|
106
|
+
await self.fallback.append_event(session.id, event)
|
|
107
|
+
await self.fallback.update_session_metadata(
|
|
108
|
+
session.id,
|
|
109
|
+
title=session.title,
|
|
110
|
+
title_source=session.title_source,
|
|
111
|
+
summary=session.summary,
|
|
112
|
+
first_prompt=session.first_prompt,
|
|
113
|
+
last_prompt=session.last_prompt,
|
|
114
|
+
)
|
|
115
|
+
current = await self.fallback.get_session(session.id)
|
|
116
|
+
if current is not None and session.state != current.state:
|
|
117
|
+
await self.fallback.update_state(
|
|
118
|
+
agent_id=session.agent_id,
|
|
119
|
+
user_id=session.user_id,
|
|
120
|
+
session_id=session.id,
|
|
121
|
+
scope="session",
|
|
122
|
+
state_delta=session.state,
|
|
123
|
+
)
|
|
124
|
+
hydrated = await self.fallback.get_session(session.id)
|
|
125
|
+
if hydrated is None:
|
|
126
|
+
raise RuntimeError(f"Failed to hydrate live session {session.id}")
|
|
127
|
+
return hydrated
|
|
128
|
+
|
|
129
|
+
async def create_session(
|
|
130
|
+
self,
|
|
131
|
+
agent_id: str,
|
|
132
|
+
user_id: str,
|
|
133
|
+
session_id: Optional[str] = None,
|
|
134
|
+
) -> Session:
|
|
135
|
+
if session_id:
|
|
136
|
+
ok, durable = await self._call_primary("get_session", session_id)
|
|
137
|
+
if ok and durable is not None:
|
|
138
|
+
return await self._hydrate(durable)
|
|
139
|
+
existing = await self.fallback.get_session(session_id)
|
|
140
|
+
if existing is not None:
|
|
141
|
+
return existing
|
|
142
|
+
|
|
143
|
+
live = await self.fallback.create_session(agent_id, user_id, session_id=session_id)
|
|
144
|
+
ok, durable = await self._call_primary(
|
|
145
|
+
"create_session",
|
|
146
|
+
agent_id,
|
|
147
|
+
user_id,
|
|
148
|
+
session_id=live.id,
|
|
149
|
+
)
|
|
150
|
+
if ok and durable is not None:
|
|
151
|
+
self._primary_session_ids.add(durable.id)
|
|
152
|
+
return await self._hydrate(durable)
|
|
153
|
+
return live
|
|
154
|
+
|
|
155
|
+
async def get_session(self, session_id: str) -> Optional[Session]:
|
|
156
|
+
live = await self.fallback.get_session(session_id)
|
|
157
|
+
ok, durable = await self._call_primary("get_session", session_id)
|
|
158
|
+
if ok and durable is not None:
|
|
159
|
+
return await self._hydrate(durable)
|
|
160
|
+
return live
|
|
161
|
+
|
|
162
|
+
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
163
|
+
ok, durable = await self._call_primary("get_session_metadata", session_id)
|
|
164
|
+
if ok and durable is not None:
|
|
165
|
+
return cast(Session, durable)
|
|
166
|
+
return await self.fallback.get_session_metadata(session_id)
|
|
167
|
+
|
|
168
|
+
async def list_sessions(
|
|
169
|
+
self,
|
|
170
|
+
agent_id: str,
|
|
171
|
+
user_id: Optional[str] = None,
|
|
172
|
+
offset: Optional[int] = None,
|
|
173
|
+
limit: Optional[int] = None,
|
|
174
|
+
) -> list[Session]:
|
|
175
|
+
ok, durable_sessions = await self._call_primary(
|
|
176
|
+
"list_sessions",
|
|
177
|
+
agent_id,
|
|
178
|
+
user_id,
|
|
179
|
+
offset,
|
|
180
|
+
limit,
|
|
181
|
+
)
|
|
182
|
+
if ok:
|
|
183
|
+
return cast(list[Session], durable_sessions or [])
|
|
184
|
+
return await self.fallback.list_sessions(agent_id, user_id, offset, limit)
|
|
185
|
+
|
|
186
|
+
async def count_sessions(self, agent_id: str, user_id: Optional[str] = None) -> int:
|
|
187
|
+
ok, total = await self._call_primary("count_sessions", agent_id, user_id)
|
|
188
|
+
if ok:
|
|
189
|
+
return int(total or 0)
|
|
190
|
+
return await self.fallback.count_sessions(agent_id, user_id)
|
|
191
|
+
|
|
192
|
+
async def delete_session(self, session_id: str) -> bool:
|
|
193
|
+
deleted = await self.fallback.delete_session(session_id)
|
|
194
|
+
ok, durable_deleted = await self._call_primary("delete_session", session_id)
|
|
195
|
+
if ok:
|
|
196
|
+
self._primary_session_ids.discard(session_id)
|
|
197
|
+
return deleted or bool(durable_deleted) if ok else deleted
|
|
198
|
+
|
|
199
|
+
async def update_session_metadata(
|
|
200
|
+
self,
|
|
201
|
+
session_id: str,
|
|
202
|
+
*,
|
|
203
|
+
title: Optional[str] = None,
|
|
204
|
+
title_source: Optional[str] = None,
|
|
205
|
+
summary: Optional[str] = None,
|
|
206
|
+
first_prompt: Optional[str] = None,
|
|
207
|
+
last_prompt: Optional[str] = None,
|
|
208
|
+
) -> Session:
|
|
209
|
+
if await self.fallback.get_session(session_id) is None:
|
|
210
|
+
await self.get_session(session_id)
|
|
211
|
+
live = await self.fallback.update_session_metadata(
|
|
212
|
+
session_id,
|
|
213
|
+
title=title,
|
|
214
|
+
title_source=title_source,
|
|
215
|
+
summary=summary,
|
|
216
|
+
first_prompt=first_prompt,
|
|
217
|
+
last_prompt=last_prompt,
|
|
218
|
+
)
|
|
219
|
+
await self._ensure_primary_session(session_id)
|
|
220
|
+
await self._call_primary(
|
|
221
|
+
"update_session_metadata",
|
|
222
|
+
session_id,
|
|
223
|
+
title=title,
|
|
224
|
+
title_source=title_source,
|
|
225
|
+
summary=summary,
|
|
226
|
+
first_prompt=first_prompt,
|
|
227
|
+
last_prompt=last_prompt,
|
|
228
|
+
)
|
|
229
|
+
return live
|
|
230
|
+
|
|
231
|
+
async def _ensure_primary_session(self, session_id: str) -> None:
|
|
232
|
+
"""Create the session in PG if it only exists in memory (degraded-era)."""
|
|
233
|
+
if not self._primary_enabled or session_id in self._primary_session_ids:
|
|
234
|
+
return
|
|
235
|
+
async with self._primary_session_lock:
|
|
236
|
+
if not self._primary_enabled or session_id in self._primary_session_ids:
|
|
237
|
+
return
|
|
238
|
+
ok, durable = await self._call_primary("get_session", session_id)
|
|
239
|
+
if not ok:
|
|
240
|
+
return
|
|
241
|
+
if durable is None:
|
|
242
|
+
live = await self.fallback.get_session(session_id)
|
|
243
|
+
if live is None:
|
|
244
|
+
return
|
|
245
|
+
ok, durable = await self._call_primary(
|
|
246
|
+
"create_session",
|
|
247
|
+
live.agent_id,
|
|
248
|
+
live.user_id,
|
|
249
|
+
session_id=live.id,
|
|
250
|
+
)
|
|
251
|
+
if not ok or durable is None:
|
|
252
|
+
return
|
|
253
|
+
self._primary_session_ids.add(session_id)
|
|
254
|
+
|
|
255
|
+
async def append_event(self, session_id: str, event: SessionEvent) -> SessionEvent:
|
|
256
|
+
if await self.fallback.get_session(session_id) is None:
|
|
257
|
+
await self.get_session(session_id)
|
|
258
|
+
live = await self.fallback.append_event(session_id, event)
|
|
259
|
+
await self._ensure_primary_session(session_id)
|
|
260
|
+
await self._call_primary("append_event", session_id, event)
|
|
261
|
+
return live
|
|
262
|
+
|
|
263
|
+
async def get_events(
|
|
264
|
+
self,
|
|
265
|
+
session_id: str,
|
|
266
|
+
offset: Optional[int] = None,
|
|
267
|
+
limit: Optional[int] = None,
|
|
268
|
+
after_seq_id: Optional[int] = None,
|
|
269
|
+
before_seq_id: Optional[int] = None,
|
|
270
|
+
) -> list[SessionEvent]:
|
|
271
|
+
await self.get_session(session_id)
|
|
272
|
+
return cast(
|
|
273
|
+
list[SessionEvent],
|
|
274
|
+
await self.fallback.get_events(
|
|
275
|
+
session_id,
|
|
276
|
+
offset,
|
|
277
|
+
limit,
|
|
278
|
+
after_seq_id,
|
|
279
|
+
before_seq_id,
|
|
280
|
+
),
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
async def count_events(
|
|
284
|
+
self,
|
|
285
|
+
session_id: str,
|
|
286
|
+
after_seq_id: Optional[int] = None,
|
|
287
|
+
before_seq_id: Optional[int] = None,
|
|
288
|
+
) -> int:
|
|
289
|
+
await self.get_session(session_id)
|
|
290
|
+
return cast(
|
|
291
|
+
int,
|
|
292
|
+
await self.fallback.count_events(session_id, after_seq_id, before_seq_id),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
async def get_events_for_agent(
|
|
296
|
+
self,
|
|
297
|
+
agent_id: str,
|
|
298
|
+
user_id: Optional[str] = None,
|
|
299
|
+
offset: Optional[int] = None,
|
|
300
|
+
limit: Optional[int] = None,
|
|
301
|
+
) -> list[SessionEvent]:
|
|
302
|
+
ok, events = await self._call_primary(
|
|
303
|
+
"get_events_for_agent", agent_id, user_id, offset, limit
|
|
304
|
+
)
|
|
305
|
+
if ok:
|
|
306
|
+
return cast(list[SessionEvent], events)
|
|
307
|
+
return await self.fallback.get_events_for_agent(agent_id, user_id, offset, limit)
|
|
308
|
+
|
|
309
|
+
async def count_events_for_agent(
|
|
310
|
+
self,
|
|
311
|
+
agent_id: str,
|
|
312
|
+
user_id: Optional[str] = None,
|
|
313
|
+
) -> int:
|
|
314
|
+
ok, total = await self._call_primary("count_events_for_agent", agent_id, user_id)
|
|
315
|
+
if ok:
|
|
316
|
+
return int(total or 0)
|
|
317
|
+
return await self.fallback.count_events_for_agent(agent_id, user_id)
|
|
318
|
+
|
|
319
|
+
async def get_state(
|
|
320
|
+
self,
|
|
321
|
+
agent_id: str,
|
|
322
|
+
user_id: Optional[str],
|
|
323
|
+
session_id: Optional[str],
|
|
324
|
+
scope: str = "session",
|
|
325
|
+
) -> Optional[SessionState]:
|
|
326
|
+
if session_id:
|
|
327
|
+
await self.get_session(session_id)
|
|
328
|
+
live = await self.fallback.get_state(agent_id, user_id, session_id, scope)
|
|
329
|
+
if live is not None or not self._primary_enabled:
|
|
330
|
+
return live
|
|
331
|
+
ok, durable = await self._call_primary(
|
|
332
|
+
"get_state",
|
|
333
|
+
agent_id,
|
|
334
|
+
user_id,
|
|
335
|
+
session_id,
|
|
336
|
+
scope,
|
|
337
|
+
)
|
|
338
|
+
if ok and durable is not None:
|
|
339
|
+
return await self.fallback.update_state(
|
|
340
|
+
agent_id=agent_id,
|
|
341
|
+
user_id=user_id,
|
|
342
|
+
session_id=session_id,
|
|
343
|
+
scope=scope,
|
|
344
|
+
state_delta=durable.state,
|
|
345
|
+
)
|
|
346
|
+
return live
|
|
347
|
+
|
|
348
|
+
async def update_state(
|
|
349
|
+
self,
|
|
350
|
+
*,
|
|
351
|
+
agent_id: str,
|
|
352
|
+
user_id: Optional[str],
|
|
353
|
+
session_id: Optional[str],
|
|
354
|
+
scope: str,
|
|
355
|
+
state_delta: dict[str, Any],
|
|
356
|
+
) -> SessionState:
|
|
357
|
+
if session_id and await self.fallback.get_session(session_id) is None:
|
|
358
|
+
await self.get_session(session_id)
|
|
359
|
+
live = await self.fallback.update_state(
|
|
360
|
+
agent_id=agent_id,
|
|
361
|
+
user_id=user_id,
|
|
362
|
+
session_id=session_id,
|
|
363
|
+
scope=scope,
|
|
364
|
+
state_delta=state_delta,
|
|
365
|
+
)
|
|
366
|
+
if session_id:
|
|
367
|
+
await self._ensure_primary_session(session_id)
|
|
368
|
+
await self._call_primary(
|
|
369
|
+
"update_state",
|
|
370
|
+
agent_id=agent_id,
|
|
371
|
+
user_id=user_id,
|
|
372
|
+
session_id=session_id,
|
|
373
|
+
scope=scope,
|
|
374
|
+
state_delta=state_delta,
|
|
375
|
+
)
|
|
376
|
+
return live
|
|
377
|
+
|
|
378
|
+
async def aclose(self) -> None:
|
|
379
|
+
if self._probe_task is not None and not self._probe_task.done():
|
|
380
|
+
self._probe_task.cancel()
|
|
381
|
+
try:
|
|
382
|
+
await self._probe_task
|
|
383
|
+
except asyncio.CancelledError:
|
|
384
|
+
pass
|
|
385
|
+
for service in (self.primary, self.fallback):
|
|
386
|
+
close = getattr(service, "aclose", None)
|
|
387
|
+
if close is not None:
|
|
388
|
+
await close()
|
ksadk/skills/models.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import Iterable
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
@@ -48,7 +49,9 @@ class SkillRef:
|
|
|
48
49
|
name=str(payload.get("Name") or payload.get("name") or ""),
|
|
49
50
|
description=str(payload.get("Description") or payload.get("description") or ""),
|
|
50
51
|
status=str(payload.get("Status") or payload.get("status") or ""),
|
|
51
|
-
content_hash=ContentHash.parse(
|
|
52
|
+
content_hash=ContentHash.parse(
|
|
53
|
+
payload.get("ContentHash") or payload.get("content_hash")
|
|
54
|
+
),
|
|
52
55
|
archive_uri=str(payload.get("ArchiveUri") or payload.get("archive_uri") or ""),
|
|
53
56
|
aliases=_string_tuple(payload.get("Aliases") or payload.get("aliases")),
|
|
54
57
|
tags=_string_tuple(payload.get("Tags") or payload.get("tags")),
|
|
@@ -65,7 +68,9 @@ class SkillRef:
|
|
|
65
68
|
version_key = self.version_id or self.version
|
|
66
69
|
if not version_key and self.content_hash:
|
|
67
70
|
version_key = self.content_hash.value
|
|
68
|
-
return "__".join(
|
|
71
|
+
return "__".join(
|
|
72
|
+
part.replace("/", "_").replace(":", "_") for part in (identity, version_key) if part
|
|
73
|
+
)
|
|
69
74
|
|
|
70
75
|
@property
|
|
71
76
|
def is_active(self) -> bool:
|
|
@@ -90,14 +95,20 @@ class SkillListResponse:
|
|
|
90
95
|
space_name: str = "",
|
|
91
96
|
) -> "SkillListResponse":
|
|
92
97
|
data = payload.get("Data") or payload.get("data") or {}
|
|
93
|
-
skills_payload =
|
|
98
|
+
skills_payload = (
|
|
99
|
+
data.get("Skills") or data.get("skills") or data.get("Items") or data.get("items") or []
|
|
100
|
+
)
|
|
94
101
|
return cls(
|
|
95
102
|
code=int(payload.get("Code") or payload.get("code") or 0),
|
|
96
103
|
message=str(payload.get("Message") or payload.get("message") or ""),
|
|
97
104
|
request_id=str(payload.get("RequestId") or payload.get("request_id") or ""),
|
|
98
105
|
space_id=str(data.get("SkillSpaceId") or data.get("skill_space_id") or space_id),
|
|
99
|
-
space_name=str(
|
|
100
|
-
|
|
106
|
+
space_name=str(
|
|
107
|
+
data.get("SkillSpaceName") or data.get("skill_space_name") or space_name
|
|
108
|
+
),
|
|
109
|
+
skills=[
|
|
110
|
+
SkillRef.from_payload(item) for item in skills_payload if isinstance(item, dict)
|
|
111
|
+
],
|
|
101
112
|
)
|
|
102
113
|
|
|
103
114
|
def active_skills(self) -> list[SkillRef]:
|
|
@@ -107,6 +118,7 @@ class SkillListResponse:
|
|
|
107
118
|
def _string_tuple(raw: Any) -> tuple[str, ...]:
|
|
108
119
|
if raw is None:
|
|
109
120
|
return ()
|
|
121
|
+
values: Iterable[Any]
|
|
110
122
|
if isinstance(raw, str):
|
|
111
123
|
values = raw.split(",")
|
|
112
124
|
elif isinstance(raw, (list, tuple, set)):
|
ksadk/skills/package_store.py
CHANGED
|
@@ -79,11 +79,14 @@ class PackageStore:
|
|
|
79
79
|
if not ref.content_hash:
|
|
80
80
|
return
|
|
81
81
|
if ref.content_hash.algorithm != "sha256":
|
|
82
|
-
raise SkillPackageError(
|
|
82
|
+
raise SkillPackageError(
|
|
83
|
+
f"Unsupported ContentHash algorithm: {ref.content_hash.algorithm}"
|
|
84
|
+
)
|
|
83
85
|
actual = hashlib.sha256(content).hexdigest()
|
|
84
86
|
if actual.lower() != ref.content_hash.value.lower():
|
|
85
87
|
raise SkillPackageError(
|
|
86
|
-
f"ContentHash mismatch for {ref.name}: expected
|
|
88
|
+
f"ContentHash mismatch for {ref.name}: expected "
|
|
89
|
+
f"{ref.content_hash.render()}, got sha256:{actual}"
|
|
87
90
|
)
|
|
88
91
|
|
|
89
92
|
def _safe_extract(self, archive_path: Path, extract_dir: Path) -> None:
|
ksadk/skills/runtime/agent.py
CHANGED
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
-
import subprocess
|
|
6
5
|
import sys
|
|
7
6
|
from dataclasses import asdict
|
|
8
7
|
from pathlib import Path
|
|
@@ -12,15 +11,29 @@ import httpx
|
|
|
12
11
|
from ksadk.skills.loader import LocalSkill
|
|
13
12
|
from ksadk.skills.models import SkillRef
|
|
14
13
|
from ksadk.skills.package_store import PackageStore
|
|
14
|
+
from ksadk.skills.runtime import loader as runtime_loader
|
|
15
|
+
from ksadk.skills.runtime import registry as runtime_registry
|
|
15
16
|
from ksadk.skills.runtime.base import normalize_skill_names
|
|
16
17
|
from ksadk.skills.runtime.executor import (
|
|
17
18
|
WorkflowExecution,
|
|
18
19
|
execute_workflow,
|
|
20
|
+
)
|
|
21
|
+
from ksadk.skills.runtime.executor import (
|
|
19
22
|
_can_run_web_artifacts_builder as _executor_can_run_web_artifacts_builder,
|
|
23
|
+
)
|
|
24
|
+
from ksadk.skills.runtime.executor import (
|
|
20
25
|
_run_command as _executor_run_command,
|
|
26
|
+
)
|
|
27
|
+
from ksadk.skills.runtime.executor import (
|
|
21
28
|
_run_web_artifacts_builder as _executor_run_web_artifacts_builder,
|
|
29
|
+
)
|
|
30
|
+
from ksadk.skills.runtime.executor import (
|
|
22
31
|
_runtime_timeout as _executor_runtime_timeout,
|
|
32
|
+
)
|
|
33
|
+
from ksadk.skills.runtime.executor import (
|
|
23
34
|
_safe_project_name as _executor_safe_project_name,
|
|
35
|
+
)
|
|
36
|
+
from ksadk.skills.runtime.executor import (
|
|
24
37
|
_tail as _executor_tail,
|
|
25
38
|
)
|
|
26
39
|
from ksadk.skills.runtime.request import (
|
|
@@ -28,8 +41,6 @@ from ksadk.skills.runtime.request import (
|
|
|
28
41
|
SkillWorkflowRequestError,
|
|
29
42
|
parse_workflow_request,
|
|
30
43
|
)
|
|
31
|
-
from ksadk.skills.runtime import loader as runtime_loader
|
|
32
|
-
from ksadk.skills.runtime import registry as runtime_registry
|
|
33
44
|
|
|
34
45
|
|
|
35
46
|
def _skill_space_ids() -> list[str]:
|
|
@@ -109,7 +120,9 @@ def run_agent(
|
|
|
109
120
|
print("workflow=")
|
|
110
121
|
print(f"skill_spaces={','.join(_skill_space_ids())}")
|
|
111
122
|
print("loaded_skills=")
|
|
112
|
-
print(
|
|
123
|
+
print(
|
|
124
|
+
f"workflow_result={json.dumps(asdict(execution), ensure_ascii=False, sort_keys=True)}"
|
|
125
|
+
)
|
|
113
126
|
return 1
|
|
114
127
|
|
|
115
128
|
prompt = request.workflow_prompt
|
|
@@ -125,7 +138,9 @@ def run_agent(
|
|
|
125
138
|
print(f"loaded_skills={','.join(skill.name for skill in loaded_skills)}")
|
|
126
139
|
print(f"selected_skills={json.dumps(selected_skill_names, ensure_ascii=False, sort_keys=True)}")
|
|
127
140
|
if _SKILL_LOAD_WARNINGS:
|
|
128
|
-
print(
|
|
141
|
+
print(
|
|
142
|
+
f"skill_warnings={json.dumps(_SKILL_LOAD_WARNINGS, ensure_ascii=False, sort_keys=True)}"
|
|
143
|
+
)
|
|
129
144
|
print(f"workflow_result={json.dumps(asdict(execution), ensure_ascii=False, sort_keys=True)}")
|
|
130
145
|
return 0 if execution.status != "failed" else 1
|
|
131
146
|
|
|
@@ -20,11 +20,7 @@ def parse_artifact_lines(stdout: str) -> list[str]:
|
|
|
20
20
|
def collect_output_dir_artifacts(output_dir: Path) -> list[str]:
|
|
21
21
|
if not output_dir.is_dir():
|
|
22
22
|
return []
|
|
23
|
-
return [
|
|
24
|
-
str(path)
|
|
25
|
-
for path in sorted(output_dir.rglob("*"))
|
|
26
|
-
if path.is_file()
|
|
27
|
-
]
|
|
23
|
+
return [str(path) for path in sorted(output_dir.rglob("*")) if path.is_file()]
|
|
28
24
|
|
|
29
25
|
|
|
30
26
|
def merge_artifacts(*groups: list[str]) -> list[str]:
|
|
@@ -7,9 +7,11 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from ksadk.sandbox import (
|
|
9
9
|
E2BSandboxBackend,
|
|
10
|
-
SandboxInputFile as RuntimeSandboxInputFile,
|
|
11
10
|
SandboxSpec,
|
|
12
11
|
)
|
|
12
|
+
from ksadk.sandbox import (
|
|
13
|
+
SandboxInputFile as RuntimeSandboxInputFile,
|
|
14
|
+
)
|
|
13
15
|
from ksadk.skills.runtime.base import (
|
|
14
16
|
SandboxInputFile,
|
|
15
17
|
SkillRuntimeError,
|
|
@@ -75,10 +77,10 @@ class E2BSkillRuntimeBackend:
|
|
|
75
77
|
@classmethod
|
|
76
78
|
def from_env(cls) -> "E2BSkillRuntimeBackend":
|
|
77
79
|
try:
|
|
78
|
-
from e2b import Sandbox
|
|
80
|
+
from e2b import Sandbox # type: ignore[import-untyped]
|
|
79
81
|
except ImportError as exc:
|
|
80
82
|
raise SkillRuntimeError(
|
|
81
|
-
"e2b>=2.
|
|
83
|
+
"e2b>=2.15.3,<2.25.0 is required for KSADK_SKILL_RUNTIME_BACKEND=e2b"
|
|
82
84
|
) from exc
|
|
83
85
|
return cls(
|
|
84
86
|
sandbox_cls=Sandbox,
|
|
@@ -87,7 +89,11 @@ class E2BSkillRuntimeBackend:
|
|
|
87
89
|
or os.environ.get("KSADK_SKILL_RUNTIME_TEMPLATE_ID")
|
|
88
90
|
or ""
|
|
89
91
|
),
|
|
90
|
-
timeout=int(
|
|
92
|
+
timeout=int(
|
|
93
|
+
os.environ.get("KSADK_SANDBOX_TIMEOUT")
|
|
94
|
+
or os.environ.get("KSADK_SKILL_RUNTIME_TIMEOUT")
|
|
95
|
+
or "900"
|
|
96
|
+
),
|
|
91
97
|
allow_internet_access=_bool_env(
|
|
92
98
|
"KSADK_SANDBOX_ALLOW_INTERNET_ACCESS",
|
|
93
99
|
_bool_env("KSADK_SKILL_RUNTIME_ALLOW_INTERNET_ACCESS", True),
|
|
@@ -17,6 +17,12 @@ from ksadk.skills.runtime.base import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def _coerce_output(value: str | bytes | None) -> str:
|
|
21
|
+
if isinstance(value, bytes):
|
|
22
|
+
return value.decode("utf-8", errors="replace")
|
|
23
|
+
return value or ""
|
|
24
|
+
|
|
25
|
+
|
|
20
26
|
class LocalProcessSkillRuntimeBackend:
|
|
21
27
|
def __init__(self, agent_path: str | Path, timeout: int = 900):
|
|
22
28
|
self.agent_path = Path(agent_path)
|
|
@@ -67,7 +73,13 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
67
73
|
encoding="utf-8",
|
|
68
74
|
)
|
|
69
75
|
completed = subprocess.run(
|
|
70
|
-
[
|
|
76
|
+
[
|
|
77
|
+
sys.executable,
|
|
78
|
+
"-u",
|
|
79
|
+
str(self.agent_path),
|
|
80
|
+
"--request-file",
|
|
81
|
+
str(request_path),
|
|
82
|
+
],
|
|
71
83
|
text=True,
|
|
72
84
|
capture_output=True,
|
|
73
85
|
timeout=timeout or self.timeout,
|
|
@@ -86,8 +98,8 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
86
98
|
return SkillRuntimeResult(
|
|
87
99
|
runtime_id=f"local:{session_id}",
|
|
88
100
|
exit_code=None,
|
|
89
|
-
stdout=exc.stdout
|
|
90
|
-
stderr=exc.stderr
|
|
101
|
+
stdout=_coerce_output(exc.stdout),
|
|
102
|
+
stderr=_coerce_output(exc.stderr),
|
|
91
103
|
duration_ms=int((time.monotonic() - started) * 1000),
|
|
92
104
|
timed_out=True,
|
|
93
105
|
error_type="TimeoutExpired",
|
ksadk/skills/runtime/base.py
CHANGED
|
@@ -57,8 +57,7 @@ class SkillRuntimeBackend(Protocol):
|
|
|
57
57
|
env: dict[str, str] | None = None,
|
|
58
58
|
input_files: list[SandboxInputFile] | None = None,
|
|
59
59
|
timeout: int = 900,
|
|
60
|
-
) -> SkillRuntimeResult:
|
|
61
|
-
...
|
|
60
|
+
) -> SkillRuntimeResult: ...
|
|
62
61
|
|
|
63
62
|
|
|
64
63
|
def parse_output_files(stdout: str) -> list[str]:
|
ksadk/skills/runtime/executor.py
CHANGED
|
@@ -82,7 +82,10 @@ def _can_run_web_artifacts_builder(skill: LocalSkill, prompt: str) -> bool:
|
|
|
82
82
|
if not init_script.exists() or not bundle_script.exists():
|
|
83
83
|
return False
|
|
84
84
|
normalized = prompt.lower()
|
|
85
|
-
return any(
|
|
85
|
+
return any(
|
|
86
|
+
marker in normalized
|
|
87
|
+
for marker in ("web-artifacts-builder", "artifact", "bundle", "html", "react")
|
|
88
|
+
)
|
|
86
89
|
|
|
87
90
|
|
|
88
91
|
def _can_run_generic_workflow(skill: LocalSkill) -> bool:
|
|
@@ -91,7 +94,9 @@ def _can_run_generic_workflow(skill: LocalSkill) -> bool:
|
|
|
91
94
|
|
|
92
95
|
def _run_web_artifacts_builder(skill: LocalSkill) -> WorkflowExecution:
|
|
93
96
|
workdir = _skill_workdir()
|
|
94
|
-
project_name = _safe_project_name(
|
|
97
|
+
project_name = _safe_project_name(
|
|
98
|
+
os.environ.get("KSADK_SKILL_ARTIFACT_PROJECT") or "ksadk-artifact"
|
|
99
|
+
)
|
|
95
100
|
project_dir = workdir / project_name
|
|
96
101
|
workdir.mkdir(parents=True, exist_ok=True)
|
|
97
102
|
if project_dir.exists():
|
|
@@ -114,7 +119,9 @@ def _run_web_artifacts_builder(skill: LocalSkill) -> WorkflowExecution:
|
|
|
114
119
|
timeout=timeout,
|
|
115
120
|
)
|
|
116
121
|
commands.append(bundle_result)
|
|
117
|
-
output_files =
|
|
122
|
+
output_files = (
|
|
123
|
+
[str(project_dir / "bundle.html")] if (project_dir / "bundle.html").exists() else []
|
|
124
|
+
)
|
|
118
125
|
status = "ok" if bundle_result["exit_code"] == 0 and output_files else "failed"
|
|
119
126
|
return WorkflowExecution(
|
|
120
127
|
status=status,
|