agentengine-sdk-python 0.7.0__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.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/METADATA +36 -20
- 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 +233 -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 +500 -720
- 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 +168 -89
- ksadk/cli/cmd_invoke.py +184 -122
- ksadk/cli/cmd_launch.py +64 -28
- ksadk/cli/cmd_mcp.py +98 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +483 -227
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +33 -10
- 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 +34 -14
- 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 +500 -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 +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 +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 +51 -38
- ksadk/deployment/manager.py +63 -65
- ksadk/deployment/providers/serverless.py +309 -202
- 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 +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 +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 +345 -120
- 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 -742
- ksadk/runners/langgraph_runner.py +352 -90
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +134 -33
- 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 -3885
- 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-D-SSn2ee.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-BA13sHc9.js → arc-CFKwSk_B.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-Dej8jX8c.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-1F64jqvy.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-9q7AUAKb.js} +1 -1
- ksadk/server/static/assets/channel-iUGv2N24.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-6qgwJm7Q.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-CsWIQRhc.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-BK8paA20.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B-JEhy7h.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-DYBvMHAa.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-BGhvzDYt.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.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-Zhy2GBnP.js → cose-bilkent-S5V4N54A-CX3yotHq.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-C7TguAWo.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-Dd17_kws.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-DVIClIil.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Df_3gYQa.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-BhLk6ZtA.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-D4GNGvuu.js} +1 -1
- ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-6CVKuTAe.js} +1 -1
- ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-BUHRxvDG.js} +1 -1
- ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-BZ9n9AjO.js} +1 -1
- ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BibcG1V9.js} +1 -1
- ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-Bs-jQcRX.js} +1 -1
- ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-C2xjE7cO.js} +1 -1
- ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-C7-3jInC.js} +1 -1
- ksadk/server/static/assets/{dist-D-xOD048.js → dist-C99THtIA.js} +1 -1
- ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-CGcp2ex8.js} +1 -1
- ksadk/server/static/assets/{dist-DyOkZmze.js → dist-CVQRZjPu.js} +1 -1
- ksadk/server/static/assets/{dist-BssVmjIo.js → dist-Cf23NY4L.js} +1 -1
- ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-CgF3fj15.js} +1 -1
- ksadk/server/static/assets/{dist-2hInLS_J.js → dist-Cwt7koer.js} +1 -1
- ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-D82mtD2s.js} +1 -1
- ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-DF06ORQo.js} +1 -1
- ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-DHn6nBzr.js} +1 -1
- ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-Djgl2wVZ.js} +1 -1
- ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-DlzCRy0S.js} +1 -1
- ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-DqNnNFrw.js} +1 -1
- ksadk/server/static/assets/{dist-D57wnGWd.js → dist-DyvYLMW9.js} +1 -1
- ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-eoW6tZXA.js} +1 -1
- ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-ivOya1LD.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-CnfRcY2M.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-DGaJjGNJ.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.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-C7Q0X-wi.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-BO_CSqq5.js → infoDiagram-5YYISTIA-CYIIsb8y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-DLOHGvWw.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-BIzKeejT.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-BWHoFSw2.js} +1 -1
- ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-DATssjp1.js} +1 -1
- ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-CvMBw9cA.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-mGAcEwcq.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.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-DPv_VstN.js → pieDiagram-4H26LBE5-By-ra07M.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-CxIR4JXI.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DpW90iu3.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-DpGa6EAV.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-NTKNGGe5.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.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-FbCTGrf9.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-DWgwtPsJ.js → vennDiagram-CIIHVFJN-l3Z7-wbP.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-BR54GPmr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.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 +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 +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 +134 -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 +212 -101
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/exporters/langfuse_exporter.py +91 -76
- ksadk/tracing/setup.py +69 -53
- ksadk/tracing/span_utils.py +5 -2
- 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/schemas/runtime_event_v1.json +95 -0
- agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
- 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
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,14 @@ from collections.abc import Mapping, Sequence
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
from urllib.parse import quote
|
|
6
6
|
|
|
7
|
+
from ksadk.agui.a2ui_projection import project_a2ui_operations
|
|
8
|
+
from ksadk.events.runtime_event import EventType
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _event_metadata(event: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
12
|
+
metadata = event.get("Metadata")
|
|
13
|
+
return metadata if isinstance(metadata, Mapping) else {}
|
|
14
|
+
|
|
7
15
|
|
|
8
16
|
def project_session_messages(
|
|
9
17
|
events: Sequence[Mapping[str, Any]],
|
|
@@ -14,8 +22,13 @@ def project_session_messages(
|
|
|
14
22
|
) -> list[dict[str, Any]]:
|
|
15
23
|
"""Project persisted runtime events into the chat history contract."""
|
|
16
24
|
|
|
25
|
+
agui_invocations = _agui_invocation_ids(events)
|
|
26
|
+
normalized = [
|
|
27
|
+
_normalize_runtime_event(event, agui_invocations=agui_invocations) for event in events
|
|
28
|
+
]
|
|
29
|
+
approval_responses = _approval_response_events(normalized)
|
|
17
30
|
groups: dict[str, list[Mapping[str, Any]]] = {}
|
|
18
|
-
for event in sorted(
|
|
31
|
+
for event in sorted(normalized, key=lambda item: int(item.get("SeqId") or 0)):
|
|
19
32
|
invocation_id = str(event.get("InvocationId") or f"seq:{event.get('SeqId')}")
|
|
20
33
|
groups.setdefault(invocation_id, []).append(event)
|
|
21
34
|
|
|
@@ -27,6 +40,7 @@ def project_session_messages(
|
|
|
27
40
|
include_reasoning=include_reasoning,
|
|
28
41
|
include_tool_events=include_tool_events,
|
|
29
42
|
include_attachments=include_attachments,
|
|
43
|
+
approval_responses=approval_responses,
|
|
30
44
|
)
|
|
31
45
|
)
|
|
32
46
|
return sorted(messages, key=lambda item: int(item.get("SeqId") or 0))
|
|
@@ -38,15 +52,24 @@ def _project_event_group(
|
|
|
38
52
|
include_reasoning: bool,
|
|
39
53
|
include_tool_events: bool,
|
|
40
54
|
include_attachments: bool,
|
|
55
|
+
approval_responses: Mapping[str, Mapping[str, Any]],
|
|
41
56
|
) -> list[dict[str, Any]]:
|
|
42
57
|
reasoning = [
|
|
43
58
|
{"text": _event_text(event), "SeqId": event.get("SeqId")}
|
|
44
59
|
for event in events
|
|
45
60
|
if event.get("EventType") == "reasoning" and _event_text(event)
|
|
46
61
|
]
|
|
47
|
-
tool_events =
|
|
62
|
+
tool_events = (
|
|
63
|
+
_project_tool_events(events, approval_responses=approval_responses)
|
|
64
|
+
if include_tool_events
|
|
65
|
+
else []
|
|
66
|
+
)
|
|
67
|
+
activities = _project_a2ui_activities(events)
|
|
48
68
|
projected: list[dict[str, Any]] = []
|
|
49
69
|
assistant_seen = False
|
|
70
|
+
latest_snapshot: Mapping[str, Any] | None = None
|
|
71
|
+
streamed_text = ""
|
|
72
|
+
start_seq_id = min((int(event.get("SeqId") or 0) for event in events), default=0)
|
|
50
73
|
|
|
51
74
|
for event in events:
|
|
52
75
|
event_type = str(event.get("EventType") or "")
|
|
@@ -63,36 +86,176 @@ def _project_event_group(
|
|
|
63
86
|
message["Reasoning"] = reasoning
|
|
64
87
|
if tool_events:
|
|
65
88
|
message["ToolEvents"] = tool_events
|
|
89
|
+
if include_reasoning:
|
|
90
|
+
blocks = _project_interleaved_blocks(events, tool_events=tool_events)
|
|
91
|
+
if blocks:
|
|
92
|
+
message["Blocks"] = blocks
|
|
66
93
|
projected.append(message)
|
|
67
94
|
assistant_seen = True
|
|
95
|
+
elif event_type == "assistant_stream_snapshot":
|
|
96
|
+
latest_snapshot = event
|
|
97
|
+
elif event_type == "assistant_stream_delta":
|
|
98
|
+
streamed_text += _event_text(event)
|
|
68
99
|
|
|
69
|
-
if not assistant_seen and (
|
|
100
|
+
if not assistant_seen and (
|
|
101
|
+
latest_snapshot is not None or streamed_text or reasoning or tool_events or activities
|
|
102
|
+
):
|
|
70
103
|
anchor = next(
|
|
71
104
|
(
|
|
72
105
|
event
|
|
73
106
|
for event in reversed(events)
|
|
74
107
|
if event.get("EventType")
|
|
75
|
-
in {
|
|
108
|
+
in {
|
|
109
|
+
"assistant_stream_snapshot",
|
|
110
|
+
"assistant_stream_delta",
|
|
111
|
+
"approval_request",
|
|
112
|
+
"tool_call",
|
|
113
|
+
"reasoning",
|
|
114
|
+
EventType.A2UI_SURFACE_BEGIN,
|
|
115
|
+
EventType.A2UI_SURFACE_UPDATE,
|
|
116
|
+
EventType.A2UI_SURFACE_END,
|
|
117
|
+
}
|
|
76
118
|
),
|
|
77
119
|
events[-1],
|
|
78
120
|
)
|
|
79
|
-
message = _base_message(
|
|
121
|
+
message = _base_message(
|
|
122
|
+
anchor,
|
|
123
|
+
"assistant",
|
|
124
|
+
content=(
|
|
125
|
+
_event_text(latest_snapshot) if latest_snapshot is not None else streamed_text
|
|
126
|
+
),
|
|
127
|
+
)
|
|
80
128
|
if include_reasoning and reasoning:
|
|
81
129
|
message["Reasoning"] = reasoning
|
|
82
130
|
if tool_events:
|
|
83
131
|
message["ToolEvents"] = tool_events
|
|
132
|
+
if include_reasoning:
|
|
133
|
+
blocks = _project_interleaved_blocks(events, tool_events=tool_events)
|
|
134
|
+
if blocks:
|
|
135
|
+
message["Blocks"] = blocks
|
|
84
136
|
projected.append(message)
|
|
85
137
|
|
|
138
|
+
if activities:
|
|
139
|
+
assistant = next(
|
|
140
|
+
(message for message in reversed(projected) if message.get("Role") == "assistant"),
|
|
141
|
+
None,
|
|
142
|
+
)
|
|
143
|
+
if assistant is not None:
|
|
144
|
+
assistant["Activities"] = activities
|
|
145
|
+
|
|
146
|
+
for message in projected:
|
|
147
|
+
message["StartSeqId"] = start_seq_id
|
|
86
148
|
return projected
|
|
87
149
|
|
|
88
150
|
|
|
151
|
+
def _project_interleaved_blocks(
|
|
152
|
+
events: Sequence[Mapping[str, Any]],
|
|
153
|
+
*,
|
|
154
|
+
tool_events: Sequence[Mapping[str, Any]],
|
|
155
|
+
) -> list[dict[str, Any]]:
|
|
156
|
+
"""Reconstruct ordered chat blocks from persisted streaming events.
|
|
157
|
+
|
|
158
|
+
``assistant_stream_snapshot`` carries a cumulative text value. The delta
|
|
159
|
+
relative to the prior snapshot is the text emitted at that point in the
|
|
160
|
+
event sequence. Reasoning events written before that snapshot can
|
|
161
|
+
therefore be replayed as ``thinking → text → thinking → text`` instead of
|
|
162
|
+
being flattened into the legacy ``Reasoning`` and ``Content`` fields.
|
|
163
|
+
|
|
164
|
+
Older transcripts wrote all reasoning only at terminal time. Their first
|
|
165
|
+
reasoning event appears after streamed text, so their original boundaries
|
|
166
|
+
are unknowable. Return no blocks for those transcripts and let clients
|
|
167
|
+
use the existing best-effort compatibility projection.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
blocks: list[dict[str, Any]] = []
|
|
171
|
+
latest_snapshot_text = ""
|
|
172
|
+
saw_stream_text = False
|
|
173
|
+
saw_reasoning_after_stream_text = False
|
|
174
|
+
tools_by_seq_id = {
|
|
175
|
+
int(tool.get("SeqId") or 0): tool
|
|
176
|
+
for tool in tool_events
|
|
177
|
+
if int(tool.get("SeqId") or 0) > 0
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
def append_text(text: str, seq_id: Any) -> None:
|
|
181
|
+
if not text:
|
|
182
|
+
return
|
|
183
|
+
if blocks and blocks[-1].get("Type") == "text":
|
|
184
|
+
blocks[-1]["Content"] = f"{blocks[-1].get('Content') or ''}{text}"
|
|
185
|
+
return
|
|
186
|
+
blocks.append({"Type": "text", "Content": text, "SeqId": seq_id})
|
|
187
|
+
|
|
188
|
+
def append_thinking(text: str, seq_id: Any) -> None:
|
|
189
|
+
if not text:
|
|
190
|
+
return
|
|
191
|
+
if blocks and blocks[-1].get("Type") == "thinking":
|
|
192
|
+
blocks[-1]["Content"] = f"{blocks[-1].get('Content') or ''}{text}"
|
|
193
|
+
return
|
|
194
|
+
blocks.append({"Type": "thinking", "Content": text, "SeqId": seq_id})
|
|
195
|
+
|
|
196
|
+
def append_tool(event: Mapping[str, Any]) -> None:
|
|
197
|
+
tool = tools_by_seq_id.get(int(event.get("SeqId") or 0))
|
|
198
|
+
if not tool:
|
|
199
|
+
return
|
|
200
|
+
blocks.append(
|
|
201
|
+
{
|
|
202
|
+
"Type": "tool",
|
|
203
|
+
"SeqId": tool.get("SeqId"),
|
|
204
|
+
"Name": tool.get("Name") or "tool",
|
|
205
|
+
"Args": tool.get("Args"),
|
|
206
|
+
"Result": tool.get("Result"),
|
|
207
|
+
"Status": tool.get("Status") or "completed",
|
|
208
|
+
"ToolCallId": tool.get("ToolCallId"),
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
for event in events:
|
|
213
|
+
event_type = str(event.get("EventType") or "")
|
|
214
|
+
text = _event_text(event)
|
|
215
|
+
seq_id = event.get("SeqId")
|
|
216
|
+
|
|
217
|
+
if event_type == "reasoning":
|
|
218
|
+
metadata = _event_metadata(event)
|
|
219
|
+
if saw_stream_text and metadata.get("stream_boundary") != "before_text":
|
|
220
|
+
saw_reasoning_after_stream_text = True
|
|
221
|
+
append_thinking(text, seq_id)
|
|
222
|
+
continue
|
|
223
|
+
if event_type == "tool_call":
|
|
224
|
+
append_tool(event)
|
|
225
|
+
continue
|
|
226
|
+
if event_type == "assistant_stream_delta":
|
|
227
|
+
append_text(text, seq_id)
|
|
228
|
+
saw_stream_text = saw_stream_text or bool(text)
|
|
229
|
+
continue
|
|
230
|
+
if event_type == "assistant_stream_snapshot":
|
|
231
|
+
if text.startswith(latest_snapshot_text):
|
|
232
|
+
append_text(text[len(latest_snapshot_text) :], seq_id)
|
|
233
|
+
elif text != latest_snapshot_text:
|
|
234
|
+
# A replacement snapshot has no safe incremental boundary.
|
|
235
|
+
# Keep the latest content as a standalone text block instead
|
|
236
|
+
# of duplicating already-replayed output.
|
|
237
|
+
append_text(text, seq_id)
|
|
238
|
+
latest_snapshot_text = text
|
|
239
|
+
saw_stream_text = saw_stream_text or bool(text)
|
|
240
|
+
continue
|
|
241
|
+
if event_type == "assistant_message":
|
|
242
|
+
if latest_snapshot_text and text.startswith(latest_snapshot_text):
|
|
243
|
+
append_text(text[len(latest_snapshot_text) :], seq_id)
|
|
244
|
+
elif not latest_snapshot_text:
|
|
245
|
+
append_text(text, seq_id)
|
|
246
|
+
|
|
247
|
+
if saw_reasoning_after_stream_text:
|
|
248
|
+
return []
|
|
249
|
+
return blocks
|
|
250
|
+
|
|
251
|
+
|
|
89
252
|
def _base_message(
|
|
90
253
|
event: Mapping[str, Any],
|
|
91
254
|
role: str,
|
|
92
255
|
*,
|
|
93
256
|
content: str | None = None,
|
|
94
257
|
) -> dict[str, Any]:
|
|
95
|
-
metadata =
|
|
258
|
+
metadata = _event_metadata(event)
|
|
96
259
|
message: dict[str, Any] = {
|
|
97
260
|
"MessageId": event.get("EventId"),
|
|
98
261
|
"Role": role,
|
|
@@ -127,35 +290,56 @@ def _event_text(event: Mapping[str, Any]) -> str:
|
|
|
127
290
|
)
|
|
128
291
|
|
|
129
292
|
|
|
130
|
-
def _project_tool_events(
|
|
293
|
+
def _project_tool_events(
|
|
294
|
+
events: Sequence[Mapping[str, Any]],
|
|
295
|
+
*,
|
|
296
|
+
approval_responses: Mapping[str, Mapping[str, Any]],
|
|
297
|
+
) -> list[dict[str, Any]]:
|
|
131
298
|
projected: list[dict[str, Any]] = []
|
|
132
|
-
pending_calls: list[
|
|
299
|
+
pending_calls: list[dict[str, Any]] = []
|
|
300
|
+
pending_by_key: dict[str, dict[str, Any]] = {}
|
|
301
|
+
seen_result_receipts: set[str] = set()
|
|
133
302
|
|
|
134
303
|
for event in events:
|
|
135
304
|
event_type = str(event.get("EventType") or "")
|
|
136
|
-
metadata =
|
|
305
|
+
metadata = _event_metadata(event)
|
|
137
306
|
if event_type == "tool_call":
|
|
138
307
|
entry = _tool_event_from_call(event, metadata)
|
|
139
308
|
projected.append(entry)
|
|
140
|
-
pending_calls.append(
|
|
309
|
+
pending_calls.append(entry)
|
|
310
|
+
pair_key = _tool_pair_key(metadata)
|
|
311
|
+
if pair_key:
|
|
312
|
+
pending_by_key[pair_key] = entry
|
|
141
313
|
continue
|
|
142
314
|
if event_type != "tool_result":
|
|
143
315
|
continue
|
|
144
316
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
(
|
|
148
|
-
item
|
|
149
|
-
for item in reversed(pending_calls)
|
|
150
|
-
if item[1]["Name"] == name and item[1]["Status"] == "running"
|
|
151
|
-
),
|
|
152
|
-
None,
|
|
317
|
+
receipt = metadata.get("tool_receipt")
|
|
318
|
+
receipt_key = (
|
|
319
|
+
str(receipt.get("idempotency_key") or "") if isinstance(receipt, Mapping) else ""
|
|
153
320
|
)
|
|
321
|
+
if receipt_key and receipt_key in seen_result_receipts:
|
|
322
|
+
continue
|
|
323
|
+
if receipt_key:
|
|
324
|
+
seen_result_receipts.add(receipt_key)
|
|
325
|
+
|
|
326
|
+
name = str(metadata.get("tool_name") or "tool")
|
|
327
|
+
pair_key = _tool_pair_key(metadata)
|
|
328
|
+
match = pending_by_key.get(pair_key) if pair_key else None
|
|
329
|
+
if match is None or match["Status"] != "running":
|
|
330
|
+
match = next(
|
|
331
|
+
(
|
|
332
|
+
item
|
|
333
|
+
for item in reversed(pending_calls)
|
|
334
|
+
if item["Name"] == name and item["Status"] == "running"
|
|
335
|
+
),
|
|
336
|
+
None,
|
|
337
|
+
)
|
|
154
338
|
if match is None:
|
|
155
339
|
entry = _tool_event_from_call(event, metadata)
|
|
156
340
|
projected.append(entry)
|
|
157
341
|
else:
|
|
158
|
-
entry = match
|
|
342
|
+
entry = match
|
|
159
343
|
output = metadata.get("tool_output", _event_text(event))
|
|
160
344
|
entry["Status"] = (
|
|
161
345
|
"failed" if isinstance(output, Mapping) and output.get("ok") is False else "completed"
|
|
@@ -163,13 +347,24 @@ def _project_tool_events(events: Sequence[Mapping[str, Any]]) -> list[dict[str,
|
|
|
163
347
|
entry["Result"] = output
|
|
164
348
|
entry["ResultSeqId"] = event.get("SeqId")
|
|
165
349
|
|
|
166
|
-
projected.extend(_project_approval_events(events))
|
|
350
|
+
projected.extend(_project_approval_events(events, responses=approval_responses))
|
|
167
351
|
return projected
|
|
168
352
|
|
|
169
353
|
|
|
170
|
-
def
|
|
171
|
-
|
|
172
|
-
|
|
354
|
+
def _tool_pair_key(metadata: Mapping[str, Any]) -> str:
|
|
355
|
+
call_id = metadata.get("call_id")
|
|
356
|
+
if call_id:
|
|
357
|
+
return f"call:{call_id}"
|
|
358
|
+
tool_receipt = metadata.get("tool_receipt")
|
|
359
|
+
if isinstance(tool_receipt, Mapping) and tool_receipt.get("tool_call_id"):
|
|
360
|
+
return f"call:{tool_receipt['tool_call_id']}"
|
|
361
|
+
run_id = metadata.get("run_id")
|
|
362
|
+
if run_id:
|
|
363
|
+
return f"run:{run_id}:{metadata.get('tool_name') or 'tool'}"
|
|
364
|
+
return ""
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _tool_event_from_call(event: Mapping[str, Any], metadata: Mapping[str, Any]) -> dict[str, Any]:
|
|
173
368
|
tool_receipt = metadata.get("tool_receipt")
|
|
174
369
|
call_id = metadata.get("call_id") or metadata.get("run_id")
|
|
175
370
|
if not call_id and isinstance(tool_receipt, Mapping):
|
|
@@ -184,28 +379,16 @@ def _tool_event_from_call(
|
|
|
184
379
|
}
|
|
185
380
|
|
|
186
381
|
|
|
187
|
-
def _project_approval_events(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
metadata = event.get("Metadata") if isinstance(event.get("Metadata"), Mapping) else {}
|
|
193
|
-
resume_input = metadata.get("resume_input")
|
|
194
|
-
if not isinstance(resume_input, Mapping):
|
|
195
|
-
continue
|
|
196
|
-
request_id = str(
|
|
197
|
-
resume_input.get("approval_request_id")
|
|
198
|
-
or resume_input.get("interrupt_id")
|
|
199
|
-
or resume_input.get("id")
|
|
200
|
-
or ""
|
|
201
|
-
)
|
|
202
|
-
responses[request_id] = event
|
|
203
|
-
|
|
382
|
+
def _project_approval_events(
|
|
383
|
+
events: Sequence[Mapping[str, Any]],
|
|
384
|
+
*,
|
|
385
|
+
responses: Mapping[str, Mapping[str, Any]],
|
|
386
|
+
) -> list[dict[str, Any]]:
|
|
204
387
|
approvals: list[dict[str, Any]] = []
|
|
205
388
|
for request in events:
|
|
206
389
|
if request.get("EventType") != "approval_request":
|
|
207
390
|
continue
|
|
208
|
-
metadata =
|
|
391
|
+
metadata = _event_metadata(request)
|
|
209
392
|
interrupt_info = metadata.get("interrupt_info")
|
|
210
393
|
if not isinstance(interrupt_info, Mapping):
|
|
211
394
|
interrupt_info = {}
|
|
@@ -213,18 +396,18 @@ def _project_approval_events(events: Sequence[Mapping[str, Any]]) -> list[dict[s
|
|
|
213
396
|
interrupt_info.get("approval_request_id") or interrupt_info.get("id") or ""
|
|
214
397
|
)
|
|
215
398
|
response = responses.get(request_id)
|
|
216
|
-
response_metadata = (
|
|
217
|
-
response.get("Metadata")
|
|
218
|
-
if response is not None and isinstance(response.get("Metadata"), Mapping)
|
|
219
|
-
else {}
|
|
220
|
-
)
|
|
399
|
+
response_metadata = _event_metadata(response) if response is not None else {}
|
|
221
400
|
resume_input = response_metadata.get("resume_input")
|
|
222
401
|
if not isinstance(resume_input, Mapping):
|
|
223
402
|
resume_input = {}
|
|
224
|
-
status =
|
|
225
|
-
"
|
|
226
|
-
if
|
|
227
|
-
else
|
|
403
|
+
status = (
|
|
404
|
+
"paused"
|
|
405
|
+
if response is None
|
|
406
|
+
else (
|
|
407
|
+
"approved"
|
|
408
|
+
if resume_input.get("approve") or resume_input.get("approved")
|
|
409
|
+
else "denied"
|
|
410
|
+
)
|
|
228
411
|
)
|
|
229
412
|
entry: dict[str, Any] = {
|
|
230
413
|
"SeqId": request.get("SeqId"),
|
|
@@ -233,6 +416,8 @@ def _project_approval_events(events: Sequence[Mapping[str, Any]]) -> list[dict[s
|
|
|
233
416
|
"Status": status,
|
|
234
417
|
"ApprovalRequestId": request_id or None,
|
|
235
418
|
}
|
|
419
|
+
if metadata.get("protocol") == "ag-ui":
|
|
420
|
+
entry["Protocol"] = "ag-ui"
|
|
236
421
|
arguments = (
|
|
237
422
|
interrupt_info.get("arguments")
|
|
238
423
|
or interrupt_info.get("tool_args")
|
|
@@ -240,12 +425,214 @@ def _project_approval_events(events: Sequence[Mapping[str, Any]]) -> list[dict[s
|
|
|
240
425
|
)
|
|
241
426
|
if arguments is not None:
|
|
242
427
|
entry["Args"] = arguments
|
|
428
|
+
approval_level = interrupt_info.get("approval_level") or interrupt_info.get("risk_level")
|
|
429
|
+
if approval_level:
|
|
430
|
+
entry["ApprovalLevel"] = str(approval_level)
|
|
431
|
+
approval_message = interrupt_info.get("approval_message") or interrupt_info.get("message")
|
|
432
|
+
if approval_message:
|
|
433
|
+
entry["ApprovalMessage"] = str(approval_message)
|
|
243
434
|
approvals.append(entry)
|
|
244
435
|
return approvals
|
|
245
436
|
|
|
246
437
|
|
|
438
|
+
def _approval_response_events(
|
|
439
|
+
events: Sequence[Mapping[str, Any]],
|
|
440
|
+
) -> dict[str, Mapping[str, Any]]:
|
|
441
|
+
responses: dict[str, Mapping[str, Any]] = {}
|
|
442
|
+
for event in events:
|
|
443
|
+
if event.get("EventType") != "approval_response":
|
|
444
|
+
continue
|
|
445
|
+
metadata = _event_metadata(event)
|
|
446
|
+
resume_input = metadata.get("resume_input")
|
|
447
|
+
if not isinstance(resume_input, Mapping):
|
|
448
|
+
continue
|
|
449
|
+
request_id = str(
|
|
450
|
+
resume_input.get("approval_request_id")
|
|
451
|
+
or resume_input.get("interrupt_id")
|
|
452
|
+
or resume_input.get("id")
|
|
453
|
+
or ""
|
|
454
|
+
)
|
|
455
|
+
if request_id:
|
|
456
|
+
responses[request_id] = event
|
|
457
|
+
return responses
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def _project_a2ui_activities(events: Sequence[Mapping[str, Any]]) -> list[dict[str, Any]]:
|
|
461
|
+
activities: list[dict[str, Any]] = []
|
|
462
|
+
for event in events:
|
|
463
|
+
event_type = str(event.get("EventType") or "")
|
|
464
|
+
if event_type not in {
|
|
465
|
+
EventType.A2UI_SURFACE_BEGIN,
|
|
466
|
+
EventType.A2UI_SURFACE_UPDATE,
|
|
467
|
+
EventType.A2UI_SURFACE_END,
|
|
468
|
+
}:
|
|
469
|
+
continue
|
|
470
|
+
content = event.get("Content")
|
|
471
|
+
payload = content if isinstance(content, Mapping) else {}
|
|
472
|
+
operations = project_a2ui_operations(event_type, payload)
|
|
473
|
+
if not operations:
|
|
474
|
+
continue
|
|
475
|
+
surface_id = str(payload.get("surface_id") or payload.get("surfaceId") or "")
|
|
476
|
+
activities.append(
|
|
477
|
+
{
|
|
478
|
+
"SeqId": event.get("SeqId"),
|
|
479
|
+
"Type": "a2ui-surface",
|
|
480
|
+
"MessageId": f"{event.get('InvocationId')}:a2ui:{surface_id}",
|
|
481
|
+
"SurfaceId": surface_id,
|
|
482
|
+
"Content": {
|
|
483
|
+
"surfaceId": surface_id,
|
|
484
|
+
"a2ui_operations": operations,
|
|
485
|
+
},
|
|
486
|
+
}
|
|
487
|
+
)
|
|
488
|
+
return activities
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _agui_invocation_ids(events: Sequence[Mapping[str, Any]]) -> set[str]:
|
|
492
|
+
"""Locate AG-UI runs so history written before ``payload.protocol`` remains usable."""
|
|
493
|
+
invocation_ids: set[str] = set()
|
|
494
|
+
for event in events:
|
|
495
|
+
if str(event.get("EventType") or "") != EventType.RUN_STARTED:
|
|
496
|
+
continue
|
|
497
|
+
if not _event_metadata(event).get("ksadk_runtime_event"):
|
|
498
|
+
continue
|
|
499
|
+
content = event.get("Content")
|
|
500
|
+
payload = content.get("payload") if isinstance(content, Mapping) else None
|
|
501
|
+
if isinstance(payload, Mapping) and payload.get("source") == "ag-ui":
|
|
502
|
+
invocation_id = str(event.get("InvocationId") or "")
|
|
503
|
+
if invocation_id:
|
|
504
|
+
invocation_ids.add(invocation_id)
|
|
505
|
+
return invocation_ids
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def _normalize_runtime_event(
|
|
509
|
+
event: Mapping[str, Any],
|
|
510
|
+
*,
|
|
511
|
+
agui_invocations: set[str],
|
|
512
|
+
) -> Mapping[str, Any]:
|
|
513
|
+
metadata = _event_metadata(event)
|
|
514
|
+
if not metadata.get("ksadk_runtime_event"):
|
|
515
|
+
return event
|
|
516
|
+
raw_content = event.get("Content")
|
|
517
|
+
content = raw_content if isinstance(raw_content, Mapping) else {}
|
|
518
|
+
payload = content.get("payload")
|
|
519
|
+
payload = payload if isinstance(payload, Mapping) else {}
|
|
520
|
+
event_type = str(event.get("EventType") or "")
|
|
521
|
+
normalized = dict(event)
|
|
522
|
+
normalized["Content"] = dict(payload)
|
|
523
|
+
normalized_metadata = dict(metadata)
|
|
524
|
+
|
|
525
|
+
if event_type == EventType.RUN_STARTED and payload.get("source") == "ag-ui":
|
|
526
|
+
normalized["EventType"] = "user_message"
|
|
527
|
+
normalized["Content"] = {"text": _input_text(payload.get("input"))}
|
|
528
|
+
normalized["Author"] = "user"
|
|
529
|
+
elif event_type == EventType.TEXT_COMPLETED:
|
|
530
|
+
normalized["EventType"] = "assistant_message"
|
|
531
|
+
elif event_type == EventType.TEXT_DELTA:
|
|
532
|
+
normalized["EventType"] = "assistant_stream_delta"
|
|
533
|
+
elif event_type in {EventType.REASONING_DELTA, EventType.REASONING_COMPLETED}:
|
|
534
|
+
normalized["EventType"] = "reasoning"
|
|
535
|
+
elif event_type == EventType.TOOL_CALL_BEGIN:
|
|
536
|
+
normalized["EventType"] = "tool_call"
|
|
537
|
+
normalized_metadata.update(
|
|
538
|
+
{
|
|
539
|
+
"call_id": payload.get("call_id"),
|
|
540
|
+
"tool_name": payload.get("name"),
|
|
541
|
+
"tool_args": payload.get("args"),
|
|
542
|
+
}
|
|
543
|
+
)
|
|
544
|
+
elif event_type == EventType.TOOL_CALL_END:
|
|
545
|
+
normalized["EventType"] = "tool_result"
|
|
546
|
+
normalized_metadata.update(
|
|
547
|
+
{
|
|
548
|
+
"call_id": payload.get("call_id"),
|
|
549
|
+
"tool_name": payload.get("name"),
|
|
550
|
+
"tool_output": payload.get("result", payload.get("error")),
|
|
551
|
+
}
|
|
552
|
+
)
|
|
553
|
+
elif event_type == EventType.APPROVAL_REQUESTED:
|
|
554
|
+
detail = payload.get("detail")
|
|
555
|
+
detail = detail if isinstance(detail, Mapping) else {}
|
|
556
|
+
approval_request = detail.get("approval_requests")
|
|
557
|
+
approval_request = approval_request if isinstance(approval_request, Mapping) else detail
|
|
558
|
+
action_requests = approval_request.get("action_requests")
|
|
559
|
+
action = (
|
|
560
|
+
next(
|
|
561
|
+
(item for item in action_requests if isinstance(item, Mapping)),
|
|
562
|
+
{},
|
|
563
|
+
)
|
|
564
|
+
if isinstance(action_requests, list)
|
|
565
|
+
else {}
|
|
566
|
+
)
|
|
567
|
+
normalized["EventType"] = "approval_request"
|
|
568
|
+
normalized_metadata["interrupt_info"] = {
|
|
569
|
+
"approval_request_id": payload.get("approval_id") or payload.get("call_id"),
|
|
570
|
+
"id": payload.get("approval_id") or payload.get("call_id"),
|
|
571
|
+
"tool_name": action.get("name")
|
|
572
|
+
or approval_request.get("tool_name")
|
|
573
|
+
or detail.get("tool_name")
|
|
574
|
+
or payload.get("kind")
|
|
575
|
+
or "approval",
|
|
576
|
+
"arguments": action.get("args")
|
|
577
|
+
or action.get("arguments")
|
|
578
|
+
or approval_request.get("arguments")
|
|
579
|
+
or approval_request.get("args")
|
|
580
|
+
or detail.get("arguments")
|
|
581
|
+
or detail.get("args"),
|
|
582
|
+
"approval_level": action.get("approval_level")
|
|
583
|
+
or approval_request.get("approval_level")
|
|
584
|
+
or detail.get("approval_level")
|
|
585
|
+
or payload.get("approval_level"),
|
|
586
|
+
"approval_message": action.get("description")
|
|
587
|
+
or approval_request.get("message")
|
|
588
|
+
or detail.get("message")
|
|
589
|
+
or payload.get("message"),
|
|
590
|
+
}
|
|
591
|
+
is_agui_approval = payload.get("protocol") == "ag-ui" or (
|
|
592
|
+
str(event.get("InvocationId") or "") in agui_invocations
|
|
593
|
+
)
|
|
594
|
+
if is_agui_approval:
|
|
595
|
+
normalized_metadata["protocol"] = "ag-ui"
|
|
596
|
+
elif event_type == EventType.APPROVAL_RESOLVED:
|
|
597
|
+
decision = payload.get("decision")
|
|
598
|
+
normalized["EventType"] = "approval_response"
|
|
599
|
+
normalized_metadata["resume_input"] = {
|
|
600
|
+
"approval_request_id": payload.get("approval_id") or payload.get("call_id"),
|
|
601
|
+
"approve": _approval_decision_is_approved(decision),
|
|
602
|
+
"decision": decision,
|
|
603
|
+
}
|
|
604
|
+
normalized["Metadata"] = normalized_metadata
|
|
605
|
+
return normalized
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
def _approval_decision_is_approved(decision: Any) -> bool:
|
|
609
|
+
"""Accept the historical AG-UI decision envelopes during transcript replay."""
|
|
610
|
+
|
|
611
|
+
if decision is True:
|
|
612
|
+
return True
|
|
613
|
+
if isinstance(decision, Mapping):
|
|
614
|
+
for key in ("approve", "approved"):
|
|
615
|
+
if key in decision:
|
|
616
|
+
return bool(decision[key])
|
|
617
|
+
return _approval_decision_is_approved(decision.get("decision"))
|
|
618
|
+
return isinstance(decision, str) and decision.strip().lower() in {"approve", "approved"}
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def _input_text(value: Any) -> str:
|
|
622
|
+
if isinstance(value, str):
|
|
623
|
+
return value
|
|
624
|
+
if isinstance(value, Mapping):
|
|
625
|
+
if value.get("text") is not None:
|
|
626
|
+
return str(value.get("text") or "")
|
|
627
|
+
if value.get("content") is not None:
|
|
628
|
+
return _input_text(value.get("content"))
|
|
629
|
+
if isinstance(value, list):
|
|
630
|
+
return "".join(_input_text(item) for item in value)
|
|
631
|
+
return "" if value is None else str(value)
|
|
632
|
+
|
|
633
|
+
|
|
247
634
|
def _event_attachments(event: Mapping[str, Any]) -> list[dict[str, Any]]:
|
|
248
|
-
metadata =
|
|
635
|
+
metadata = _event_metadata(event)
|
|
249
636
|
attachments: list[dict[str, Any]] = []
|
|
250
637
|
seen: set[str] = set()
|
|
251
638
|
for item in metadata.get("attachments") or []:
|
|
@@ -79,12 +79,12 @@ def _coerce_token_limit(value: Any, *, assume_k_for_plain_values: bool = False)
|
|
|
79
79
|
text = text[:-1]
|
|
80
80
|
|
|
81
81
|
try:
|
|
82
|
-
|
|
82
|
+
parsed_number = float(text)
|
|
83
83
|
except (TypeError, ValueError):
|
|
84
84
|
return None
|
|
85
|
-
if
|
|
85
|
+
if parsed_number <= 0:
|
|
86
86
|
return None
|
|
87
|
-
resolved = int(
|
|
87
|
+
resolved = int(parsed_number * multiplier)
|
|
88
88
|
if multiplier == 1 and assume_k_for_plain_values and text.isdigit() and 0 < resolved <= 1000:
|
|
89
89
|
return resolved * 1000
|
|
90
90
|
return resolved
|
|
@@ -189,7 +189,9 @@ def get_context_window_tokens(model_metadata: Mapping[str, Any] | None = None) -
|
|
|
189
189
|
if model_metadata.get("context_window_tokens"):
|
|
190
190
|
limits["context_window_tokens"] = model_metadata["context_window_tokens"]
|
|
191
191
|
|
|
192
|
-
return
|
|
192
|
+
return (
|
|
193
|
+
_coerce_positive_int(limits.get("context_window_tokens")) or DEFAULT_CONTEXT_WINDOW_TOKENS
|
|
194
|
+
)
|
|
193
195
|
|
|
194
196
|
|
|
195
197
|
def get_effective_context_window_tokens(model_metadata: Mapping[str, Any] | None = None) -> int:
|
|
@@ -202,7 +204,9 @@ def get_effective_context_window_tokens(model_metadata: Mapping[str, Any] | None
|
|
|
202
204
|
limits["max_output_tokens"] = model_metadata["max_output_tokens"]
|
|
203
205
|
|
|
204
206
|
context_window = get_context_window_tokens(model_metadata)
|
|
205
|
-
max_output_tokens =
|
|
207
|
+
max_output_tokens = (
|
|
208
|
+
_coerce_positive_int(limits.get("max_output_tokens")) or DEFAULT_MAX_OUTPUT_TOKENS
|
|
209
|
+
)
|
|
206
210
|
reserved_tokens = min(max_output_tokens, AUTOCOMPACT_SUMMARY_RESERVE_TOKENS)
|
|
207
211
|
return max(1, context_window - reserved_tokens)
|
|
208
212
|
|
|
@@ -366,5 +370,7 @@ def normalize_model_metadata(raw_model: Mapping[str, Any] | str | None) -> dict[
|
|
|
366
370
|
"pricing": pricing,
|
|
367
371
|
}
|
|
368
372
|
normalized["auto_compact_threshold_tokens"] = get_auto_compact_threshold_tokens(normalized)
|
|
369
|
-
normalized["auto_compact_threshold_percentage"] = get_auto_compact_threshold_percentage(
|
|
373
|
+
normalized["auto_compact_threshold_percentage"] = get_auto_compact_threshold_percentage(
|
|
374
|
+
normalized
|
|
375
|
+
)
|
|
370
376
|
return normalized
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, Mapping
|
|
4
4
|
|
|
5
|
-
|
|
6
5
|
_VALID_REASONING_EFFORTS = {"none", "minimal", "low", "medium", "high", "xhigh"}
|
|
7
6
|
_CHAT_COMPLETIONS_REASONING_EFFORTS = {"low", "medium", "high"}
|
|
8
7
|
_PASSTHROUGH_OPTION_KEYS = {"temperature", "top_p", "max_tokens", "max_completion_tokens"}
|