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
|
@@ -0,0 +1,649 @@
|
|
|
1
|
+
"""Session, UI bootstrap, checkpoint-list, and tool-receipt routes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from fastapi import HTTPException
|
|
9
|
+
|
|
10
|
+
from ksadk.server.factory import get_runner, get_state
|
|
11
|
+
from ksadk.sessions import SessionEvent
|
|
12
|
+
from ksadk.tools.gateway import tool_approval_capability
|
|
13
|
+
from ksadk.toolsets import describe_agentengine_tools
|
|
14
|
+
from ksadk_runtime_common.workspace_files import (
|
|
15
|
+
build_workspace_files_bootstrap,
|
|
16
|
+
workspace_files_enabled,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from . import dependencies as deps
|
|
20
|
+
from .common import (
|
|
21
|
+
_action_response,
|
|
22
|
+
_build_bootstrap_model_payload,
|
|
23
|
+
_build_native_terminal_capability,
|
|
24
|
+
_ensure_session,
|
|
25
|
+
_hydrate_session,
|
|
26
|
+
)
|
|
27
|
+
from .models import (
|
|
28
|
+
CreateSessionActionRequest,
|
|
29
|
+
ListSessionCheckpointsActionRequest,
|
|
30
|
+
ListSessionEventsActionRequest,
|
|
31
|
+
ListSessionMessagesActionRequest,
|
|
32
|
+
ListSessionsActionRequest,
|
|
33
|
+
ListToolReceiptsActionRequest,
|
|
34
|
+
SessionIdRequest,
|
|
35
|
+
UiBootstrapRequest,
|
|
36
|
+
_event_run_id,
|
|
37
|
+
_runtime_agent_id,
|
|
38
|
+
)
|
|
39
|
+
from .projection import (
|
|
40
|
+
_apply_checkpoint_resume_audit,
|
|
41
|
+
_apply_latest_checkpoint_policy,
|
|
42
|
+
_checkpoint_event_to_action_payload,
|
|
43
|
+
_event_invocation_id,
|
|
44
|
+
_event_to_action_payload,
|
|
45
|
+
_extend_invocation_after_window,
|
|
46
|
+
_extend_invocation_before_window,
|
|
47
|
+
_iter_scoped_event_pages,
|
|
48
|
+
_iter_session_event_pages,
|
|
49
|
+
_record_resume_audit,
|
|
50
|
+
_require_action_session,
|
|
51
|
+
_session_to_action_payload,
|
|
52
|
+
_tool_receipt_event_to_action_payload,
|
|
53
|
+
)
|
|
54
|
+
from .routers import sessions_router, tools_router, ui_bootstrap_router
|
|
55
|
+
from .streaming import _cancel_detached_streams_for_session
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@ui_bootstrap_router.post("/agentengine/api/v1/GetAgentUiBootstrap")
|
|
59
|
+
async def get_agent_ui_bootstrap(request: UiBootstrapRequest):
|
|
60
|
+
state = get_state()
|
|
61
|
+
runner = state.runner
|
|
62
|
+
if runner is not None:
|
|
63
|
+
runner = get_runner()
|
|
64
|
+
agent_id = request.AgentId or (_runtime_agent_id(runner) if runner else "default-agent")
|
|
65
|
+
description = getattr(runner.detection_result, "description", "") if runner else ""
|
|
66
|
+
framework = ""
|
|
67
|
+
if runner:
|
|
68
|
+
detection_type = getattr(getattr(runner, "detection_result", None), "type", None)
|
|
69
|
+
framework = str(getattr(detection_type, "value", detection_type) or "").strip().lower()
|
|
70
|
+
workspace_enabled = workspace_files_enabled(default=True)
|
|
71
|
+
ui_spec = deps.resolve_agent_ui_spec()
|
|
72
|
+
runtime_capabilities = (
|
|
73
|
+
runner.get_runtime_capabilities()
|
|
74
|
+
if runner and callable(getattr(runner, "get_runtime_capabilities", None))
|
|
75
|
+
else {}
|
|
76
|
+
)
|
|
77
|
+
checkpoint_resume_capability = {
|
|
78
|
+
"Supported": bool(
|
|
79
|
+
(runtime_capabilities.get("ResumeRun") or {}).get("Supported")
|
|
80
|
+
if isinstance(runtime_capabilities, Mapping)
|
|
81
|
+
else False
|
|
82
|
+
),
|
|
83
|
+
"Checkpoint": (
|
|
84
|
+
(runtime_capabilities.get("Checkpoint") or {})
|
|
85
|
+
if isinstance(runtime_capabilities, Mapping)
|
|
86
|
+
else {}
|
|
87
|
+
),
|
|
88
|
+
"ResumeRun": (
|
|
89
|
+
(runtime_capabilities.get("ResumeRun") or {})
|
|
90
|
+
if isinstance(runtime_capabilities, Mapping)
|
|
91
|
+
else {}
|
|
92
|
+
),
|
|
93
|
+
}
|
|
94
|
+
checkpoint_resume_supported = bool(checkpoint_resume_capability["Supported"])
|
|
95
|
+
cancel_run_supported = bool(
|
|
96
|
+
(runtime_capabilities.get("CancelRun") or {}).get("Supported")
|
|
97
|
+
if isinstance(runtime_capabilities, Mapping)
|
|
98
|
+
else False
|
|
99
|
+
)
|
|
100
|
+
responses_transport = {
|
|
101
|
+
"Protocol": "responses",
|
|
102
|
+
"Runtime": "ksadk",
|
|
103
|
+
"Endpoint": "/v1/responses",
|
|
104
|
+
"Version": "v1",
|
|
105
|
+
"Capabilities": {
|
|
106
|
+
"A2UI": False,
|
|
107
|
+
"Interrupt": checkpoint_resume_supported,
|
|
108
|
+
"Cancel": cancel_run_supported,
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
hosted_chat_transports = []
|
|
112
|
+
if state.agui_agent is not None and state.agui_config is not None:
|
|
113
|
+
from ksadk.agui.config import AGUI_PROTOCOL_VERSION
|
|
114
|
+
|
|
115
|
+
hosted_chat_transports.append(
|
|
116
|
+
{
|
|
117
|
+
"Protocol": "ag-ui",
|
|
118
|
+
"Runtime": "copilotkit",
|
|
119
|
+
"Endpoint": state.agui_config.path,
|
|
120
|
+
"Version": AGUI_PROTOCOL_VERSION,
|
|
121
|
+
"Capabilities": {
|
|
122
|
+
"A2UI": True,
|
|
123
|
+
"Interrupt": checkpoint_resume_supported,
|
|
124
|
+
"Cancel": True,
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
hosted_chat_transports.append(responses_transport)
|
|
129
|
+
preferred_transport = (
|
|
130
|
+
"ag-ui"
|
|
131
|
+
if hosted_chat_transports[0]["Protocol"] == "ag-ui"
|
|
132
|
+
and bool(getattr(state.agui_config, "preferred", False))
|
|
133
|
+
else "responses"
|
|
134
|
+
)
|
|
135
|
+
return _action_response(
|
|
136
|
+
"GetAgentUiBootstrap",
|
|
137
|
+
{
|
|
138
|
+
"Agent": {
|
|
139
|
+
"AgentId": agent_id,
|
|
140
|
+
"Name": runner.detection_result.name if runner else agent_id,
|
|
141
|
+
"Description": description or "",
|
|
142
|
+
"Framework": framework,
|
|
143
|
+
},
|
|
144
|
+
"Modules": ["Chat", "Build", "Deploy"],
|
|
145
|
+
"Capabilities": {
|
|
146
|
+
"Attachments": True,
|
|
147
|
+
"WorkspaceFiles": workspace_enabled,
|
|
148
|
+
"Approval": True,
|
|
149
|
+
"ApprovalPolicy": tool_approval_capability(),
|
|
150
|
+
"Thinking": True,
|
|
151
|
+
"StopRun": cancel_run_supported,
|
|
152
|
+
"ResumeRun": checkpoint_resume_supported,
|
|
153
|
+
"RuntimeCapabilities": runtime_capabilities,
|
|
154
|
+
"CheckpointResumeCapability": checkpoint_resume_capability,
|
|
155
|
+
"RunLifecycle": {
|
|
156
|
+
"Enabled": True,
|
|
157
|
+
"Resume": True,
|
|
158
|
+
"Abort": True,
|
|
159
|
+
"Checkpoints": checkpoint_resume_supported,
|
|
160
|
+
"CheckpointResume": checkpoint_resume_supported,
|
|
161
|
+
"CheckpointResumePreview": checkpoint_resume_supported,
|
|
162
|
+
},
|
|
163
|
+
"MCP": False,
|
|
164
|
+
"HostedRuntime": False,
|
|
165
|
+
"NativeTerminal": _build_native_terminal_capability(framework),
|
|
166
|
+
"BuiltinTools": describe_agentengine_tools(),
|
|
167
|
+
},
|
|
168
|
+
"WorkspaceFiles": build_workspace_files_bootstrap(enabled=workspace_enabled),
|
|
169
|
+
"AccessMode": "Owner",
|
|
170
|
+
"SharePermissions": {
|
|
171
|
+
"Interactive": True,
|
|
172
|
+
"DefaultPath": ui_spec.get("ui_path") or ui_spec.get("path") or "/chat",
|
|
173
|
+
"SharePath": ui_spec.get("ui_path") or ui_spec.get("path") or "/chat",
|
|
174
|
+
},
|
|
175
|
+
"CustomUI": {
|
|
176
|
+
"Enabled": bool(ui_spec.get("enabled")),
|
|
177
|
+
"Profile": ui_spec.get("ui_profile") or ui_spec.get("profile"),
|
|
178
|
+
"Path": ui_spec.get("ui_path") or ui_spec.get("path"),
|
|
179
|
+
"Url": ui_spec.get("ui_url") or ui_spec.get("url"),
|
|
180
|
+
"BundlePath": ui_spec.get("ui_bundle_path") or ui_spec.get("bundle_path"),
|
|
181
|
+
},
|
|
182
|
+
"ApiFormats": ["responses", "chat_completions"],
|
|
183
|
+
"HostedChat": {
|
|
184
|
+
"PreferredTransport": preferred_transport,
|
|
185
|
+
"Transports": hosted_chat_transports,
|
|
186
|
+
},
|
|
187
|
+
"Stream": True,
|
|
188
|
+
"SessionId": request.SessionId,
|
|
189
|
+
"SessionBackend": deps.describe_session_backend(),
|
|
190
|
+
"HostedRuntime": None,
|
|
191
|
+
"Model": _build_bootstrap_model_payload(),
|
|
192
|
+
},
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@sessions_router.post("/agentengine/api/v1/CreateSession")
|
|
197
|
+
async def create_session_action(request: CreateSessionActionRequest):
|
|
198
|
+
session = await _ensure_session(request.AgentId, request.UserId or "user", request.SessionId)
|
|
199
|
+
return _action_response("CreateSession", {"Session": await _session_to_action_payload(session)})
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@sessions_router.post("/agentengine/api/v1/ListSessions")
|
|
203
|
+
async def list_sessions_action(request: ListSessionsActionRequest):
|
|
204
|
+
service = deps.resolve_session_service()
|
|
205
|
+
offset = (request.Page - 1) * request.PageSize
|
|
206
|
+
sessions = await service.list_sessions(
|
|
207
|
+
request.AgentId,
|
|
208
|
+
request.UserId,
|
|
209
|
+
offset=offset,
|
|
210
|
+
limit=request.PageSize,
|
|
211
|
+
)
|
|
212
|
+
total = await service.count_sessions(request.AgentId, request.UserId)
|
|
213
|
+
session_payloads = [await _session_to_action_payload(session) for session in sessions]
|
|
214
|
+
return _action_response(
|
|
215
|
+
"ListSessions",
|
|
216
|
+
{
|
|
217
|
+
"Sessions": session_payloads,
|
|
218
|
+
"Total": total,
|
|
219
|
+
"Page": request.Page,
|
|
220
|
+
"PageSize": request.PageSize,
|
|
221
|
+
"DataSource": "runtime",
|
|
222
|
+
"Degraded": False,
|
|
223
|
+
"SessionContractVersion": 2,
|
|
224
|
+
},
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@sessions_router.post("/agentengine/api/v1/GetSession")
|
|
229
|
+
async def get_session_action(request: SessionIdRequest):
|
|
230
|
+
service = deps.resolve_session_service()
|
|
231
|
+
session = await _require_action_session(
|
|
232
|
+
service,
|
|
233
|
+
session_id=request.SessionId,
|
|
234
|
+
agent_id=request.AgentId,
|
|
235
|
+
user_id=request.UserId,
|
|
236
|
+
)
|
|
237
|
+
hydrated = await _hydrate_session(session)
|
|
238
|
+
if hydrated is None:
|
|
239
|
+
raise HTTPException(status_code=404, detail="Session not found")
|
|
240
|
+
return _action_response("GetSession", {"Session": await _session_to_action_payload(hydrated)})
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@sessions_router.post("/agentengine/api/v1/DeleteSession")
|
|
244
|
+
async def delete_session_action(request: SessionIdRequest):
|
|
245
|
+
service = deps.resolve_session_service()
|
|
246
|
+
await _require_action_session(
|
|
247
|
+
service,
|
|
248
|
+
session_id=request.SessionId,
|
|
249
|
+
agent_id=request.AgentId,
|
|
250
|
+
user_id=request.UserId,
|
|
251
|
+
)
|
|
252
|
+
await _cancel_detached_streams_for_session(request.SessionId)
|
|
253
|
+
deleted = await service.delete_session(request.SessionId)
|
|
254
|
+
if not deleted:
|
|
255
|
+
raise HTTPException(status_code=404, detail="Session not found")
|
|
256
|
+
return _action_response("DeleteSession", {"Deleted": True})
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@sessions_router.post("/agentengine/api/v1/ListSessionEvents")
|
|
260
|
+
async def list_session_events_action(request: ListSessionEventsActionRequest):
|
|
261
|
+
runner = get_state().runner
|
|
262
|
+
service = deps.resolve_session_service()
|
|
263
|
+
session_id = str(request.SessionId or "").strip()
|
|
264
|
+
if not session_id:
|
|
265
|
+
# 未传 SessionId:返回该 agent 全部会话的事件(存储层跨会话查询,真分页无截断;
|
|
266
|
+
# seq 游标是会话内序号,跨会话模式下不适用,直接忽略)
|
|
267
|
+
agent_id = str(request.AgentId or "").strip() or (
|
|
268
|
+
_runtime_agent_id(runner) if runner else "default-agent"
|
|
269
|
+
)
|
|
270
|
+
events = await service.get_events_for_agent(
|
|
271
|
+
agent_id,
|
|
272
|
+
user_id=request.UserId,
|
|
273
|
+
offset=request.Offset,
|
|
274
|
+
limit=request.Limit,
|
|
275
|
+
)
|
|
276
|
+
total = await service.count_events_for_agent(agent_id, user_id=request.UserId)
|
|
277
|
+
return _action_response(
|
|
278
|
+
"ListSessionEvents",
|
|
279
|
+
{
|
|
280
|
+
"Events": [_event_to_action_payload(event) for event in events],
|
|
281
|
+
"Total": total,
|
|
282
|
+
"Offset": request.Offset or 0,
|
|
283
|
+
"Limit": request.Limit if request.Limit is not None else len(events),
|
|
284
|
+
"AfterSeqId": request.AfterSeqId,
|
|
285
|
+
"BeforeSeqId": request.BeforeSeqId,
|
|
286
|
+
"ScopedAllSessions": True,
|
|
287
|
+
},
|
|
288
|
+
)
|
|
289
|
+
await _require_action_session(
|
|
290
|
+
service,
|
|
291
|
+
session_id=session_id,
|
|
292
|
+
agent_id=request.AgentId,
|
|
293
|
+
user_id=request.UserId,
|
|
294
|
+
)
|
|
295
|
+
events = await service.get_events(
|
|
296
|
+
session_id,
|
|
297
|
+
offset=request.Offset,
|
|
298
|
+
limit=request.Limit,
|
|
299
|
+
after_seq_id=request.AfterSeqId,
|
|
300
|
+
before_seq_id=request.BeforeSeqId,
|
|
301
|
+
)
|
|
302
|
+
total = await service.count_events(
|
|
303
|
+
session_id,
|
|
304
|
+
after_seq_id=request.AfterSeqId,
|
|
305
|
+
before_seq_id=request.BeforeSeqId,
|
|
306
|
+
)
|
|
307
|
+
return _action_response(
|
|
308
|
+
"ListSessionEvents",
|
|
309
|
+
{
|
|
310
|
+
"Events": [_event_to_action_payload(event) for event in events],
|
|
311
|
+
"Total": total,
|
|
312
|
+
"Offset": request.Offset or 0,
|
|
313
|
+
"Limit": request.Limit if request.Limit is not None else len(events),
|
|
314
|
+
"AfterSeqId": request.AfterSeqId,
|
|
315
|
+
"BeforeSeqId": request.BeforeSeqId,
|
|
316
|
+
},
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@sessions_router.post("/agentengine/api/v1/ListSessionMessages")
|
|
321
|
+
async def list_session_messages_action(request: ListSessionMessagesActionRequest):
|
|
322
|
+
from ksadk.conversations.message_projection import project_session_messages
|
|
323
|
+
|
|
324
|
+
service = deps.resolve_session_service()
|
|
325
|
+
await _require_action_session(
|
|
326
|
+
service,
|
|
327
|
+
session_id=request.SessionId,
|
|
328
|
+
agent_id=request.AgentId,
|
|
329
|
+
user_id=request.UserId,
|
|
330
|
+
)
|
|
331
|
+
total_events = await service.count_events(
|
|
332
|
+
request.SessionId,
|
|
333
|
+
after_seq_id=request.AfterSeqId,
|
|
334
|
+
before_seq_id=request.BeforeSeqId,
|
|
335
|
+
)
|
|
336
|
+
event_offset = 0
|
|
337
|
+
if request.AfterSeqId is not None and total_events > 2000:
|
|
338
|
+
# Storage pagination is tail-based. Offset past the newest surplus so
|
|
339
|
+
# reconnect starts with the oldest unseen window and cannot skip gaps.
|
|
340
|
+
event_offset = total_events - 2000
|
|
341
|
+
events = await service.get_events(
|
|
342
|
+
request.SessionId,
|
|
343
|
+
offset=event_offset,
|
|
344
|
+
limit=2000,
|
|
345
|
+
after_seq_id=request.AfterSeqId,
|
|
346
|
+
before_seq_id=request.BeforeSeqId,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
def project(
|
|
350
|
+
events_to_project: list[SessionEvent],
|
|
351
|
+
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
|
|
352
|
+
serialized = [_event_to_action_payload(event) for event in events_to_project]
|
|
353
|
+
return serialized, project_session_messages(
|
|
354
|
+
serialized,
|
|
355
|
+
include_reasoning=request.IncludeReasoning,
|
|
356
|
+
include_tool_events=request.IncludeToolEvents,
|
|
357
|
+
include_attachments=request.IncludeAttachments,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
serialized_events, messages = project(events)
|
|
361
|
+
if request.AfterSeqId is not None:
|
|
362
|
+
if total_events > len(events):
|
|
363
|
+
events = await _extend_invocation_after_window(
|
|
364
|
+
service,
|
|
365
|
+
request.SessionId,
|
|
366
|
+
events,
|
|
367
|
+
before_seq_id=request.BeforeSeqId,
|
|
368
|
+
)
|
|
369
|
+
serialized_events, messages = project(events)
|
|
370
|
+
page = messages
|
|
371
|
+
has_more = total_events > len(serialized_events)
|
|
372
|
+
next_cursor = None
|
|
373
|
+
else:
|
|
374
|
+
page_start = len(messages)
|
|
375
|
+
while page_start > 0:
|
|
376
|
+
group_start_seq_id = int(messages[page_start - 1].get("StartSeqId") or 0)
|
|
377
|
+
group_start_index = next(
|
|
378
|
+
(
|
|
379
|
+
index
|
|
380
|
+
for index, message in enumerate(messages[:page_start])
|
|
381
|
+
if int(message.get("StartSeqId") or 0) == group_start_seq_id
|
|
382
|
+
),
|
|
383
|
+
page_start - 1,
|
|
384
|
+
)
|
|
385
|
+
current_size = len(messages) - page_start
|
|
386
|
+
group_size = page_start - group_start_index
|
|
387
|
+
if current_size and current_size + group_size > request.Limit:
|
|
388
|
+
break
|
|
389
|
+
page_start = group_start_index
|
|
390
|
+
if len(messages) - page_start >= request.Limit:
|
|
391
|
+
break
|
|
392
|
+
page = messages[page_start:]
|
|
393
|
+
if (
|
|
394
|
+
page
|
|
395
|
+
and events
|
|
396
|
+
and total_events > len(events)
|
|
397
|
+
and _event_invocation_id(events[0])
|
|
398
|
+
and any(
|
|
399
|
+
str(message.get("InvocationId") or "") == _event_invocation_id(events[0])
|
|
400
|
+
for message in page
|
|
401
|
+
)
|
|
402
|
+
):
|
|
403
|
+
events = await _extend_invocation_before_window(
|
|
404
|
+
service,
|
|
405
|
+
request.SessionId,
|
|
406
|
+
events,
|
|
407
|
+
after_seq_id=request.AfterSeqId,
|
|
408
|
+
)
|
|
409
|
+
serialized_events, messages = project(events)
|
|
410
|
+
page_start = len(messages)
|
|
411
|
+
while page_start > 0:
|
|
412
|
+
group_start_seq_id = int(messages[page_start - 1].get("StartSeqId") or 0)
|
|
413
|
+
group_start_index = next(
|
|
414
|
+
(
|
|
415
|
+
index
|
|
416
|
+
for index, message in enumerate(messages[:page_start])
|
|
417
|
+
if int(message.get("StartSeqId") or 0) == group_start_seq_id
|
|
418
|
+
),
|
|
419
|
+
page_start - 1,
|
|
420
|
+
)
|
|
421
|
+
current_size = len(messages) - page_start
|
|
422
|
+
group_size = page_start - group_start_index
|
|
423
|
+
if current_size and current_size + group_size > request.Limit:
|
|
424
|
+
break
|
|
425
|
+
page_start = group_start_index
|
|
426
|
+
if len(messages) - page_start >= request.Limit:
|
|
427
|
+
break
|
|
428
|
+
page = messages[page_start:]
|
|
429
|
+
minimum_start_seq_id = int(page[0].get("StartSeqId") or 0) if page else 0
|
|
430
|
+
has_more = page_start > 0 or total_events > len(serialized_events)
|
|
431
|
+
# BeforeSeqId is exclusive. Use the invocation group boundary so the
|
|
432
|
+
# next page cannot duplicate reasoning/tools or skip its user message.
|
|
433
|
+
next_cursor = minimum_start_seq_id if has_more else None
|
|
434
|
+
latest_seq_id = (
|
|
435
|
+
int(page[-1].get("SeqId") or 0)
|
|
436
|
+
if page
|
|
437
|
+
else max(
|
|
438
|
+
(int(event.get("SeqId") or 0) for event in serialized_events),
|
|
439
|
+
default=int(request.AfterSeqId or 0),
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
return _action_response(
|
|
443
|
+
"ListSessionMessages",
|
|
444
|
+
{
|
|
445
|
+
"SessionId": request.SessionId,
|
|
446
|
+
"Messages": page,
|
|
447
|
+
"LatestSeqId": latest_seq_id,
|
|
448
|
+
"HasMore": has_more,
|
|
449
|
+
"NextCursor": next_cursor,
|
|
450
|
+
},
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def _count_resumable_checkpoints(checkpoints: list[dict[str, Any]]) -> int:
|
|
455
|
+
"""统计可恢复 checkpoint 数量。
|
|
456
|
+
|
|
457
|
+
规则:IsResumable=True AND ReplayAllowed!=False AND IsTerminal!=True
|
|
458
|
+
AND CheckpointStatus not in {expired, disabled}。
|
|
459
|
+
不排除 resumed(已恢复过的仍计入,符合存档点可反复读的回档语义)。
|
|
460
|
+
"""
|
|
461
|
+
resumable = 0
|
|
462
|
+
for cp in checkpoints:
|
|
463
|
+
if cp.get("IsResumable") is not True:
|
|
464
|
+
continue
|
|
465
|
+
if cp.get("ReplayAllowed") is False:
|
|
466
|
+
continue
|
|
467
|
+
if cp.get("IsTerminal") is True:
|
|
468
|
+
continue
|
|
469
|
+
status = str(cp.get("CheckpointStatus") or "").strip().lower()
|
|
470
|
+
if status in {"expired", "disabled"}:
|
|
471
|
+
continue
|
|
472
|
+
resumable += 1
|
|
473
|
+
return resumable
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
async def _list_checkpoints_payload(request: ListSessionCheckpointsActionRequest) -> dict[str, Any]:
|
|
477
|
+
service = deps.resolve_session_service()
|
|
478
|
+
run_id_filter = str(request.RunId or "").strip()
|
|
479
|
+
framework_filter = str(request.Framework or "").strip().lower()
|
|
480
|
+
|
|
481
|
+
session_id = str(request.SessionId or "").strip()
|
|
482
|
+
if session_id:
|
|
483
|
+
await _require_action_session(
|
|
484
|
+
service,
|
|
485
|
+
session_id=session_id,
|
|
486
|
+
agent_id=request.AgentId,
|
|
487
|
+
user_id=request.UserId,
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
audit_by_session: dict[str, dict[tuple[str, str], dict[str, Any]]] = {}
|
|
491
|
+
latest_by_session_run: dict[tuple[str, str], int] = {}
|
|
492
|
+
run_seen = not run_id_filter
|
|
493
|
+
async for page in _iter_scoped_event_pages(
|
|
494
|
+
service,
|
|
495
|
+
session_id=session_id or None,
|
|
496
|
+
agent_id=request.AgentId,
|
|
497
|
+
user_id=request.UserId,
|
|
498
|
+
):
|
|
499
|
+
for event in page:
|
|
500
|
+
if run_id_filter and _event_run_id(event) == run_id_filter:
|
|
501
|
+
run_seen = True
|
|
502
|
+
_record_resume_audit(audit_by_session, event)
|
|
503
|
+
checkpoint = _checkpoint_event_to_action_payload(event)
|
|
504
|
+
if checkpoint is None or not (checkpoint.get("Metadata") or {}).get(
|
|
505
|
+
"only_latest_resumable"
|
|
506
|
+
):
|
|
507
|
+
continue
|
|
508
|
+
key = (event.session_id, str(checkpoint.get("RunId") or ""))
|
|
509
|
+
latest_by_session_run[key] = max(
|
|
510
|
+
latest_by_session_run.get(key, 0),
|
|
511
|
+
int(checkpoint.get("SeqId") or 0),
|
|
512
|
+
)
|
|
513
|
+
if session_id and not run_seen:
|
|
514
|
+
raise HTTPException(status_code=409, detail="RunId does not belong to SessionId")
|
|
515
|
+
|
|
516
|
+
def project_checkpoint(event: SessionEvent) -> dict[str, Any] | None:
|
|
517
|
+
checkpoint = _checkpoint_event_to_action_payload(event)
|
|
518
|
+
if checkpoint is None:
|
|
519
|
+
return None
|
|
520
|
+
checkpoint = _apply_checkpoint_resume_audit(
|
|
521
|
+
checkpoint,
|
|
522
|
+
audit_by_session.get(event.session_id, {}),
|
|
523
|
+
)
|
|
524
|
+
checkpoint = _apply_latest_checkpoint_policy(
|
|
525
|
+
checkpoint,
|
|
526
|
+
latest_by_session_run,
|
|
527
|
+
session_id=event.session_id,
|
|
528
|
+
)
|
|
529
|
+
if run_id_filter and checkpoint["RunId"] != run_id_filter:
|
|
530
|
+
return None
|
|
531
|
+
if framework_filter and str(checkpoint["Framework"]).lower() != framework_filter:
|
|
532
|
+
return None
|
|
533
|
+
return checkpoint
|
|
534
|
+
|
|
535
|
+
total = 0
|
|
536
|
+
resumable_total = 0
|
|
537
|
+
async for page in _iter_scoped_event_pages(
|
|
538
|
+
service,
|
|
539
|
+
session_id=session_id or None,
|
|
540
|
+
agent_id=request.AgentId,
|
|
541
|
+
user_id=request.UserId,
|
|
542
|
+
):
|
|
543
|
+
for event in page:
|
|
544
|
+
checkpoint = project_checkpoint(event)
|
|
545
|
+
if checkpoint is None:
|
|
546
|
+
continue
|
|
547
|
+
if checkpoint.get("IsResumable") is True:
|
|
548
|
+
resumable_total += 1
|
|
549
|
+
if request.OnlyResumable and checkpoint.get("IsResumable") is not True:
|
|
550
|
+
continue
|
|
551
|
+
total += 1
|
|
552
|
+
|
|
553
|
+
offset = int(request.Offset or 0)
|
|
554
|
+
limit = int(request.Limit)
|
|
555
|
+
window_end = max(total - offset, 0)
|
|
556
|
+
window_start = max(window_end - limit, 0)
|
|
557
|
+
checkpoints: list[dict[str, Any]] = []
|
|
558
|
+
filtered_index = 0
|
|
559
|
+
async for page in _iter_scoped_event_pages(
|
|
560
|
+
service,
|
|
561
|
+
session_id=session_id or None,
|
|
562
|
+
agent_id=request.AgentId,
|
|
563
|
+
user_id=request.UserId,
|
|
564
|
+
):
|
|
565
|
+
for event in page:
|
|
566
|
+
checkpoint = project_checkpoint(event)
|
|
567
|
+
if checkpoint is None:
|
|
568
|
+
continue
|
|
569
|
+
if request.OnlyResumable and checkpoint.get("IsResumable") is not True:
|
|
570
|
+
continue
|
|
571
|
+
if window_start <= filtered_index < window_end:
|
|
572
|
+
checkpoints.append(checkpoint)
|
|
573
|
+
filtered_index += 1
|
|
574
|
+
if filtered_index >= window_end:
|
|
575
|
+
break
|
|
576
|
+
if filtered_index >= window_end:
|
|
577
|
+
break
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
"Checkpoints": checkpoints,
|
|
581
|
+
"Total": total,
|
|
582
|
+
"ResumableTotal": resumable_total,
|
|
583
|
+
"HasResumableCheckpoint": resumable_total > 0,
|
|
584
|
+
"Offset": offset,
|
|
585
|
+
"Limit": limit,
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
@sessions_router.post("/agentengine/api/v1/ListSessionCheckpoints")
|
|
590
|
+
async def list_session_checkpoints_action(request: ListSessionCheckpointsActionRequest):
|
|
591
|
+
return _action_response("ListSessionCheckpoints", await _list_checkpoints_payload(request))
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
@tools_router.post("/agentengine/api/v1/ListToolReceipts")
|
|
595
|
+
async def list_tool_receipts_action(request: ListToolReceiptsActionRequest):
|
|
596
|
+
service = deps.resolve_session_service()
|
|
597
|
+
await _require_action_session(
|
|
598
|
+
service,
|
|
599
|
+
session_id=request.SessionId,
|
|
600
|
+
agent_id=request.AgentId,
|
|
601
|
+
user_id=request.UserId,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
run_id_filter = str(request.RunId or "").strip()
|
|
605
|
+
checkpoint_id_filter = str(request.CheckpointId or "").strip()
|
|
606
|
+
total = 0
|
|
607
|
+
async for page in _iter_session_event_pages(service, request.SessionId):
|
|
608
|
+
for event in page:
|
|
609
|
+
receipt = _tool_receipt_event_to_action_payload(event)
|
|
610
|
+
if receipt is None:
|
|
611
|
+
continue
|
|
612
|
+
if run_id_filter and receipt["RunId"] != run_id_filter:
|
|
613
|
+
continue
|
|
614
|
+
if checkpoint_id_filter and receipt["CheckpointId"] != checkpoint_id_filter:
|
|
615
|
+
continue
|
|
616
|
+
total += 1
|
|
617
|
+
|
|
618
|
+
offset = int(request.Offset)
|
|
619
|
+
limit = int(request.Limit)
|
|
620
|
+
window_end = max(total - offset, 0)
|
|
621
|
+
window_start = max(window_end - limit, 0)
|
|
622
|
+
receipts: list[dict[str, Any]] = []
|
|
623
|
+
filtered_index = 0
|
|
624
|
+
async for page in _iter_session_event_pages(service, request.SessionId):
|
|
625
|
+
for event in page:
|
|
626
|
+
receipt = _tool_receipt_event_to_action_payload(event)
|
|
627
|
+
if receipt is None:
|
|
628
|
+
continue
|
|
629
|
+
if run_id_filter and receipt["RunId"] != run_id_filter:
|
|
630
|
+
continue
|
|
631
|
+
if checkpoint_id_filter and receipt["CheckpointId"] != checkpoint_id_filter:
|
|
632
|
+
continue
|
|
633
|
+
if window_start <= filtered_index < window_end:
|
|
634
|
+
receipts.append(receipt)
|
|
635
|
+
filtered_index += 1
|
|
636
|
+
if filtered_index >= window_end:
|
|
637
|
+
break
|
|
638
|
+
if filtered_index >= window_end:
|
|
639
|
+
break
|
|
640
|
+
|
|
641
|
+
return _action_response(
|
|
642
|
+
"ListToolReceipts",
|
|
643
|
+
{
|
|
644
|
+
"ToolReceipts": receipts,
|
|
645
|
+
"Total": total,
|
|
646
|
+
"Offset": offset,
|
|
647
|
+
"Limit": limit,
|
|
648
|
+
},
|
|
649
|
+
)
|