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,443 @@
|
|
|
1
|
+
"""Runtime HTTP request models and pure projection helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from typing import Any, Dict, List, Mapping, Optional
|
|
8
|
+
|
|
9
|
+
from fastapi import HTTPException
|
|
10
|
+
from pydantic import BaseModel, Field, field_validator
|
|
11
|
+
|
|
12
|
+
from ksadk.conversations.run_kinds import RUN_MODE_UNKNOWN, RUN_TRIGGER_UNKNOWN
|
|
13
|
+
from ksadk.conversations.run_status import RUN_STATUS_ACTIVE, RUN_STATUS_TERMINAL
|
|
14
|
+
from ksadk.runners.base_runner import BaseRunner
|
|
15
|
+
from ksadk.sessions import SessionEvent
|
|
16
|
+
|
|
17
|
+
_RUN_TERMINAL_STATUSES = RUN_STATUS_TERMINAL
|
|
18
|
+
_RUN_ACTIVE_STATUSES = RUN_STATUS_ACTIVE
|
|
19
|
+
_EVENT_SCAN_PAGE_SIZE = 500
|
|
20
|
+
_MAX_PREVIEW_TOOL_RECEIPTS = 500
|
|
21
|
+
_RUNTIME_RUN_STATUS_BY_EVENT_TYPE = {
|
|
22
|
+
"run.started": "in_progress",
|
|
23
|
+
"run.progress": "in_progress",
|
|
24
|
+
"run.interrupted": "interrupted",
|
|
25
|
+
"run.completed": "completed",
|
|
26
|
+
"run.failed": "failed",
|
|
27
|
+
"run.canceled": "cancelled",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _parse_iso_datetime(value: Any) -> datetime | None:
|
|
32
|
+
raw = str(value or "").strip()
|
|
33
|
+
if not raw:
|
|
34
|
+
return None
|
|
35
|
+
if raw.endswith("Z"):
|
|
36
|
+
raw = f"{raw[:-1]}+00:00"
|
|
37
|
+
try:
|
|
38
|
+
parsed = datetime.fromisoformat(raw)
|
|
39
|
+
except ValueError:
|
|
40
|
+
return None
|
|
41
|
+
if parsed.tzinfo is None:
|
|
42
|
+
return parsed.replace(tzinfo=timezone.utc)
|
|
43
|
+
return parsed.astimezone(timezone.utc)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class UiBootstrapRequest(BaseModel):
|
|
47
|
+
AgentId: Optional[str] = None
|
|
48
|
+
SessionId: Optional[str] = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class CreateSessionActionRequest(BaseModel):
|
|
52
|
+
AgentId: str
|
|
53
|
+
UserId: Optional[str] = "user"
|
|
54
|
+
SessionId: Optional[str] = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ListSessionsActionRequest(BaseModel):
|
|
58
|
+
AgentId: str
|
|
59
|
+
UserId: Optional[str] = None
|
|
60
|
+
Page: int = Field(1, ge=1)
|
|
61
|
+
PageSize: int = Field(20, ge=1, le=200)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class SessionIdRequest(BaseModel):
|
|
65
|
+
SessionId: str
|
|
66
|
+
AgentId: Optional[str] = None
|
|
67
|
+
UserId: Optional[str] = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class ListSessionEventsActionRequest(BaseModel):
|
|
71
|
+
AgentId: Optional[str] = None
|
|
72
|
+
SessionId: Optional[str] = None
|
|
73
|
+
UserId: Optional[str] = None
|
|
74
|
+
Offset: Optional[int] = Field(None, ge=0)
|
|
75
|
+
Limit: int = Field(200, ge=1, le=2000)
|
|
76
|
+
AfterSeqId: Optional[int] = Field(None, ge=0)
|
|
77
|
+
BeforeSeqId: Optional[int] = Field(None, ge=1)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ListSessionMessagesActionRequest(BaseModel):
|
|
81
|
+
AgentId: Optional[str] = None
|
|
82
|
+
UserId: Optional[str] = None
|
|
83
|
+
SessionId: str
|
|
84
|
+
AfterSeqId: Optional[int] = Field(None, ge=0)
|
|
85
|
+
BeforeSeqId: Optional[int] = Field(None, ge=1)
|
|
86
|
+
Limit: int = Field(50, ge=1, le=200)
|
|
87
|
+
IncludeReasoning: bool = False
|
|
88
|
+
IncludeToolEvents: bool = False
|
|
89
|
+
IncludeAttachments: bool = True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ListSessionCheckpointsActionRequest(BaseModel):
|
|
93
|
+
AgentId: str
|
|
94
|
+
SessionId: Optional[str] = None
|
|
95
|
+
UserId: Optional[str] = None
|
|
96
|
+
RunId: Optional[str] = None
|
|
97
|
+
OnlyResumable: bool = False
|
|
98
|
+
Framework: Optional[str] = None
|
|
99
|
+
Offset: Optional[int] = Field(None, ge=0)
|
|
100
|
+
Limit: int = Field(100, ge=1, le=500)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class ListToolReceiptsActionRequest(BaseModel):
|
|
104
|
+
AgentId: str
|
|
105
|
+
UserId: Optional[str] = None
|
|
106
|
+
SessionId: str
|
|
107
|
+
RunId: Optional[str] = None
|
|
108
|
+
CheckpointId: Optional[str] = None
|
|
109
|
+
Offset: int = Field(0, ge=0)
|
|
110
|
+
Limit: int = Field(200, ge=1, le=500)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class ResumeRunActionRequest(BaseModel):
|
|
114
|
+
AgentId: str
|
|
115
|
+
UserId: Optional[str] = None
|
|
116
|
+
SessionId: str
|
|
117
|
+
RunId: str
|
|
118
|
+
CheckpointId: str
|
|
119
|
+
ResumeAttemptId: Optional[str] = None
|
|
120
|
+
InvocationId: Optional[str] = None
|
|
121
|
+
Stream: bool = False
|
|
122
|
+
Model: Optional[str] = None
|
|
123
|
+
ModelMetadata: Optional[Dict[str, Any]] = None
|
|
124
|
+
ModelOptions: Optional[Dict[str, Any]] = None
|
|
125
|
+
Metadata: Optional[Dict[str, Any]] = None
|
|
126
|
+
ResumeInstructionEnabled: bool = False
|
|
127
|
+
ResumeInstruction: Optional[str] = None
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class GetCheckpointResumePreviewActionRequest(BaseModel):
|
|
131
|
+
AgentId: str
|
|
132
|
+
UserId: Optional[str] = None
|
|
133
|
+
SessionId: str
|
|
134
|
+
RunId: str
|
|
135
|
+
CheckpointId: str
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class RunAgentActionRequest(BaseModel):
|
|
139
|
+
AgentId: str
|
|
140
|
+
Messages: List[Dict[str, Any]] = Field(default_factory=list)
|
|
141
|
+
UserId: Optional[str] = "user"
|
|
142
|
+
AccountId: Optional[str] = None
|
|
143
|
+
SessionId: Optional[str] = None
|
|
144
|
+
InvocationId: Optional[str] = None
|
|
145
|
+
ApiFormat: str = "responses"
|
|
146
|
+
Stream: bool = False
|
|
147
|
+
Background: bool = False # 立即返回 job 句柄,后台执行,进度走 SubscribeRunEvents
|
|
148
|
+
Model: Optional[str] = None
|
|
149
|
+
ModelMetadata: Optional[Dict[str, Any]] = None
|
|
150
|
+
ModelOptions: Optional[Dict[str, Any]] = None
|
|
151
|
+
Metadata: Optional[Dict[str, Any]] = None
|
|
152
|
+
ResponsesInput: Optional[Any] = None
|
|
153
|
+
PreviousResponseId: Optional[str] = None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class ResponseFeedbackRefActionRequest(BaseModel):
|
|
157
|
+
AgentId: str
|
|
158
|
+
SessionId: str
|
|
159
|
+
ResponseId: str
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class UpsertResponseFeedbackActionRequest(ResponseFeedbackRefActionRequest):
|
|
163
|
+
Rating: str
|
|
164
|
+
Comment: Optional[str] = ""
|
|
165
|
+
EventId: Optional[str] = None
|
|
166
|
+
TraceId: Optional[str] = None
|
|
167
|
+
RootSpanId: Optional[str] = None
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class ResponsesRequest(BaseModel):
|
|
171
|
+
input: Any
|
|
172
|
+
model: Optional[str] = None
|
|
173
|
+
model_metadata: Optional[Dict[str, Any]] = None
|
|
174
|
+
model_options: Optional[Dict[str, Any]] = None
|
|
175
|
+
instructions: Optional[str] = None
|
|
176
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
177
|
+
conversation: Optional[Any] = None
|
|
178
|
+
safety_identifier: Optional[str] = None
|
|
179
|
+
prompt_cache_key: Optional[str] = None
|
|
180
|
+
user: Optional[str] = None
|
|
181
|
+
account_id: Optional[str] = None
|
|
182
|
+
store: Optional[bool] = None
|
|
183
|
+
previous_response_id: Optional[str] = None
|
|
184
|
+
stream: bool = False
|
|
185
|
+
session_id: Optional[str] = None
|
|
186
|
+
|
|
187
|
+
@field_validator("metadata")
|
|
188
|
+
@classmethod
|
|
189
|
+
def validate_metadata(cls, value: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
|
190
|
+
if value is None:
|
|
191
|
+
return None
|
|
192
|
+
public_items = [(key, item) for key, item in value.items() if key != "agentengine"]
|
|
193
|
+
if len(public_items) > 16:
|
|
194
|
+
raise ValueError("Responses metadata supports at most 16 key-value pairs")
|
|
195
|
+
for key, item in public_items:
|
|
196
|
+
if len(key) > 64:
|
|
197
|
+
raise ValueError("Responses metadata keys must be at most 64 characters")
|
|
198
|
+
if not isinstance(item, str):
|
|
199
|
+
raise ValueError("Responses metadata values must be strings")
|
|
200
|
+
if len(item) > 512:
|
|
201
|
+
raise ValueError("Responses metadata values must be at most 512 characters")
|
|
202
|
+
return value
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class WorkspaceListActionRequest(BaseModel):
|
|
206
|
+
AgentId: Optional[str] = None
|
|
207
|
+
Path: str = "."
|
|
208
|
+
Recursive: bool = False
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _clean_optional_string(value: Any) -> str | None:
|
|
212
|
+
if value is None:
|
|
213
|
+
return None
|
|
214
|
+
text = str(value).strip()
|
|
215
|
+
return text or None
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _resolve_responses_conversation_id(conversation_value: Any) -> str | None:
|
|
219
|
+
if conversation_value is None:
|
|
220
|
+
return None
|
|
221
|
+
if isinstance(conversation_value, str):
|
|
222
|
+
return _clean_optional_string(conversation_value)
|
|
223
|
+
if isinstance(conversation_value, Mapping):
|
|
224
|
+
return _clean_optional_string(conversation_value.get("id"))
|
|
225
|
+
raise HTTPException(
|
|
226
|
+
status_code=400,
|
|
227
|
+
detail="Responses field 'conversation' must be a string or an object with an 'id'.",
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _resolve_responses_session_and_user(request: ResponsesRequest) -> tuple[str | None, str]:
|
|
232
|
+
conversation_id = _resolve_responses_conversation_id(request.conversation)
|
|
233
|
+
legacy_session_id = _clean_optional_string(request.session_id)
|
|
234
|
+
|
|
235
|
+
if conversation_id and legacy_session_id and conversation_id != legacy_session_id:
|
|
236
|
+
raise HTTPException(
|
|
237
|
+
status_code=400,
|
|
238
|
+
detail=(
|
|
239
|
+
"Responses field 'conversation' conflicts with ksadk legacy field "
|
|
240
|
+
"'session_id'. Use 'conversation' for OpenAI-compatible calls."
|
|
241
|
+
),
|
|
242
|
+
)
|
|
243
|
+
if conversation_id and request.previous_response_id:
|
|
244
|
+
raise HTTPException(
|
|
245
|
+
status_code=400,
|
|
246
|
+
detail=(
|
|
247
|
+
"Responses fields 'conversation' and 'previous_response_id' cannot be "
|
|
248
|
+
"used together."
|
|
249
|
+
),
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
resolved_session_id = conversation_id or legacy_session_id
|
|
253
|
+
resolved_user_id = (
|
|
254
|
+
_clean_optional_string(request.safety_identifier)
|
|
255
|
+
or _clean_optional_string(request.user)
|
|
256
|
+
or "user"
|
|
257
|
+
)
|
|
258
|
+
return resolved_session_id, resolved_user_id
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _runtime_agent_id(active_runner: BaseRunner) -> str:
|
|
262
|
+
runtime_id = _clean_optional_string(os.getenv("AGENT_RUNTIME_ID"))
|
|
263
|
+
if runtime_id:
|
|
264
|
+
return runtime_id
|
|
265
|
+
return str(getattr(active_runner.detection_result, "name", "") or "agent")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _metadata_invocation_id(metadata: Mapping[str, Any] | None) -> str | None:
|
|
269
|
+
if not isinstance(metadata, Mapping):
|
|
270
|
+
return None
|
|
271
|
+
agentengine_metadata = metadata.get("agentengine")
|
|
272
|
+
if not isinstance(agentengine_metadata, Mapping):
|
|
273
|
+
return None
|
|
274
|
+
return _clean_optional_string(agentengine_metadata.get("invocation_id"))
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _split_custom_metadata(
|
|
278
|
+
metadata: Mapping[str, Any] | None,
|
|
279
|
+
) -> tuple[dict[str, Any], dict[str, Any]]:
|
|
280
|
+
public_metadata = dict(metadata or {})
|
|
281
|
+
runtime_metadata: dict[str, Any] = {}
|
|
282
|
+
agentengine_metadata = public_metadata.get("agentengine")
|
|
283
|
+
public_metadata.pop("agentengine", None)
|
|
284
|
+
if isinstance(agentengine_metadata, Mapping):
|
|
285
|
+
runtime_metadata["agentengine"] = dict(agentengine_metadata)
|
|
286
|
+
# The approval profile is a small, validated-by-the-agent runtime control.
|
|
287
|
+
# It must not be mixed into caller-visible public metadata.
|
|
288
|
+
tool_approval_mode = agentengine_metadata.get("tool_approval_mode")
|
|
289
|
+
if isinstance(tool_approval_mode, str):
|
|
290
|
+
runtime_metadata["tool_approval_mode"] = tool_approval_mode
|
|
291
|
+
return public_metadata, runtime_metadata
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _run_agent_response_metadata(
|
|
295
|
+
custom_metadata: Mapping[str, Any] | None,
|
|
296
|
+
result: Mapping[str, Any] | None,
|
|
297
|
+
) -> dict[str, Any]:
|
|
298
|
+
response_metadata = dict(custom_metadata or {})
|
|
299
|
+
result_metadata = result.get("metadata") if isinstance(result, Mapping) else None
|
|
300
|
+
if isinstance(result_metadata, Mapping):
|
|
301
|
+
agentengine_metadata = result_metadata.get("agentengine")
|
|
302
|
+
if isinstance(agentengine_metadata, Mapping):
|
|
303
|
+
response_metadata["agentengine"] = dict(agentengine_metadata)
|
|
304
|
+
return response_metadata
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def _event_text(event: SessionEvent) -> str:
|
|
308
|
+
parts = (event.content or {}).get("parts")
|
|
309
|
+
if isinstance(parts, list):
|
|
310
|
+
text_parts: list[str] = []
|
|
311
|
+
for part in parts:
|
|
312
|
+
if isinstance(part, Mapping):
|
|
313
|
+
text_parts.append(str(part.get("text") or ""))
|
|
314
|
+
else:
|
|
315
|
+
text_parts.append(str(part or ""))
|
|
316
|
+
text = "".join(text_parts).strip()
|
|
317
|
+
if text:
|
|
318
|
+
return text
|
|
319
|
+
return str((event.content or {}).get("text") or "").strip()
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _truncate_session_text(text: str, limit: int = 512) -> str:
|
|
323
|
+
normalized = " ".join(str(text or "").strip().split())
|
|
324
|
+
if len(normalized) <= limit:
|
|
325
|
+
return normalized
|
|
326
|
+
return f"{normalized[: max(limit - 1, 0)].rstrip()}…"
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def _session_user_prompt_from_event(event: SessionEvent) -> str:
|
|
330
|
+
metadata = event.metadata or {}
|
|
331
|
+
content = event.content or {}
|
|
332
|
+
return str(
|
|
333
|
+
metadata.get("agent_input")
|
|
334
|
+
or metadata.get("user_input")
|
|
335
|
+
or content.get("agent_input")
|
|
336
|
+
or _event_text(event)
|
|
337
|
+
or ""
|
|
338
|
+
).strip()
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def _run_status_payload_status(event: SessionEvent) -> str:
|
|
342
|
+
legacy_status = str(
|
|
343
|
+
(event.metadata or {}).get("status")
|
|
344
|
+
or (event.metadata or {}).get("run_status")
|
|
345
|
+
or (event.content or {}).get("status")
|
|
346
|
+
or ""
|
|
347
|
+
).strip()
|
|
348
|
+
if legacy_status:
|
|
349
|
+
return legacy_status
|
|
350
|
+
runtime_payload = (event.content or {}).get("payload")
|
|
351
|
+
runtime_status = (
|
|
352
|
+
str(runtime_payload.get("status") or "").strip()
|
|
353
|
+
if isinstance(runtime_payload, Mapping)
|
|
354
|
+
else ""
|
|
355
|
+
)
|
|
356
|
+
return runtime_status or _RUNTIME_RUN_STATUS_BY_EVENT_TYPE.get(event.event_type, "")
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _is_run_lifecycle_event(event: SessionEvent) -> bool:
|
|
360
|
+
return event.event_type == "run_status" or event.event_type in _RUNTIME_RUN_STATUS_BY_EVENT_TYPE
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _event_run_id(event: SessionEvent) -> str:
|
|
364
|
+
return str(
|
|
365
|
+
(event.metadata or {}).get("run_id")
|
|
366
|
+
or (event.metadata or {}).get("invocation_id")
|
|
367
|
+
or event.invocation_id
|
|
368
|
+
or ""
|
|
369
|
+
).strip()
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _session_topic_from_events(events: list[SessionEvent]) -> str:
|
|
373
|
+
for event in reversed(events):
|
|
374
|
+
metadata = event.metadata or {}
|
|
375
|
+
tool_output = metadata.get("tool_output")
|
|
376
|
+
if isinstance(tool_output, Mapping):
|
|
377
|
+
topic = str(tool_output.get("topic") or tool_output.get("research_title") or "").strip()
|
|
378
|
+
if topic:
|
|
379
|
+
return topic
|
|
380
|
+
topic = str(metadata.get("research_title") or metadata.get("task_title") or "").strip()
|
|
381
|
+
if topic:
|
|
382
|
+
return topic
|
|
383
|
+
return ""
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _latest_session_run_status(events: list[SessionEvent]) -> tuple[str, str]:
|
|
387
|
+
latest_by_invocation: dict[str, tuple[str, SessionEvent]] = {}
|
|
388
|
+
for event in reversed(events):
|
|
389
|
+
if not _is_run_lifecycle_event(event):
|
|
390
|
+
continue
|
|
391
|
+
status = _run_status_payload_status(event)
|
|
392
|
+
invocation_id = _event_run_id(event)
|
|
393
|
+
if status or invocation_id:
|
|
394
|
+
latest_by_invocation.setdefault(invocation_id, (status, event))
|
|
395
|
+
for invocation_id, (status, _) in latest_by_invocation.items():
|
|
396
|
+
if status in _RUN_ACTIVE_STATUSES:
|
|
397
|
+
return invocation_id, status
|
|
398
|
+
for invocation_id, (status, _) in latest_by_invocation.items():
|
|
399
|
+
if status not in _RUN_TERMINAL_STATUSES:
|
|
400
|
+
return invocation_id, status
|
|
401
|
+
if latest_by_invocation:
|
|
402
|
+
invocation_id, (status, _) = next(iter(latest_by_invocation.items()))
|
|
403
|
+
return invocation_id, status
|
|
404
|
+
for event in reversed(events):
|
|
405
|
+
invocation_id = _event_run_id(event)
|
|
406
|
+
if invocation_id:
|
|
407
|
+
return invocation_id, ""
|
|
408
|
+
return "", ""
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def _latest_session_run_metadata(
|
|
412
|
+
events: list[SessionEvent],
|
|
413
|
+
) -> tuple[str, str, str, str]:
|
|
414
|
+
"""返回 (invocation_id, status, run_mode, run_trigger)。
|
|
415
|
+
|
|
416
|
+
与 _latest_session_run_status 同语义,但额外从最新 run_status 事件的 metadata
|
|
417
|
+
读取 run_mode/run_trigger。旧事件缺字段降级 unknown。原 _latest_session_run_status
|
|
418
|
+
不动,保护现有 ActiveInvocationId/ActiveRunStatus 契约。
|
|
419
|
+
"""
|
|
420
|
+
invocation_id, status = _latest_session_run_status(events)
|
|
421
|
+
run_mode = RUN_MODE_UNKNOWN
|
|
422
|
+
run_trigger = RUN_TRIGGER_UNKNOWN
|
|
423
|
+
if invocation_id:
|
|
424
|
+
for event in reversed(events):
|
|
425
|
+
if not _is_run_lifecycle_event(event) or _event_run_id(event) != invocation_id:
|
|
426
|
+
continue
|
|
427
|
+
metadata = event.metadata or {}
|
|
428
|
+
run_mode = str(metadata.get("run_mode") or RUN_MODE_UNKNOWN)
|
|
429
|
+
run_trigger = str(metadata.get("run_trigger") or RUN_TRIGGER_UNKNOWN)
|
|
430
|
+
break
|
|
431
|
+
return invocation_id, status, run_mode, run_trigger
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
class WorkspaceDeleteActionRequest(BaseModel):
|
|
435
|
+
AgentId: Optional[str] = None
|
|
436
|
+
Path: str
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
class CancelRunActionRequest(BaseModel):
|
|
440
|
+
AgentId: Optional[str] = None
|
|
441
|
+
UserId: Optional[str] = None
|
|
442
|
+
SessionId: Optional[str] = None
|
|
443
|
+
InvocationId: str
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""OpenAI Responses and Chat Completions compatibility routes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import uuid
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from typing import Any, Dict, List, Optional
|
|
8
|
+
|
|
9
|
+
from fastapi.responses import StreamingResponse
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from ksadk.conversations.run_kinds import RUN_MODE_FOREGROUND, trigger_from_resume_input
|
|
13
|
+
|
|
14
|
+
from . import dependencies as deps
|
|
15
|
+
from .checkpoint_resolution import _resolve_checkpoint_resume_input_from_session
|
|
16
|
+
from .common import _prepare_runner_for_model, _resolve_active_runner
|
|
17
|
+
from .models import (
|
|
18
|
+
ResponsesRequest,
|
|
19
|
+
_clean_optional_string,
|
|
20
|
+
_metadata_invocation_id,
|
|
21
|
+
_resolve_responses_session_and_user,
|
|
22
|
+
_runtime_agent_id,
|
|
23
|
+
_split_custom_metadata,
|
|
24
|
+
)
|
|
25
|
+
from .routers import openai_compat_router
|
|
26
|
+
from .streaming import _detached_resume_key_from_input, _reject_if_detached_resume_active
|
|
27
|
+
from .workspace import _build_models_payload
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ChatCompletionRequest(BaseModel):
|
|
31
|
+
messages: List[Dict[str, Any]]
|
|
32
|
+
model: Optional[str] = None
|
|
33
|
+
model_metadata: Optional[Dict[str, Any]] = None
|
|
34
|
+
model_options: Optional[Dict[str, Any]] = None
|
|
35
|
+
stream: bool = False
|
|
36
|
+
session_id: Optional[str] = None
|
|
37
|
+
user: Optional[str] = None
|
|
38
|
+
account_id: Optional[str] = None
|
|
39
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
40
|
+
temperature: Optional[float] = 0.7
|
|
41
|
+
max_tokens: Optional[int] = None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@openai_compat_router.get("/v1/models")
|
|
45
|
+
async def list_openai_models():
|
|
46
|
+
"""Expose the current model catalog through the OpenAI-compatible path."""
|
|
47
|
+
|
|
48
|
+
payload = await _build_models_payload()
|
|
49
|
+
return {
|
|
50
|
+
"object": "list",
|
|
51
|
+
"data": payload.get("data", []),
|
|
52
|
+
"current": payload.get("current"),
|
|
53
|
+
"source": payload.get("source", ""),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@openai_compat_router.post("/v1/responses")
|
|
58
|
+
async def responses(request: ResponsesRequest):
|
|
59
|
+
"""OpenAI Responses 兼容接口。"""
|
|
60
|
+
active_runner = _resolve_active_runner()
|
|
61
|
+
resolved_session_id, resolved_user_id = _resolve_responses_session_and_user(request)
|
|
62
|
+
agent_id = _runtime_agent_id(active_runner)
|
|
63
|
+
|
|
64
|
+
resume_input = deps.conversation().extract_responses_resume_input(request.input)
|
|
65
|
+
resume_input = await _resolve_checkpoint_resume_input_from_session(
|
|
66
|
+
service=deps.resolve_session_service(),
|
|
67
|
+
agent_id=agent_id,
|
|
68
|
+
session_id=resolved_session_id,
|
|
69
|
+
resume_input=resume_input,
|
|
70
|
+
)
|
|
71
|
+
messages = (
|
|
72
|
+
[]
|
|
73
|
+
if resume_input is not None
|
|
74
|
+
else deps.conversation().normalize_responses_input(request.input)
|
|
75
|
+
)
|
|
76
|
+
custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
|
|
77
|
+
if request.previous_response_id:
|
|
78
|
+
request_metadata["previous_response_id"] = request.previous_response_id
|
|
79
|
+
if request.prompt_cache_key:
|
|
80
|
+
request_metadata["prompt_cache_key"] = request.prompt_cache_key
|
|
81
|
+
if request.safety_identifier:
|
|
82
|
+
request_metadata["safety_identifier"] = request.safety_identifier
|
|
83
|
+
if request.user:
|
|
84
|
+
request_metadata["user"] = request.user
|
|
85
|
+
if request.conversation is not None:
|
|
86
|
+
request_metadata["conversation"] = request.conversation
|
|
87
|
+
if request.store is not None:
|
|
88
|
+
request_metadata["store"] = request.store
|
|
89
|
+
account_id = _clean_optional_string(request.account_id)
|
|
90
|
+
invocation_id = _metadata_invocation_id(request_metadata)
|
|
91
|
+
|
|
92
|
+
if request.stream:
|
|
93
|
+
resume_key = _detached_resume_key_from_input(resolved_session_id, resume_input)
|
|
94
|
+
_reject_if_detached_resume_active(resume_key)
|
|
95
|
+
return deps.detached_streaming_response(
|
|
96
|
+
deps.conversation().stream_responses_conversation_turn(
|
|
97
|
+
runner=active_runner,
|
|
98
|
+
agent_id=agent_id,
|
|
99
|
+
user_id=resolved_user_id,
|
|
100
|
+
messages=messages,
|
|
101
|
+
session_id=resolved_session_id,
|
|
102
|
+
model=request.model,
|
|
103
|
+
model_metadata=request.model_metadata,
|
|
104
|
+
model_options=request.model_options,
|
|
105
|
+
instructions=request.instructions,
|
|
106
|
+
request_metadata=request_metadata,
|
|
107
|
+
custom_metadata=custom_metadata,
|
|
108
|
+
resume_input=resume_input,
|
|
109
|
+
account_id=account_id,
|
|
110
|
+
invocation_id=invocation_id,
|
|
111
|
+
prepare_runner=_prepare_runner_for_model,
|
|
112
|
+
session_service_provider=deps.resolve_session_service,
|
|
113
|
+
run_mode=RUN_MODE_FOREGROUND,
|
|
114
|
+
),
|
|
115
|
+
invocation_id=invocation_id,
|
|
116
|
+
resume_key=resume_key,
|
|
117
|
+
run_mode=RUN_MODE_FOREGROUND,
|
|
118
|
+
run_trigger=trigger_from_resume_input(resume_input),
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
response_id = f"resp_{uuid.uuid4().hex}"
|
|
122
|
+
resolved_session_id, result = await deps.conversation().invoke_conversation_once(
|
|
123
|
+
runner=active_runner,
|
|
124
|
+
agent_id=agent_id,
|
|
125
|
+
user_id=resolved_user_id,
|
|
126
|
+
messages=messages,
|
|
127
|
+
session_id=resolved_session_id,
|
|
128
|
+
model=request.model,
|
|
129
|
+
model_metadata=request.model_metadata,
|
|
130
|
+
model_options=request.model_options,
|
|
131
|
+
instructions=request.instructions,
|
|
132
|
+
request_metadata=request_metadata,
|
|
133
|
+
custom_metadata=custom_metadata,
|
|
134
|
+
resume_input=resume_input,
|
|
135
|
+
response_id=response_id,
|
|
136
|
+
account_id=account_id,
|
|
137
|
+
invocation_id=invocation_id,
|
|
138
|
+
prepare_runner=_prepare_runner_for_model,
|
|
139
|
+
session_service_provider=deps.resolve_session_service,
|
|
140
|
+
run_mode=RUN_MODE_FOREGROUND,
|
|
141
|
+
)
|
|
142
|
+
return deps.conversation().build_responses_payload(
|
|
143
|
+
output_text=result["output_text"],
|
|
144
|
+
model=request.model,
|
|
145
|
+
session_id=resolved_session_id,
|
|
146
|
+
response_id=response_id,
|
|
147
|
+
metadata=custom_metadata,
|
|
148
|
+
usage=result.get("usage") if isinstance(result.get("usage"), Mapping) else None,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@openai_compat_router.post("/v1/chat/completions")
|
|
153
|
+
async def chat_completions(request: ChatCompletionRequest):
|
|
154
|
+
"""OpenAI 兼容的聊天补全接口 (支持流式和非流式)"""
|
|
155
|
+
active_runner = _resolve_active_runner()
|
|
156
|
+
messages = deps.conversation().normalize_kop_messages(request.messages)
|
|
157
|
+
agent_id = _runtime_agent_id(active_runner)
|
|
158
|
+
resolved_user_id = _clean_optional_string(request.user) or "user"
|
|
159
|
+
account_id = _clean_optional_string(request.account_id)
|
|
160
|
+
custom_metadata, request_metadata = _split_custom_metadata(request.metadata)
|
|
161
|
+
invocation_id = _metadata_invocation_id(request_metadata)
|
|
162
|
+
|
|
163
|
+
if request.stream:
|
|
164
|
+
return StreamingResponse(
|
|
165
|
+
deps.conversation().stream_conversation_turn(
|
|
166
|
+
runner=active_runner,
|
|
167
|
+
agent_id=agent_id,
|
|
168
|
+
user_id=resolved_user_id,
|
|
169
|
+
messages=messages,
|
|
170
|
+
session_id=request.session_id,
|
|
171
|
+
model=request.model,
|
|
172
|
+
model_metadata=request.model_metadata,
|
|
173
|
+
model_options=request.model_options,
|
|
174
|
+
request_metadata=request_metadata,
|
|
175
|
+
custom_metadata=custom_metadata,
|
|
176
|
+
invocation_id=invocation_id,
|
|
177
|
+
account_id=account_id,
|
|
178
|
+
prepare_runner=_prepare_runner_for_model,
|
|
179
|
+
session_service_provider=deps.resolve_session_service,
|
|
180
|
+
run_mode=RUN_MODE_FOREGROUND,
|
|
181
|
+
),
|
|
182
|
+
media_type="text/event-stream",
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
resolved_session_id, result = await deps.conversation().invoke_conversation_once(
|
|
186
|
+
runner=active_runner,
|
|
187
|
+
agent_id=agent_id,
|
|
188
|
+
user_id=resolved_user_id,
|
|
189
|
+
messages=messages,
|
|
190
|
+
session_id=request.session_id,
|
|
191
|
+
model=request.model,
|
|
192
|
+
model_metadata=request.model_metadata,
|
|
193
|
+
model_options=request.model_options,
|
|
194
|
+
request_metadata=request_metadata,
|
|
195
|
+
custom_metadata=custom_metadata,
|
|
196
|
+
invocation_id=invocation_id,
|
|
197
|
+
account_id=account_id,
|
|
198
|
+
prepare_runner=_prepare_runner_for_model,
|
|
199
|
+
session_service_provider=deps.resolve_session_service,
|
|
200
|
+
run_mode=RUN_MODE_FOREGROUND,
|
|
201
|
+
)
|
|
202
|
+
return deps.conversation().build_chat_completions_payload(
|
|
203
|
+
output_text=result["output_text"],
|
|
204
|
+
model=request.model,
|
|
205
|
+
session_id=resolved_session_id,
|
|
206
|
+
metadata=result.get("metadata"),
|
|
207
|
+
)
|