agentengine-sdk-python 0.7.0__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/METADATA +52 -20
- agentengine_sdk_python-0.8.1.dist-info/RECORD +644 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/WHEEL +1 -1
- ksadk/a2a/__init__.py +180 -11
- ksadk/a2a/bootstrap.py +332 -0
- ksadk/a2a/card.py +15 -0
- ksadk/a2a/context_store.py +203 -0
- ksadk/a2a/control_plane.py +1056 -0
- ksadk/a2a/credential.py +99 -0
- ksadk/a2a/event_adapter.py +149 -0
- ksadk/a2a/executor.py +361 -137
- ksadk/a2a/external_transport.py +516 -0
- ksadk/a2a/identity.py +304 -0
- ksadk/a2a/ids.py +22 -0
- ksadk/a2a/langgraph.py +285 -0
- ksadk/a2a/resume_store.py +201 -0
- ksadk/a2a/routes.py +112 -0
- ksadk/a2a/server.py +102 -62
- ksadk/a2a/service_env.py +33 -0
- ksadk/a2a/space_client.py +1122 -0
- ksadk/a2a/task_adapter.py +423 -0
- ksadk/a2a/task_event_dispatcher.py +167 -0
- ksadk/a2a/task_event_outbox.py +326 -0
- ksadk/a2a/task_store.py +206 -0
- ksadk/a2a_card.py +101 -0
- ksadk/a2ui/__init__.py +27 -0
- ksadk/a2ui/core.py +186 -0
- ksadk/a2ui/models.py +166 -0
- ksadk/a2ui/renderer.py +198 -0
- ksadk/agui/__init__.py +9 -0
- ksadk/agui/a2ui_projection.py +92 -0
- ksadk/agui/agent.py +872 -0
- ksadk/agui/config.py +92 -0
- ksadk/agui/routes.py +47 -0
- ksadk/api/client.py +238 -204
- ksadk/api/environment.py +27 -0
- ksadk/builders/__init__.py +2 -0
- ksadk/builders/base.py +16 -14
- ksadk/builders/code_builder.py +375 -270
- ksadk/builders/container_builder.py +240 -200
- ksadk/builders/framework_requirements.py +31 -12
- ksadk/builders/ks3_uploader.py +60 -29
- ksadk/builders/managed_runtime_builder.py +173 -0
- ksadk/builders/mcp_builder.py +91 -92
- ksadk/builders/requirements_utils.py +1 -5
- ksadk/cli/__init__.py +97 -171
- ksadk/cli/cmd_a2a.py +255 -84
- ksadk/cli/cmd_agent.py +19 -5
- ksadk/cli/cmd_build.py +158 -29
- ksadk/cli/cmd_completion.py +47 -35
- ksadk/cli/cmd_config.py +267 -198
- ksadk/cli/cmd_create.py +507 -740
- ksadk/cli/cmd_dashboard.py +120 -45
- ksadk/cli/cmd_deploy.py +135 -59
- ksadk/cli/cmd_destroy.py +44 -14
- ksadk/cli/cmd_eval.py +386 -0
- ksadk/cli/cmd_files.py +63 -24
- ksadk/cli/cmd_hermes.py +313 -135
- ksadk/cli/cmd_invoke.py +184 -122
- ksadk/cli/cmd_launch.py +76 -28
- ksadk/cli/cmd_mcp.py +98 -64
- ksadk/cli/cmd_model.py +14 -5
- ksadk/cli/cmd_openclaw.py +564 -268
- ksadk/cli/cmd_replay.py +71 -0
- ksadk/cli/cmd_run.py +58 -73
- ksadk/cli/cmd_status.py +80 -31
- ksadk/cli/cmd_studio.py +110 -0
- ksadk/cli/cmd_version.py +20 -13
- ksadk/cli/cmd_web.py +95 -18
- ksadk/cli/deploy_utils.py +20 -20
- ksadk/cli/dry_run.py +7 -4
- ksadk/cli/env_options.py +83 -0
- ksadk/cli/error_utils.py +37 -12
- ksadk/cli/global_options.py +4 -3
- ksadk/cli/local_runtime.py +1 -2
- ksadk/cli/model_catalog.py +6 -2
- ksadk/cli/network_options.py +41 -19
- ksadk/cli/resource_common.py +6 -2
- ksadk/cli/runtime_bootstrap.py +51 -0
- ksadk/cli/storage.py +0 -1
- ksadk/cli/ui.py +11 -3
- ksadk/cli/workflow_common.py +52 -18
- ksadk/codex/__init__.py +12 -0
- ksadk/codex/client.py +1042 -0
- ksadk/codex/phase.py +143 -0
- ksadk/codex/runtime.py +940 -0
- ksadk/common/aicp_env.py +0 -1
- ksadk/common/auth.py +2 -2
- ksadk/common/constants.py +1 -3
- ksadk/common/kop_client.py +232 -0
- ksadk/common/llm_utils.py +17 -13
- ksadk/compat/__init__.py +5 -0
- ksadk/compat/adk_compat.py +200 -0
- ksadk/compat/copilotkit_a2ui.py +330 -0
- ksadk/configs/__init__.py +12 -14
- ksadk/configs/env_registry.py +661 -116
- ksadk/configs/global_config.py +3 -2
- ksadk/configs/settings.py +133 -209
- ksadk/conversations/__init__.py +85 -92
- ksadk/conversations/attachment_storage.py +16 -11
- ksadk/conversations/attachments.py +44 -36
- ksadk/conversations/compaction_pipeline.py +12 -12
- ksadk/conversations/compaction_prompt.py +9 -5
- ksadk/conversations/context.py +221 -6
- ksadk/conversations/message_projection.py +438 -51
- ksadk/conversations/model_context.py +12 -6
- ksadk/conversations/model_options.py +0 -1
- ksadk/conversations/normalize.py +20 -16
- ksadk/conversations/reasoning_markup.py +1 -1
- ksadk/conversations/runtime.py +339 -5255
- ksadk/conversations/runtime_compaction.py +333 -0
- ksadk/conversations/runtime_constants.py +27 -0
- ksadk/conversations/runtime_governance.py +185 -0
- ksadk/conversations/runtime_input.py +660 -0
- ksadk/conversations/runtime_invocation.py +395 -0
- ksadk/conversations/runtime_metadata.py +475 -0
- ksadk/conversations/runtime_observability.py +367 -0
- ksadk/conversations/runtime_payloads.py +272 -0
- ksadk/conversations/runtime_persistence.py +440 -0
- ksadk/conversations/runtime_preparation.py +426 -0
- ksadk/conversations/runtime_resume.py +836 -0
- ksadk/conversations/runtime_stream_events.py +902 -0
- ksadk/conversations/runtime_streaming.py +700 -0
- ksadk/conversations/semantic_summary.py +17 -5
- ksadk/conversations/session_title.py +6 -3
- ksadk/deployment/__init__.py +15 -16
- ksadk/deployment/agent_access.py +12 -23
- ksadk/deployment/base.py +51 -38
- ksadk/deployment/managed_runtime.py +33 -0
- ksadk/deployment/manager.py +85 -71
- ksadk/deployment/providers/serverless.py +379 -210
- ksadk/deployment/registry.py +38 -32
- ksadk/deployment/state.py +11 -11
- ksadk/deployment/ui_config.py +1 -1
- ksadk/detection/__init__.py +1 -1
- ksadk/detection/detector.py +146 -83
- ksadk/detection/mcp_detector.py +9 -6
- ksadk/evaluation/__init__.py +84 -0
- ksadk/evaluation/a2a_adapter.py +444 -0
- ksadk/evaluation/adapters.py +54 -0
- ksadk/evaluation/contracts.py +409 -0
- ksadk/evaluation/evalset.py +351 -0
- ksadk/evaluation/evaluators.py +461 -0
- ksadk/evaluation/executor.py +118 -0
- ksadk/evaluation/storage.py +68 -0
- ksadk/evaluation/target.py +73 -0
- ksadk/events/__init__.py +25 -0
- ksadk/events/parser.py +191 -0
- ksadk/events/replay.py +37 -0
- ksadk/events/runtime_event.py +273 -0
- ksadk/events/store.py +317 -0
- ksadk/harness/__init__.py +35 -0
- ksadk/harness/app.py +269 -0
- ksadk/harness/config.py +181 -0
- ksadk/harness/reasoner.py +105 -0
- ksadk/harness/runtime.py +364 -0
- ksadk/harness/sandbox.py +141 -0
- ksadk/harness/tools.py +222 -0
- ksadk/hermes_terminal.py +28 -12
- ksadk/identity/resolver.py +15 -9
- ksadk/ids.py +32 -0
- ksadk/knowledge_base/adk_tool.py +1 -1
- ksadk/knowledge_base/client.py +38 -33
- ksadk/managed_a2a_card.py +160 -0
- ksadk/managed_runtime.py +195 -0
- ksadk/markdown.py +5 -2
- ksadk/mcp_runtime/__init__.py +9 -6
- ksadk/memory/__init__.py +1 -1
- ksadk/memory/adk/__init__.py +2 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +2 -6
- ksadk/memory/adk/backends/http_ltm_backend.py +13 -21
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +7 -13
- ksadk/memory/adk/backends/sdk_ltm_backend.py +36 -36
- ksadk/memory/adk/long_term_memory.py +34 -37
- ksadk/memory/adk/resilient_session_service.py +4 -5
- ksadk/memory/adk/short_term_memory.py +12 -21
- ksadk/memory/adk_tool.py +3 -2
- ksadk/memory/backends/base.py +19 -19
- ksadk/memory/backends/memory.py +24 -25
- ksadk/memory/backends/redis.py +31 -30
- ksadk/memory/langchain_tool.py +2 -1
- ksadk/memory/manager.py +52 -47
- ksadk/memory/service.py +16 -6
- ksadk/memory/tool.py +4 -0
- ksadk/model_policy.py +15 -7
- ksadk/model_proxy/__init__.py +51 -0
- ksadk/model_proxy/bootstrap.py +80 -0
- ksadk/model_proxy/cache.py +165 -0
- ksadk/model_proxy/config.py +66 -0
- ksadk/model_proxy/demo_webui.py +115 -0
- ksadk/model_proxy/detect.py +145 -0
- ksadk/model_proxy/gate.py +68 -0
- ksadk/model_proxy/namespace.py +201 -0
- ksadk/model_proxy/protocol_proxy.py +22 -0
- ksadk/model_proxy/server.py +443 -0
- ksadk/model_proxy/transform.py +735 -0
- ksadk/openclaw_gateway.py +29 -14
- ksadk/runners/adk_runner.py +354 -146
- ksadk/runners/base_runner.py +71 -29
- ksadk/runners/deepagents_runner.py +0 -1
- ksadk/runners/factory.py +18 -5
- ksadk/runners/langchain_runner.py +29 -742
- ksadk/runners/langgraph_runner.py +417 -97
- ksadk/runners/patch_langchain.py +16 -16
- ksadk/runners/remote_runner.py +134 -33
- ksadk/runners/usage_accumulator.py +1 -0
- ksadk/runners/utils/__init__.py +0 -10
- ksadk/runners/utils/loader.py +23 -7
- ksadk/runtime/__init__.py +67 -0
- ksadk/runtime/adapter.py +412 -0
- ksadk/runtime/conversation_execution.py +553 -0
- ksadk/runtime/executor.py +251 -0
- ksadk/runtime/factory.py +156 -0
- ksadk/runtime/framework_adapters.py +118 -0
- ksadk/runtime/launch.py +48 -0
- ksadk/runtime/preprocessing.py +131 -0
- ksadk/runtime/runner_adapter.py +1032 -0
- ksadk/runtime/runner_loading.py +36 -0
- ksadk/runtime_context.py +18 -3
- ksadk/runtime_state.py +0 -1
- ksadk/sandbox/__init__.py +4 -1
- ksadk/sandbox/backends/__init__.py +4 -1
- ksadk/sandbox/backends/e2b.py +13 -5
- ksadk/sandbox/backends/local_process.py +11 -3
- ksadk/sandbox/base.py +10 -15
- ksadk/sandbox/factory.py +14 -4
- ksadk/sandbox/registry.py +57 -6
- ksadk/server/__init__.py +39 -4
- ksadk/server/api_models.py +15 -5
- ksadk/server/app.py +24 -3928
- ksadk/server/composition.py +47 -0
- ksadk/server/factory.py +622 -0
- ksadk/server/routes/__init__.py +1 -0
- ksadk/server/routes/checkpoint_resolution.py +116 -0
- ksadk/server/routes/common.py +682 -0
- ksadk/server/routes/control.py +331 -0
- ksadk/server/routes/dependencies.py +98 -0
- ksadk/server/routes/misc.py +425 -0
- ksadk/server/routes/models.py +451 -0
- ksadk/server/routes/openai_compat.py +229 -0
- ksadk/server/routes/projection.py +848 -0
- ksadk/server/routes/routers.py +52 -0
- ksadk/server/routes/run.py +519 -0
- ksadk/server/routes/sessions.py +644 -0
- ksadk/server/routes/streaming.py +265 -0
- ksadk/server/routes/workspace.py +414 -0
- ksadk/server/static/assets/{ArtifactsPanel-D-SSn2ee.js → ArtifactsPanel-CakCqxEN.js} +1 -1
- ksadk/server/static/assets/CodeBlock-CynLknyO.js +9 -0
- ksadk/server/static/assets/MathMessageMarkdown-3sQdOysS.js +8 -0
- ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +303 -0
- ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +1 -0
- ksadk/server/static/assets/{arc-BA13sHc9.js → arc-DrgjcKhl.js} +1 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-3BPJPVTR-DzJzgVoL.js → architectureDiagram-3BPJPVTR-BXoVRbQ6.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-GPEHLZMM-UTdVcZhn.js → blockDiagram-GPEHLZMM-BnaB3Ywv.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-AAUBKEIU-Dix0GD4m.js → c4Diagram-AAUBKEIU-Dw4weZcp.js} +1 -1
- ksadk/server/static/assets/channel-Dt3rQTFI.js +1 -0
- ksadk/server/static/assets/{chunk-2J33WTMH-C2JxuZ42.js → chunk-2J33WTMH-ChjpLK7j.js} +1 -1
- ksadk/server/static/assets/{chunk-4BX2VUAB-Be57QPgD.js → chunk-4BX2VUAB-B9drTgOW.js} +1 -1
- ksadk/server/static/assets/{chunk-55IACEB6-WjSuy4nv.js → chunk-55IACEB6-CK4ROATy.js} +1 -1
- ksadk/server/static/assets/{chunk-727SXJPM-BOovP-b5.js → chunk-727SXJPM-B9KtTTgw.js} +1 -1
- ksadk/server/static/assets/{chunk-AQP2D5EJ-DOmZNmWj.js → chunk-AQP2D5EJ-1O1mki3m.js} +1 -1
- ksadk/server/static/assets/{chunk-FMBD7UC4-DzwlodkU.js → chunk-FMBD7UC4-B_fH2YuH.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-DMqAikEU.js → chunk-ND2GUHAM-D6rFLaVV.js} +1 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +1 -0
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-Zhy2GBnP.js → cose-bilkent-S5V4N54A-ChNs_Mdk.js} +1 -1
- ksadk/server/static/assets/{dagre-BM42HDAG-CbKrtIUz.js → dagre-BM42HDAG-D0QXg_MQ.js} +1 -1
- ksadk/server/static/assets/{diagram-2AECGRRQ-BRApgQRK.js → diagram-2AECGRRQ-DBDDKwBQ.js} +1 -1
- ksadk/server/static/assets/{diagram-5GNKFQAL-D0xbnDiK.js → diagram-5GNKFQAL-BkwDOxmO.js} +1 -1
- ksadk/server/static/assets/{diagram-KO2AKTUF-CVugVI9L.js → diagram-KO2AKTUF-Bv8waYvY.js} +1 -1
- ksadk/server/static/assets/{diagram-LMA3HP47-DozUGgee.js → diagram-LMA3HP47-e1VECDdu.js} +1 -1
- ksadk/server/static/assets/{diagram-OG6HWLK6-ZOYsKlru.js → diagram-OG6HWLK6-Ds9adfRl.js} +1 -1
- ksadk/server/static/assets/{dist-DpKtt4Bo.js → dist-4N2NMVYg.js} +1 -1
- ksadk/server/static/assets/{dist-CkEKJFtk.js → dist-B-jNR6Vn.js} +1 -1
- ksadk/server/static/assets/{dist-D57wnGWd.js → dist-B5J2uhNk.js} +1 -1
- ksadk/server/static/assets/{dist-8_SfK1IP.js → dist-B5oS1zcj.js} +1 -1
- ksadk/server/static/assets/{dist-DMezvBGJ.js → dist-BB3-OwTQ.js} +1 -1
- ksadk/server/static/assets/{dist-2hInLS_J.js → dist-BIlKoW0k.js} +1 -1
- ksadk/server/static/assets/{dist-BrCcQ47T.js → dist-BjOdlDjj.js} +1 -1
- ksadk/server/static/assets/{dist-BmlMPsCc.js → dist-C1sz5Eo3.js} +1 -1
- ksadk/server/static/assets/{dist-B0NP_Z0z.js → dist-CWV4lDr1.js} +1 -1
- ksadk/server/static/assets/{dist-D-xOD048.js → dist-CmZHzlwZ.js} +1 -1
- ksadk/server/static/assets/{dist-DL_NKc_z.js → dist-D6MpCZtz.js} +1 -1
- ksadk/server/static/assets/{dist-DyOkZmze.js → dist-DJN_6Y39.js} +1 -1
- ksadk/server/static/assets/{dist-DmFaq_Iy.js → dist-DQU9EWw-.js} +1 -1
- ksadk/server/static/assets/{dist-gX6GOLKq.js → dist-DWKByxWV.js} +1 -1
- ksadk/server/static/assets/{dist-DyWsb78Q.js → dist-Dli7qW-B.js} +1 -1
- ksadk/server/static/assets/{dist-BIJVDMuB.js → dist-DsHPdk3W.js} +1 -1
- ksadk/server/static/assets/{dist-Dp0k7bWI.js → dist-X4TnqwOK.js} +1 -1
- ksadk/server/static/assets/{dist-8EEyGgDx.js → dist-_pHPTyZ-.js} +1 -1
- ksadk/server/static/assets/{dist-CPBtqRTW.js → dist-fhOuWds5.js} +1 -1
- ksadk/server/static/assets/{dist-D-JMdWPQ.js → dist-gLnrGsoU.js} +1 -1
- ksadk/server/static/assets/{dist-BssVmjIo.js → dist-j6Dxmf_j.js} +1 -1
- ksadk/server/static/assets/{dist-C3HIIaN5.js → dist-o2OVmKvt.js} +1 -1
- ksadk/server/static/assets/{erDiagram-TEJ5UH35-Bk-9bgE5.js → erDiagram-TEJ5UH35-BPItFKH6.js} +1 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +1 -0
- ksadk/server/static/assets/{flowDiagram-I6XJVG4X-Dn9kZVuZ.js → flowDiagram-I6XJVG4X-BbYB9w5Y.js} +1 -1
- ksadk/server/static/assets/{ganttDiagram-6RSMTGT7-BGxXlJqm.js → ganttDiagram-6RSMTGT7-TQXa0KXv.js} +1 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-PVQCEYII-C7Q0X-wi.js → gitGraphDiagram-PVQCEYII-bKblCnpa.js} +1 -1
- ksadk/server/static/assets/index-R52pJJvg.js +177 -0
- ksadk/server/static/assets/index-jJr3_955.css +2 -0
- ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +1 -0
- ksadk/server/static/assets/{infoDiagram-5YYISTIA-BO_CSqq5.js → infoDiagram-5YYISTIA-BGVT7J_i.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-eYLPLd46.js → ishikawaDiagram-YF4QCWOH-K0OOfVna.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-De9geSb0.js → journeyDiagram-JHISSGLW-8LeOJaZp.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-Cs80kQto.js → kanban-definition-UN3LZRKU-C6uCgZrW.js} +1 -1
- ksadk/server/static/assets/{katex-DSrCFD8n.js → katex-CYWseY5E.js} +1 -1
- ksadk/server/static/assets/{linear-CN9sbKTF.js → linear-hdBcYzM8.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DlgSBU8l.js → mermaid-parser.core-BWrDjSZM.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-9afz7Oug.js → mindmap-definition-RKZ34NQL-Bjy_2v4_.js} +1 -1
- ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +1 -0
- ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +1 -0
- ksadk/server/static/assets/{pieDiagram-4H26LBE5-DPv_VstN.js → pieDiagram-4H26LBE5-GmmqNiVH.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-o77wZ1XK.js → quadrantDiagram-W4KKPZXB-BmkRbwCg.js} +1 -1
- ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +1 -0
- ksadk/server/static/assets/{requirementDiagram-4Y6WPE33-BYVw81VC.js → requirementDiagram-4Y6WPE33-DSWFqL7c.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-B7nZFMKT.js → sankeyDiagram-5OEKKPKP-l6iXmU65.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-BGRRrFw5.js → sequenceDiagram-3UESZ5HK-Cq6UBeQB.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-AJRCARHV-BUfHCoPs.js → stateDiagram-AJRCARHV-qzTQpg3Y.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +1 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-FbCTGrf9.js → timeline-definition-PNZ67QCA-DEz24vV0.js} +1 -1
- ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +1 -0
- ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +1 -0
- ksadk/server/static/assets/{vennDiagram-CIIHVFJN-DWgwtPsJ.js → vennDiagram-CIIHVFJN-CMCixki2.js} +1 -1
- ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-YWT4CUSO-2x8G-tTM.js → wardleyDiagram-YWT4CUSO-CVzB8F9K.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-2RQKCTM6-Drma3AYl.js → xychartDiagram-2RQKCTM6-BFBqBLc1.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +111 -58
- ksadk/sessions/__init__.py +69 -19
- ksadk/sessions/base.py +31 -11
- ksadk/sessions/continuity.py +2 -3
- ksadk/sessions/in_memory.py +46 -2
- ksadk/sessions/local_service.py +148 -17
- ksadk/sessions/postgres_service.py +143 -25
- ksadk/sessions/resilient.py +36 -8
- ksadk/skills/models.py +17 -5
- ksadk/skills/package_store.py +5 -2
- ksadk/skills/runtime/agent.py +20 -5
- ksadk/skills/runtime/artifacts.py +1 -5
- ksadk/skills/runtime/backends/e2b.py +10 -4
- ksadk/skills/runtime/backends/local.py +15 -3
- ksadk/skills/runtime/base.py +1 -2
- ksadk/skills/runtime/executor.py +10 -3
- ksadk/skills/runtime/factory.py +4 -2
- ksadk/skills/runtime/loader.py +1 -2
- ksadk/skills/runtime/registry.py +15 -10
- ksadk/skills/runtime/request.py +3 -1
- ksadk/skills/service_client.py +47 -16
- ksadk/skills/tool_defs.py +15 -10
- ksadk/studio/__init__.py +5 -0
- ksadk/studio/agent_avatar_assets.py +120 -0
- ksadk/studio/agent_lifecycle.py +51 -0
- ksadk/studio/api.py +1046 -0
- ksadk/studio/api_catalog_routes.py +324 -0
- ksadk/studio/api_contracts.py +177 -0
- ksadk/studio/api_helpers.py +132 -0
- ksadk/studio/authoring.py +524 -0
- ksadk/studio/authoring_coordinator.py +285 -0
- ksadk/studio/builder.py +320 -0
- ksadk/studio/capabilities.py +351 -0
- ksadk/studio/cloud.py +278 -0
- ksadk/studio/codex_agent_service.py +583 -0
- ksadk/studio/codex_builder.py +324 -0
- ksadk/studio/codex_manifest.py +278 -0
- ksadk/studio/codex_run.py +352 -0
- ksadk/studio/compiler.py +189 -0
- ksadk/studio/contracts.py +644 -0
- ksadk/studio/errors.py +47 -0
- ksadk/studio/evaluation.py +192 -0
- ksadk/studio/event_store.py +284 -0
- ksadk/studio/framework_run.py +114 -0
- ksadk/studio/identifiers.py +33 -0
- ksadk/studio/mcp_runtime.py +229 -0
- ksadk/studio/model_client.py +543 -0
- ksadk/studio/model_profile_service.py +214 -0
- ksadk/studio/operations.py +243 -0
- ksadk/studio/otel_trace.py +754 -0
- ksadk/studio/pagination.py +182 -0
- ksadk/studio/python_tool_inspection.py +183 -0
- ksadk/studio/repository.py +306 -0
- ksadk/studio/resource_catalog.py +1217 -0
- ksadk/studio/run_service.py +707 -0
- ksadk/studio/runtime_catalog.py +74 -0
- ksadk/studio/runtime_source.py +339 -0
- ksadk/studio/service.py +1141 -0
- ksadk/studio/shared_web.py +994 -0
- ksadk/studio/skill_discovery.py +628 -0
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
- ksadk/studio/static/assets/index-CaEN0eTR.css +1 -0
- ksadk/studio/static/assets/index-DI2eY_NH.js +252 -0
- ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
- ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- ksadk/studio/static/index.html +15 -0
- ksadk/studio/templates.py +630 -0
- ksadk/studio/validator.py +246 -0
- ksadk/studio/workspace.py +137 -0
- ksadk/terminal_exec_policy.py +3 -4
- ksadk/tools/gateway.py +101 -15
- ksadk/tools/result_budget.py +12 -4
- ksadk/toolsets/__init__.py +161 -37
- ksadk/toolsets/a2a.py +426 -0
- ksadk/toolsets/platform.py +21 -5
- ksadk/toolsets/sandbox.py +82 -16
- ksadk/toolsets/skills.py +200 -39
- ksadk/toolsets/web.py +123 -26
- ksadk/toolsets/workspace.py +212 -101
- ksadk/tracing/__init__.py +19 -21
- ksadk/tracing/exporters/inmemory_exporter.py +62 -51
- ksadk/tracing/setup.py +135 -506
- ksadk/tracing/span_utils.py +0 -41
- ksadk/tui/loop.py +78 -30
- ksadk/tui/stream_render.py +1 -0
- ksadk/ui_config.py +5 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/registry.py +56 -56
- ksadk_runtime_common/schemas/runtime_event_v1.json +95 -0
- ksadk_runtime_common/workspace_files/router.py +8 -2
- agentengine_sdk_python-0.7.0.dist-info/RECORD +0 -482
- ksadk/a2a/card_builder.py +0 -64
- ksadk/a2a/client.py +0 -309
- ksadk/runners/utils/langfuse.py +0 -230
- ksadk/server/static/assets/CodeBlock-P16VOLYi.js +0 -9
- ksadk/server/static/assets/MathMessageMarkdown-CdGiQWHR.js +0 -8
- ksadk/server/static/assets/MermaidBlock-IOcal8cm.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-DGSDWsei.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-BvUlsA6l.js +0 -1
- ksadk/server/static/assets/channel-CTuydARX.js +0 -1
- ksadk/server/static/assets/chunk-QZHKN3VN-BnCydivS.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-BNHg45Be.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-BNHg45Be.js +0 -1
- ksadk/server/static/assets/eventmodeling-FCH6USID-DsAgWnlf.js +0 -1
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BIao9Yjg.js +0 -1
- ksadk/server/static/assets/index-C00Lwg3L.js +0 -165
- ksadk/server/static/assets/index-DAURbCsP.css +0 -1
- ksadk/server/static/assets/info-J43DQDTF-CyipqGxU.js +0 -1
- ksadk/server/static/assets/packet-YPE3B663-CGkyRxlg.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-M0uWAf4n.js +0 -1
- ksadk/server/static/assets/radar-GUYGQ44K-Bdbm24-x.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-8xBN_gLM.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-npMo0ak1.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-CHdzrrdo.js +0 -1
- ksadk/server/static/assets/wardley-L42UT6IY-BEQz7wyy.js +0 -1
- ksadk/tracing/exporters/langfuse_exporter.py +0 -445
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.7.0.dist-info → agentengine_sdk_python-0.8.1.dist-info}/top_level.txt +0 -0
ksadk/sessions/continuity.py
CHANGED
|
@@ -22,7 +22,7 @@ class SessionContinuityStatus:
|
|
|
22
22
|
details: dict[str, Any] = field(default_factory=dict)
|
|
23
23
|
|
|
24
24
|
def to_payload(self) -> dict[str, Any]:
|
|
25
|
-
payload = {
|
|
25
|
+
payload: dict[str, Any] = {
|
|
26
26
|
"Level": self.level.value,
|
|
27
27
|
"Path": self.path,
|
|
28
28
|
"Runner": self.runner,
|
|
@@ -320,8 +320,7 @@ class ADKSessionAdapter(RunnerSessionAdapter):
|
|
|
320
320
|
stm_backend = getattr(_stm, "backend", None) if _stm is not None else None
|
|
321
321
|
is_durable = stm_backend is not None and stm_backend != "local"
|
|
322
322
|
level = (
|
|
323
|
-
SessionContinuityLevel.RUNTIME if is_durable
|
|
324
|
-
else SessionContinuityLevel.SEMANTIC
|
|
323
|
+
SessionContinuityLevel.RUNTIME if is_durable else SessionContinuityLevel.SEMANTIC
|
|
325
324
|
)
|
|
326
325
|
path = "adk_resume"
|
|
327
326
|
elif has_native_session:
|
ksadk/sessions/in_memory.py
CHANGED
|
@@ -5,6 +5,7 @@ import copy
|
|
|
5
5
|
import time
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
|
+
from ksadk.ids import new_session_id
|
|
8
9
|
from ksadk.sessions.base import BaseSessionService, Session, SessionEvent, SessionState, generate_id
|
|
9
10
|
|
|
10
11
|
|
|
@@ -25,7 +26,7 @@ class InMemorySessionService(BaseSessionService):
|
|
|
25
26
|
return copy.deepcopy(self._sessions[session_id])
|
|
26
27
|
|
|
27
28
|
session = Session(
|
|
28
|
-
id=session_id or
|
|
29
|
+
id=session_id or new_session_id(),
|
|
29
30
|
agent_id=agent_id,
|
|
30
31
|
user_id=user_id,
|
|
31
32
|
)
|
|
@@ -43,6 +44,15 @@ class InMemorySessionService(BaseSessionService):
|
|
|
43
44
|
session = self._sessions.get(session_id)
|
|
44
45
|
return copy.deepcopy(session) if session else None
|
|
45
46
|
|
|
47
|
+
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
48
|
+
async with self._lock:
|
|
49
|
+
session = self._sessions.get(session_id)
|
|
50
|
+
if session is None:
|
|
51
|
+
return None
|
|
52
|
+
metadata = copy.deepcopy(session)
|
|
53
|
+
metadata.events = []
|
|
54
|
+
return metadata
|
|
55
|
+
|
|
46
56
|
async def list_sessions(
|
|
47
57
|
self,
|
|
48
58
|
agent_id: str,
|
|
@@ -56,7 +66,10 @@ class InMemorySessionService(BaseSessionService):
|
|
|
56
66
|
for session in self._sessions.values()
|
|
57
67
|
if session.agent_id == agent_id and (user_id is None or session.user_id == user_id)
|
|
58
68
|
]
|
|
59
|
-
sessions.sort(
|
|
69
|
+
sessions.sort(
|
|
70
|
+
key=lambda item: (item.updated_at, item.created_at, item.id),
|
|
71
|
+
reverse=True,
|
|
72
|
+
)
|
|
60
73
|
start = offset or 0
|
|
61
74
|
end = None if limit is None else start + limit
|
|
62
75
|
return sessions[start:end]
|
|
@@ -191,6 +204,37 @@ class InMemorySessionService(BaseSessionService):
|
|
|
191
204
|
events = [event for event in events if event.seq_id < before_seq_id]
|
|
192
205
|
return len(events)
|
|
193
206
|
|
|
207
|
+
async def get_events_for_agent(
|
|
208
|
+
self,
|
|
209
|
+
agent_id: str,
|
|
210
|
+
user_id: Optional[str] = None,
|
|
211
|
+
offset: Optional[int] = None,
|
|
212
|
+
limit: Optional[int] = None,
|
|
213
|
+
) -> list[SessionEvent]:
|
|
214
|
+
async with self._lock:
|
|
215
|
+
merged = [
|
|
216
|
+
copy.deepcopy(event)
|
|
217
|
+
for session in self._sessions.values()
|
|
218
|
+
if session.agent_id == agent_id and (user_id is None or session.user_id == user_id)
|
|
219
|
+
for event in session.events
|
|
220
|
+
]
|
|
221
|
+
merged.sort(key=lambda event: (event.timestamp, event.seq_id, event.id))
|
|
222
|
+
end = max(len(merged) - (offset or 0), 0)
|
|
223
|
+
start = 0 if limit is None else max(end - limit, 0)
|
|
224
|
+
return merged[start:end]
|
|
225
|
+
|
|
226
|
+
async def count_events_for_agent(
|
|
227
|
+
self,
|
|
228
|
+
agent_id: str,
|
|
229
|
+
user_id: Optional[str] = None,
|
|
230
|
+
) -> int:
|
|
231
|
+
async with self._lock:
|
|
232
|
+
return sum(
|
|
233
|
+
len(session.events)
|
|
234
|
+
for session in self._sessions.values()
|
|
235
|
+
if session.agent_id == agent_id and (user_id is None or session.user_id == user_id)
|
|
236
|
+
)
|
|
237
|
+
|
|
194
238
|
async def get_state(
|
|
195
239
|
self,
|
|
196
240
|
agent_id: str,
|
ksadk/sessions/local_service.py
CHANGED
|
@@ -7,11 +7,12 @@ import json
|
|
|
7
7
|
import os
|
|
8
8
|
import sqlite3
|
|
9
9
|
import time
|
|
10
|
+
from collections.abc import Iterator
|
|
10
11
|
from contextlib import closing, contextmanager
|
|
11
12
|
from pathlib import Path
|
|
12
|
-
from collections.abc import Iterator
|
|
13
13
|
from typing import Optional
|
|
14
14
|
|
|
15
|
+
from ksadk.ids import new_session_id
|
|
15
16
|
from ksadk.sessions.base import (
|
|
16
17
|
BaseSessionService,
|
|
17
18
|
Session,
|
|
@@ -76,6 +77,14 @@ class LocalSessionService(BaseSessionService):
|
|
|
76
77
|
async with self._lock:
|
|
77
78
|
return await asyncio.to_thread(self._get_session_sync, session_id)
|
|
78
79
|
|
|
80
|
+
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
81
|
+
async with self._lock:
|
|
82
|
+
return await asyncio.to_thread(
|
|
83
|
+
self._get_session_sync,
|
|
84
|
+
session_id,
|
|
85
|
+
include_events=False,
|
|
86
|
+
)
|
|
87
|
+
|
|
79
88
|
async def list_sessions(
|
|
80
89
|
self,
|
|
81
90
|
agent_id: str,
|
|
@@ -161,6 +170,114 @@ class LocalSessionService(BaseSessionService):
|
|
|
161
170
|
before_seq_id,
|
|
162
171
|
)
|
|
163
172
|
|
|
173
|
+
async def get_events_for_agent(
|
|
174
|
+
self,
|
|
175
|
+
agent_id: str,
|
|
176
|
+
user_id: Optional[str] = None,
|
|
177
|
+
offset: Optional[int] = None,
|
|
178
|
+
limit: Optional[int] = None,
|
|
179
|
+
) -> list[SessionEvent]:
|
|
180
|
+
async with self._lock:
|
|
181
|
+
return await asyncio.to_thread(
|
|
182
|
+
self._get_events_for_agent_sync,
|
|
183
|
+
agent_id,
|
|
184
|
+
user_id,
|
|
185
|
+
offset,
|
|
186
|
+
limit,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
async def count_events_for_agent(
|
|
190
|
+
self,
|
|
191
|
+
agent_id: str,
|
|
192
|
+
user_id: Optional[str] = None,
|
|
193
|
+
) -> int:
|
|
194
|
+
async with self._lock:
|
|
195
|
+
return await asyncio.to_thread(
|
|
196
|
+
self._count_events_for_agent_sync,
|
|
197
|
+
agent_id,
|
|
198
|
+
user_id,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
def _get_events_for_agent_sync(
|
|
202
|
+
self,
|
|
203
|
+
agent_id: str,
|
|
204
|
+
user_id: Optional[str],
|
|
205
|
+
offset: Optional[int],
|
|
206
|
+
limit: Optional[int],
|
|
207
|
+
) -> list[SessionEvent]:
|
|
208
|
+
columns = (
|
|
209
|
+
"e.id, e.session_id, e.author, e.event_type, e.content_json, e.timestamp, "
|
|
210
|
+
"e.state_delta_json, e.seq_id, e.invocation_id, e.metadata_json"
|
|
211
|
+
)
|
|
212
|
+
user_clause = "AND s.user_id = ?" if user_id is not None else ""
|
|
213
|
+
from_clause = (
|
|
214
|
+
f"FROM {KSADK_EVENTS_TABLE} e "
|
|
215
|
+
f"JOIN {KSADK_SESSIONS_TABLE} s ON s.id = e.session_id "
|
|
216
|
+
f"WHERE s.agent_id = ? {user_clause}"
|
|
217
|
+
)
|
|
218
|
+
base_params: list[object] = [agent_id]
|
|
219
|
+
if user_id is not None:
|
|
220
|
+
base_params.append(user_id)
|
|
221
|
+
with self._connection() as connection:
|
|
222
|
+
if limit is not None or offset is not None:
|
|
223
|
+
# 与 get_events 一致的"最新 N 条"尾部语义:先 DESC 取窗口再 ASC 重排
|
|
224
|
+
query = f"""
|
|
225
|
+
SELECT id, session_id, author, event_type, content_json, timestamp,
|
|
226
|
+
state_delta_json, seq_id, invocation_id, metadata_json
|
|
227
|
+
FROM (
|
|
228
|
+
SELECT {columns}
|
|
229
|
+
{from_clause}
|
|
230
|
+
ORDER BY e.timestamp DESC, e.seq_id DESC, e.id DESC
|
|
231
|
+
LIMIT ? OFFSET ?
|
|
232
|
+
)
|
|
233
|
+
ORDER BY timestamp ASC, seq_id ASC, id ASC
|
|
234
|
+
"""
|
|
235
|
+
params = [*base_params, limit if limit is not None else -1, offset or 0]
|
|
236
|
+
else:
|
|
237
|
+
query = f"""
|
|
238
|
+
SELECT {columns}
|
|
239
|
+
{from_clause}
|
|
240
|
+
ORDER BY e.timestamp ASC, e.seq_id ASC, e.id ASC
|
|
241
|
+
"""
|
|
242
|
+
params = base_params
|
|
243
|
+
rows = connection.execute(query, params).fetchall()
|
|
244
|
+
return [
|
|
245
|
+
SessionEvent(
|
|
246
|
+
id=row["id"],
|
|
247
|
+
session_id=row["session_id"],
|
|
248
|
+
author=row["author"],
|
|
249
|
+
event_type=row["event_type"],
|
|
250
|
+
content=json.loads(row["content_json"] or "{}"),
|
|
251
|
+
timestamp=row["timestamp"],
|
|
252
|
+
state_delta=json.loads(row["state_delta_json"] or "{}"),
|
|
253
|
+
seq_id=row["seq_id"],
|
|
254
|
+
invocation_id=row["invocation_id"],
|
|
255
|
+
metadata=json.loads(row["metadata_json"] or "{}"),
|
|
256
|
+
)
|
|
257
|
+
for row in rows
|
|
258
|
+
]
|
|
259
|
+
|
|
260
|
+
def _count_events_for_agent_sync(
|
|
261
|
+
self,
|
|
262
|
+
agent_id: str,
|
|
263
|
+
user_id: Optional[str],
|
|
264
|
+
) -> int:
|
|
265
|
+
user_clause = "AND s.user_id = ?" if user_id is not None else ""
|
|
266
|
+
params: list[object] = [agent_id]
|
|
267
|
+
if user_id is not None:
|
|
268
|
+
params.append(user_id)
|
|
269
|
+
with self._connection() as connection:
|
|
270
|
+
row = connection.execute(
|
|
271
|
+
f"""
|
|
272
|
+
SELECT COUNT(*) AS total
|
|
273
|
+
FROM {KSADK_EVENTS_TABLE} e
|
|
274
|
+
JOIN {KSADK_SESSIONS_TABLE} s ON s.id = e.session_id
|
|
275
|
+
WHERE s.agent_id = ? {user_clause}
|
|
276
|
+
""",
|
|
277
|
+
params,
|
|
278
|
+
).fetchone()
|
|
279
|
+
return int(row["total"] if row else 0)
|
|
280
|
+
|
|
164
281
|
async def get_state(
|
|
165
282
|
self,
|
|
166
283
|
agent_id: str,
|
|
@@ -258,9 +375,7 @@ class LocalSessionService(BaseSessionService):
|
|
|
258
375
|
and not self._table_exists(connection, KSADK_EVENTS_TABLE)
|
|
259
376
|
and {"session_id", "author", "event_type"}.issubset(legacy_event_columns)
|
|
260
377
|
):
|
|
261
|
-
connection.execute(
|
|
262
|
-
f"ALTER TABLE {LEGACY_EVENTS_TABLE} RENAME TO {KSADK_EVENTS_TABLE}"
|
|
263
|
-
)
|
|
378
|
+
connection.execute(f"ALTER TABLE {LEGACY_EVENTS_TABLE} RENAME TO {KSADK_EVENTS_TABLE}")
|
|
264
379
|
|
|
265
380
|
legacy_state_columns = self._table_columns(connection, LEGACY_STATES_TABLE)
|
|
266
381
|
if (
|
|
@@ -268,15 +383,12 @@ class LocalSessionService(BaseSessionService):
|
|
|
268
383
|
and not self._table_exists(connection, KSADK_STATES_TABLE)
|
|
269
384
|
and {"scope", "agent_id", "state_json"}.issubset(legacy_state_columns)
|
|
270
385
|
):
|
|
271
|
-
connection.execute(
|
|
272
|
-
f"ALTER TABLE {LEGACY_STATES_TABLE} RENAME TO {KSADK_STATES_TABLE}"
|
|
273
|
-
)
|
|
386
|
+
connection.execute(f"ALTER TABLE {LEGACY_STATES_TABLE} RENAME TO {KSADK_STATES_TABLE}")
|
|
274
387
|
|
|
275
388
|
def _ensure_schema(self) -> None:
|
|
276
389
|
with self._connection() as connection:
|
|
277
390
|
self._migrate_legacy_schema(connection)
|
|
278
|
-
connection.executescript(
|
|
279
|
-
f"""
|
|
391
|
+
connection.executescript(f"""
|
|
280
392
|
CREATE TABLE IF NOT EXISTS {KSADK_SESSIONS_TABLE} (
|
|
281
393
|
id TEXT PRIMARY KEY,
|
|
282
394
|
agent_id TEXT NOT NULL,
|
|
@@ -309,6 +421,16 @@ class LocalSessionService(BaseSessionService):
|
|
|
309
421
|
CREATE INDEX IF NOT EXISTS idx_ksadk_events_session_seq
|
|
310
422
|
ON {KSADK_EVENTS_TABLE} (session_id, seq_id);
|
|
311
423
|
|
|
424
|
+
-- 跨会话事件查询(get_events_for_agent)JOIN sessions 按
|
|
425
|
+
-- s.agent_id 过滤 + ORDER BY e.timestamp;覆盖索引服务 JOIN 键
|
|
426
|
+
-- s.id=e.session_id + 排序。
|
|
427
|
+
CREATE INDEX IF NOT EXISTS idx_ksadk_events_session_ts
|
|
428
|
+
ON {KSADK_EVENTS_TABLE} (session_id, timestamp, id);
|
|
429
|
+
|
|
430
|
+
-- ListSessions 按 agent_id 过滤 + updated_at DESC 排序。
|
|
431
|
+
CREATE INDEX IF NOT EXISTS idx_ksadk_sessions_agent_updated
|
|
432
|
+
ON {KSADK_SESSIONS_TABLE} (agent_id, updated_at DESC, id);
|
|
433
|
+
|
|
312
434
|
CREATE TABLE IF NOT EXISTS {KSADK_STATES_TABLE} (
|
|
313
435
|
scope TEXT NOT NULL,
|
|
314
436
|
agent_id TEXT NOT NULL,
|
|
@@ -319,8 +441,7 @@ class LocalSessionService(BaseSessionService):
|
|
|
319
441
|
updated_at REAL NOT NULL,
|
|
320
442
|
PRIMARY KEY (scope, agent_id, user_id, session_id)
|
|
321
443
|
);
|
|
322
|
-
"""
|
|
323
|
-
)
|
|
444
|
+
""")
|
|
324
445
|
self._ensure_columns(
|
|
325
446
|
connection,
|
|
326
447
|
KSADK_SESSIONS_TABLE,
|
|
@@ -367,7 +488,7 @@ class LocalSessionService(BaseSessionService):
|
|
|
367
488
|
|
|
368
489
|
now = time.time()
|
|
369
490
|
session = Session(
|
|
370
|
-
id=session_id or
|
|
491
|
+
id=session_id or new_session_id(),
|
|
371
492
|
agent_id=agent_id,
|
|
372
493
|
user_id=user_id,
|
|
373
494
|
created_at=now,
|
|
@@ -413,6 +534,7 @@ class LocalSessionService(BaseSessionService):
|
|
|
413
534
|
session_id: str,
|
|
414
535
|
*,
|
|
415
536
|
connection: Optional[sqlite3.Connection] = None,
|
|
537
|
+
include_events: bool = True,
|
|
416
538
|
) -> Optional[Session]:
|
|
417
539
|
owns_connection = connection is None
|
|
418
540
|
connection = connection or self._connect()
|
|
@@ -439,7 +561,11 @@ class LocalSessionService(BaseSessionService):
|
|
|
439
561
|
first_prompt=row["first_prompt"],
|
|
440
562
|
last_prompt=row["last_prompt"],
|
|
441
563
|
state=json.loads(row["state_json"] or "{}"),
|
|
442
|
-
events=
|
|
564
|
+
events=(
|
|
565
|
+
self._get_events_sync(session_id, connection=connection)
|
|
566
|
+
if include_events
|
|
567
|
+
else []
|
|
568
|
+
),
|
|
443
569
|
created_at=row["created_at"],
|
|
444
570
|
updated_at=row["updated_at"],
|
|
445
571
|
version=row["version"],
|
|
@@ -467,7 +593,7 @@ class LocalSessionService(BaseSessionService):
|
|
|
467
593
|
if user_id is not None:
|
|
468
594
|
query += " AND user_id = ?"
|
|
469
595
|
params.append(user_id)
|
|
470
|
-
query += " ORDER BY updated_at DESC, created_at DESC"
|
|
596
|
+
query += " ORDER BY updated_at DESC, created_at DESC, id DESC"
|
|
471
597
|
if limit is not None:
|
|
472
598
|
query += " LIMIT ?"
|
|
473
599
|
params.append(limit)
|
|
@@ -520,8 +646,12 @@ class LocalSessionService(BaseSessionService):
|
|
|
520
646
|
if row is None:
|
|
521
647
|
return False
|
|
522
648
|
|
|
523
|
-
connection.execute(
|
|
524
|
-
|
|
649
|
+
connection.execute(
|
|
650
|
+
f"DELETE FROM {KSADK_EVENTS_TABLE} WHERE session_id = ?", (session_id,)
|
|
651
|
+
)
|
|
652
|
+
connection.execute(
|
|
653
|
+
f"DELETE FROM {KSADK_STATES_TABLE} WHERE session_id = ?", (session_id,)
|
|
654
|
+
)
|
|
525
655
|
connection.execute(f"DELETE FROM {KSADK_SESSIONS_TABLE} WHERE id = ?", (session_id,))
|
|
526
656
|
connection.commit()
|
|
527
657
|
return True
|
|
@@ -541,7 +671,8 @@ class LocalSessionService(BaseSessionService):
|
|
|
541
671
|
|
|
542
672
|
next_seq = int(
|
|
543
673
|
connection.execute(
|
|
544
|
-
f"SELECT COALESCE(MAX(seq_id), 0) + 1
|
|
674
|
+
f"SELECT COALESCE(MAX(seq_id), 0) + 1 "
|
|
675
|
+
f"FROM {KSADK_EVENTS_TABLE} WHERE session_id = ?",
|
|
545
676
|
(session_id,),
|
|
546
677
|
).fetchone()[0]
|
|
547
678
|
)
|
|
@@ -9,6 +9,7 @@ import time
|
|
|
9
9
|
from typing import Any, Optional
|
|
10
10
|
from urllib.parse import urlsplit, urlunsplit
|
|
11
11
|
|
|
12
|
+
from ksadk.ids import new_session_id
|
|
12
13
|
from ksadk.sessions.base import (
|
|
13
14
|
BaseSessionService,
|
|
14
15
|
Session,
|
|
@@ -59,7 +60,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
59
60
|
session_id: Optional[str] = None,
|
|
60
61
|
) -> Session:
|
|
61
62
|
await self._ensure_schema()
|
|
62
|
-
session_key = session_id or
|
|
63
|
+
session_key = session_id or new_session_id()
|
|
63
64
|
async with self._pool.acquire() as connection:
|
|
64
65
|
async with connection.transaction():
|
|
65
66
|
existing = await self._get_session_with_connection(connection, session_key)
|
|
@@ -70,8 +71,9 @@ class PostgresSessionService(BaseSessionService):
|
|
|
70
71
|
await connection.execute(
|
|
71
72
|
f"""
|
|
72
73
|
INSERT INTO {KSADK_PG_SESSIONS_TABLE} (
|
|
73
|
-
namespace, tenant_id, workspace_id, id, agent_id, user_id,
|
|
74
|
-
|
|
74
|
+
namespace, tenant_id, workspace_id, id, agent_id, user_id,
|
|
75
|
+
title, title_source, summary, first_prompt, last_prompt,
|
|
76
|
+
state_json, created_at, updated_at, version
|
|
75
77
|
)
|
|
76
78
|
VALUES ($1, $2, $3, $4, $5, $6, '', '', '', '', '', $7::jsonb, $8, $9, 0)
|
|
77
79
|
ON CONFLICT (namespace, id) DO NOTHING
|
|
@@ -96,7 +98,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
96
98
|
await connection.execute(
|
|
97
99
|
f"""
|
|
98
100
|
INSERT INTO {KSADK_PG_STATES_TABLE} (
|
|
99
|
-
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
101
|
+
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
102
|
+
user_id, session_id, state_json, version, updated_at
|
|
100
103
|
)
|
|
101
104
|
VALUES ($1, $2, $3, 'session', $4, $5, $6, $7::jsonb, 0, $8)
|
|
102
105
|
ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
|
|
@@ -118,6 +121,15 @@ class PostgresSessionService(BaseSessionService):
|
|
|
118
121
|
async with self._pool.acquire() as connection:
|
|
119
122
|
return await self._get_session_with_connection(connection, session_id)
|
|
120
123
|
|
|
124
|
+
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
125
|
+
await self._ensure_schema()
|
|
126
|
+
async with self._pool.acquire() as connection:
|
|
127
|
+
return await self._get_session_with_connection(
|
|
128
|
+
connection,
|
|
129
|
+
session_id,
|
|
130
|
+
include_events=False,
|
|
131
|
+
)
|
|
132
|
+
|
|
121
133
|
async def list_sessions(
|
|
122
134
|
self,
|
|
123
135
|
agent_id: str,
|
|
@@ -128,7 +140,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
128
140
|
await self._ensure_schema()
|
|
129
141
|
async with self._pool.acquire() as connection:
|
|
130
142
|
query = f"""
|
|
131
|
-
SELECT id, agent_id, user_id, title, title_source, summary,
|
|
143
|
+
SELECT id, agent_id, user_id, title, title_source, summary,
|
|
144
|
+
first_prompt, last_prompt,
|
|
132
145
|
state_json, created_at, updated_at, version
|
|
133
146
|
FROM {KSADK_PG_SESSIONS_TABLE}
|
|
134
147
|
WHERE namespace = $1 AND agent_id = $2
|
|
@@ -137,7 +150,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
137
150
|
if user_id is not None:
|
|
138
151
|
params.append(user_id)
|
|
139
152
|
query += f" AND user_id = ${len(params)}"
|
|
140
|
-
query += " ORDER BY updated_at DESC, created_at DESC"
|
|
153
|
+
query += " ORDER BY updated_at DESC, created_at DESC, id DESC"
|
|
141
154
|
if limit is not None:
|
|
142
155
|
params.append(limit)
|
|
143
156
|
query += f" LIMIT ${len(params)}"
|
|
@@ -205,7 +218,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
205
218
|
async with connection.transaction():
|
|
206
219
|
row = await connection.fetchrow(
|
|
207
220
|
f"""
|
|
208
|
-
SELECT id, agent_id, user_id, title, title_source, summary,
|
|
221
|
+
SELECT id, agent_id, user_id, title, title_source, summary,
|
|
222
|
+
first_prompt, last_prompt,
|
|
209
223
|
state_json, created_at, updated_at, version
|
|
210
224
|
FROM {KSADK_PG_SESSIONS_TABLE}
|
|
211
225
|
WHERE namespace = $1 AND id = $2
|
|
@@ -294,10 +308,14 @@ class PostgresSessionService(BaseSessionService):
|
|
|
294
308
|
await connection.execute(
|
|
295
309
|
f"""
|
|
296
310
|
INSERT INTO {KSADK_PG_EVENTS_TABLE} (
|
|
297
|
-
namespace, tenant_id, workspace_id, id, session_id, author,
|
|
311
|
+
namespace, tenant_id, workspace_id, id, session_id, author,
|
|
312
|
+
event_type, content_json, timestamp,
|
|
298
313
|
state_delta_json, seq_id, invocation_id, metadata_json
|
|
299
314
|
)
|
|
300
|
-
VALUES (
|
|
315
|
+
VALUES (
|
|
316
|
+
$1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9,
|
|
317
|
+
$10::jsonb, $11, $12, $13::jsonb
|
|
318
|
+
)
|
|
301
319
|
""",
|
|
302
320
|
self.namespace,
|
|
303
321
|
self.tenant_id,
|
|
@@ -419,6 +437,85 @@ class PostgresSessionService(BaseSessionService):
|
|
|
419
437
|
"""
|
|
420
438
|
return int(await connection.fetchval(query, *params) or 0)
|
|
421
439
|
|
|
440
|
+
def _agent_events_query_parts(
|
|
441
|
+
self,
|
|
442
|
+
agent_id: str,
|
|
443
|
+
user_id: Optional[str],
|
|
444
|
+
) -> tuple[str, list[Any]]:
|
|
445
|
+
"""跨会话事件查询的公共 JOIN/WHERE。events 表无 agent_id 列,需 join sessions。"""
|
|
446
|
+
conditions = [
|
|
447
|
+
"e.namespace = $1",
|
|
448
|
+
"s.namespace = e.namespace",
|
|
449
|
+
"s.id = e.session_id",
|
|
450
|
+
"s.agent_id = $2",
|
|
451
|
+
]
|
|
452
|
+
params: list[Any] = [self.namespace, agent_id]
|
|
453
|
+
if user_id is not None:
|
|
454
|
+
params.append(user_id)
|
|
455
|
+
conditions.append(f"s.user_id = ${len(params)}")
|
|
456
|
+
where_clause = " AND ".join(conditions)
|
|
457
|
+
from_clause = (
|
|
458
|
+
f"FROM {KSADK_PG_EVENTS_TABLE} e "
|
|
459
|
+
f"JOIN {KSADK_PG_SESSIONS_TABLE} s "
|
|
460
|
+
"ON s.namespace = e.namespace AND s.id = e.session_id "
|
|
461
|
+
f"WHERE {where_clause}"
|
|
462
|
+
)
|
|
463
|
+
return from_clause, params
|
|
464
|
+
|
|
465
|
+
async def get_events_for_agent(
|
|
466
|
+
self,
|
|
467
|
+
agent_id: str,
|
|
468
|
+
user_id: Optional[str] = None,
|
|
469
|
+
offset: Optional[int] = None,
|
|
470
|
+
limit: Optional[int] = None,
|
|
471
|
+
) -> list[SessionEvent]:
|
|
472
|
+
await self._ensure_schema()
|
|
473
|
+
from_clause, params = self._agent_events_query_parts(agent_id, user_id)
|
|
474
|
+
columns = (
|
|
475
|
+
"e.id, e.session_id, e.author, e.event_type, e.content_json, e.timestamp, "
|
|
476
|
+
"e.state_delta_json, e.seq_id, e.invocation_id, e.metadata_json"
|
|
477
|
+
)
|
|
478
|
+
async with self._pool.acquire() as connection:
|
|
479
|
+
if limit is not None or offset is not None:
|
|
480
|
+
# 与 get_events 一致的"最新 N 条"尾部语义:先 DESC 取窗口再 ASC 重排
|
|
481
|
+
if limit is not None:
|
|
482
|
+
params.append(limit)
|
|
483
|
+
limit_sql = f"LIMIT ${len(params)}"
|
|
484
|
+
else:
|
|
485
|
+
limit_sql = ""
|
|
486
|
+
params.append(offset or 0)
|
|
487
|
+
offset_sql = f"OFFSET ${len(params)}"
|
|
488
|
+
query = f"""
|
|
489
|
+
SELECT id, session_id, author, event_type, content_json, timestamp,
|
|
490
|
+
state_delta_json, seq_id, invocation_id, metadata_json
|
|
491
|
+
FROM (
|
|
492
|
+
SELECT {columns}
|
|
493
|
+
{from_clause}
|
|
494
|
+
ORDER BY e.timestamp DESC, e.seq_id DESC, e.id DESC
|
|
495
|
+
{limit_sql} {offset_sql}
|
|
496
|
+
) AS latest_events
|
|
497
|
+
ORDER BY timestamp ASC, seq_id ASC, id ASC
|
|
498
|
+
"""
|
|
499
|
+
else:
|
|
500
|
+
query = f"""
|
|
501
|
+
SELECT {columns}
|
|
502
|
+
{from_clause}
|
|
503
|
+
ORDER BY e.timestamp ASC, e.seq_id ASC, e.id ASC
|
|
504
|
+
"""
|
|
505
|
+
rows = await connection.fetch(query, *params)
|
|
506
|
+
return [self._event_from_row(row) for row in rows]
|
|
507
|
+
|
|
508
|
+
async def count_events_for_agent(
|
|
509
|
+
self,
|
|
510
|
+
agent_id: str,
|
|
511
|
+
user_id: Optional[str] = None,
|
|
512
|
+
) -> int:
|
|
513
|
+
await self._ensure_schema()
|
|
514
|
+
from_clause, params = self._agent_events_query_parts(agent_id, user_id)
|
|
515
|
+
async with self._pool.acquire() as connection:
|
|
516
|
+
query = f"SELECT COUNT(*) AS total {from_clause}"
|
|
517
|
+
return int(await connection.fetchval(query, *params) or 0)
|
|
518
|
+
|
|
422
519
|
async def get_state(
|
|
423
520
|
self,
|
|
424
521
|
agent_id: str,
|
|
@@ -445,7 +542,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
445
542
|
f"""
|
|
446
543
|
SELECT scope, agent_id, user_id, session_id, state_json, version, updated_at
|
|
447
544
|
FROM {KSADK_PG_STATES_TABLE}
|
|
448
|
-
WHERE namespace = $1 AND scope = $2 AND agent_id = $3
|
|
545
|
+
WHERE namespace = $1 AND scope = $2 AND agent_id = $3
|
|
546
|
+
AND user_id = $4 AND session_id = $5
|
|
449
547
|
""",
|
|
450
548
|
self.namespace,
|
|
451
549
|
scope,
|
|
@@ -506,7 +604,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
506
604
|
f"""
|
|
507
605
|
SELECT state_json, version
|
|
508
606
|
FROM {KSADK_PG_STATES_TABLE}
|
|
509
|
-
WHERE namespace = $1 AND scope = $2 AND agent_id = $3
|
|
607
|
+
WHERE namespace = $1 AND scope = $2 AND agent_id = $3
|
|
608
|
+
AND user_id = $4 AND session_id = $5
|
|
510
609
|
FOR UPDATE
|
|
511
610
|
""",
|
|
512
611
|
self.namespace,
|
|
@@ -521,7 +620,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
521
620
|
await connection.execute(
|
|
522
621
|
f"""
|
|
523
622
|
INSERT INTO {KSADK_PG_STATES_TABLE} (
|
|
524
|
-
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
623
|
+
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
624
|
+
user_id, session_id, state_json, version, updated_at
|
|
525
625
|
)
|
|
526
626
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10)
|
|
527
627
|
ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
|
|
@@ -568,7 +668,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
568
668
|
if self._pool is not None:
|
|
569
669
|
return
|
|
570
670
|
try:
|
|
571
|
-
import asyncpg
|
|
671
|
+
import asyncpg # type: ignore[import-untyped]
|
|
572
672
|
except ImportError as exc:
|
|
573
673
|
raise SessionBackendUnavailable(
|
|
574
674
|
"asyncpg is required for KSADK_SESSION_BACKEND=postgres"
|
|
@@ -595,8 +695,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
595
695
|
return
|
|
596
696
|
await self._ensure_pool()
|
|
597
697
|
async with self._pool.acquire() as connection:
|
|
598
|
-
await connection.execute(
|
|
599
|
-
f"""
|
|
698
|
+
await connection.execute(f"""
|
|
600
699
|
CREATE TABLE IF NOT EXISTS {KSADK_PG_SESSIONS_TABLE} (
|
|
601
700
|
namespace TEXT NOT NULL,
|
|
602
701
|
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
@@ -640,6 +739,18 @@ class PostgresSessionService(BaseSessionService):
|
|
|
640
739
|
CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_seq
|
|
641
740
|
ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, seq_id);
|
|
642
741
|
|
|
742
|
+
-- 跨会话事件查询(get_events_for_agent)需 JOIN sessions 按
|
|
743
|
+
-- s.agent_id 过滤并按 e.timestamp 排序;events 表无 agent_id 列,
|
|
744
|
+
-- 覆盖索引 (namespace, session_id, timestamp, id) 服务 JOIN 键
|
|
745
|
+
-- s.id=e.session_id + ORDER BY e.timestamp DESC。
|
|
746
|
+
CREATE INDEX IF NOT EXISTS idx_ksadk_pg_events_session_ts
|
|
747
|
+
ON {KSADK_PG_EVENTS_TABLE} (namespace, session_id, timestamp, id);
|
|
748
|
+
|
|
749
|
+
-- ListSessions 归并按 agent_id 过滤 + updated_at DESC 排序;
|
|
750
|
+
-- sessions 表 PK 是 (namespace, id),缺 agent_id 前缀索引。
|
|
751
|
+
CREATE INDEX IF NOT EXISTS idx_ksadk_pg_sessions_agent_updated
|
|
752
|
+
ON {KSADK_PG_SESSIONS_TABLE} (namespace, agent_id, updated_at DESC, id);
|
|
753
|
+
|
|
643
754
|
CREATE TABLE IF NOT EXISTS {KSADK_PG_STATES_TABLE} (
|
|
644
755
|
namespace TEXT NOT NULL,
|
|
645
756
|
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
@@ -666,11 +777,9 @@ class PostgresSessionService(BaseSessionService):
|
|
|
666
777
|
ADD COLUMN IF NOT EXISTS tenant_id TEXT NOT NULL DEFAULT 'default';
|
|
667
778
|
ALTER TABLE {KSADK_PG_STATES_TABLE}
|
|
668
779
|
ADD COLUMN IF NOT EXISTS workspace_id TEXT NOT NULL DEFAULT 'default';
|
|
669
|
-
"""
|
|
670
|
-
)
|
|
780
|
+
""")
|
|
671
781
|
try:
|
|
672
|
-
await connection.execute(
|
|
673
|
-
f"""
|
|
782
|
+
await connection.execute(f"""
|
|
674
783
|
CREATE OR REPLACE VIEW {PG_READABLE_EVENTS_VIEW} AS
|
|
675
784
|
SELECT
|
|
676
785
|
event_row.namespace,
|
|
@@ -715,8 +824,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
715
824
|
JOIN {KSADK_PG_SESSIONS_TABLE} AS session_row
|
|
716
825
|
ON session_row.namespace = event_row.namespace
|
|
717
826
|
AND session_row.id = event_row.session_id;
|
|
718
|
-
"""
|
|
719
|
-
)
|
|
827
|
+
""")
|
|
720
828
|
except Exception as exc:
|
|
721
829
|
logger.warning("Postgres readable session view unavailable: %s", exc)
|
|
722
830
|
self._schema_ready = True
|
|
@@ -727,6 +835,7 @@ class PostgresSessionService(BaseSessionService):
|
|
|
727
835
|
session_id: str,
|
|
728
836
|
*,
|
|
729
837
|
for_update: bool = False,
|
|
838
|
+
include_events: bool = True,
|
|
730
839
|
) -> Optional[Session]:
|
|
731
840
|
lock_clause = " FOR UPDATE" if for_update else ""
|
|
732
841
|
row = await connection.fetchrow(
|
|
@@ -742,10 +851,16 @@ class PostgresSessionService(BaseSessionService):
|
|
|
742
851
|
)
|
|
743
852
|
if row is None:
|
|
744
853
|
return None
|
|
745
|
-
events =
|
|
854
|
+
events = (
|
|
855
|
+
await self._get_events_with_connection(connection, session_id)
|
|
856
|
+
if include_events and not for_update
|
|
857
|
+
else []
|
|
858
|
+
)
|
|
746
859
|
return self._session_from_row(row, events=events)
|
|
747
860
|
|
|
748
|
-
async def _get_events_with_connection(
|
|
861
|
+
async def _get_events_with_connection(
|
|
862
|
+
self, connection: Any, session_id: str
|
|
863
|
+
) -> list[SessionEvent]:
|
|
749
864
|
rows = await connection.fetch(
|
|
750
865
|
f"""
|
|
751
866
|
SELECT id, session_id, author, event_type, content_json, timestamp,
|
|
@@ -785,7 +900,8 @@ class PostgresSessionService(BaseSessionService):
|
|
|
785
900
|
await connection.execute(
|
|
786
901
|
f"""
|
|
787
902
|
INSERT INTO {KSADK_PG_STATES_TABLE} (
|
|
788
|
-
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
903
|
+
namespace, tenant_id, workspace_id, scope, agent_id,
|
|
904
|
+
user_id, session_id, state_json, version, updated_at
|
|
789
905
|
)
|
|
790
906
|
VALUES ($1, $2, $3, 'session', $4, $5, $6, $7::jsonb, $8, $9)
|
|
791
907
|
ON CONFLICT (namespace, scope, agent_id, user_id, session_id)
|
|
@@ -888,7 +1004,9 @@ def mask_postgres_session_dsn(dsn: str) -> str:
|
|
|
888
1004
|
host = parts.hostname or ""
|
|
889
1005
|
port = f":{parts.port}" if parts.port else ""
|
|
890
1006
|
auth = f"{username}:***@" if username else "***@"
|
|
891
|
-
return urlunsplit(
|
|
1007
|
+
return urlunsplit(
|
|
1008
|
+
(parts.scheme, f"{auth}{host}{port}", parts.path, parts.query, parts.fragment)
|
|
1009
|
+
)
|
|
892
1010
|
|
|
893
1011
|
|
|
894
1012
|
__all__ = [
|