agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.4__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.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
- ksadk/_build_provenance.json +1 -1
- ksadk/api/client.py +105 -91
- ksadk/builders/code_builder.py +36 -9
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +1 -0
- ksadk/cli/__init__.py +32 -3
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_plugin.py +6 -1
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +424 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +56 -298
- ksadk/common/auth.py +16 -10
- ksadk/configs/env_registry.py +29 -1
- ksadk/conversations/message_projection.py +135 -14
- ksadk/conversations/projector.py +4 -6
- ksadk/conversations/runtime_invocation.py +5 -0
- ksadk/conversations/runtime_payloads.py +1 -0
- ksadk/conversations/runtime_preparation.py +30 -27
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +5 -0
- ksadk/conversations/runtime_streaming.py +25 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/harness/config.py +2 -2
- ksadk/harness/runtime.py +27 -27
- ksadk/harness/tools.py +38 -13
- ksadk/interaction/provider.py +1 -0
- ksadk/interaction/providers/langgraph.py +1 -0
- ksadk/kernel/bootstrap.py +28 -4
- ksadk/kernel/ingress.py +15 -2
- ksadk/kernel/sqlite_store.py +27 -0
- ksadk/kernel/store.py +3 -0
- ksadk/kernel/worker.py +65 -10
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/models.py +7 -4
- ksadk/memory/provider_resolver.py +3 -0
- ksadk/model_proxy/server.py +10 -5
- ksadk/plugins/__init__.py +4 -0
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +4 -2
- ksadk/plugins/bridges/codex.py +120 -13
- ksadk/plugins/bridges/dsh.py +340 -156
- ksadk/plugins/builtins.py +35 -36
- ksadk/plugins/bundle_security.py +28 -4
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/composition.py +8 -0
- ksadk/plugins/contracts.py +118 -0
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_toolchain.py +110 -21
- ksadk/plugins/ecosystem_probe.py +6 -6
- ksadk/plugins/host.py +102 -39
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +23 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/codex.py +335 -69
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh_capabilities.py +1389 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +118 -113
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/resolver.py +8 -1
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +74 -6
- ksadk/runners/adk_runner.py +149 -11
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +475 -145
- ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
- ksadk/runtime/adapter.py +2 -0
- ksadk/runtime/conversation_execution.py +92 -16
- ksadk/runtime/executor.py +78 -2
- ksadk/runtime/factory.py +29 -273
- ksadk/runtime/framework_adapters.py +23 -0
- ksadk/runtime/preprocessing.py +10 -2
- ksadk/runtime/runner_adapter.py +73 -14
- ksadk/runtime_context.py +40 -2
- ksadk/sandbox/backends/e2b.py +52 -11
- ksadk/sandbox/backends/local_process.py +9 -0
- ksadk/sandbox/base.py +2 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/scheduler/sqlite_store.py +18 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/control.py +210 -46
- ksadk/server/routes/dependencies.py +15 -0
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/sessions.py +284 -107
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
- ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
- ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
- ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
- ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
- ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
- ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
- ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
- ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
- ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
- ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
- ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
- ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
- ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
- ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
- ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
- ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
- ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
- ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
- ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
- ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
- ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
- ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
- ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
- ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
- ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
- ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
- ksadk/server/static/assets/index-DcTML1Up.css +2 -0
- ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
- ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
- ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/models.py +26 -4
- ksadk/skills/package_store.py +186 -38
- ksadk/skills/runtime/agent.py +31 -6
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/backends/e2b.py +98 -6
- ksadk/skills/runtime/backends/local.py +73 -8
- ksadk/skills/runtime/base.py +3 -0
- ksadk/skills/runtime/executor.py +2 -0
- ksadk/skills/runtime/loader.py +10 -2
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +31 -0
- ksadk/skills/service_client.py +167 -28
- ksadk/studio/api.py +224 -42
- ksadk/studio/api_catalog_routes.py +18 -0
- ksadk/studio/api_plugin_routes.py +526 -95
- ksadk/studio/api_resource_connections.py +183 -0
- ksadk/studio/authoring_coordinator.py +19 -14
- ksadk/studio/builder.py +76 -0
- ksadk/studio/cloud.py +342 -104
- ksadk/studio/cloud_shared_web.py +565 -0
- ksadk/studio/codex_agent_service.py +128 -26
- ksadk/studio/codex_builder.py +241 -2
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +31 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +184 -25
- ksadk/studio/compatibility_report.py +12 -1
- ksadk/studio/compiler.py +78 -14
- ksadk/studio/contracts.py +132 -6
- ksadk/studio/dsh_application.py +137 -0
- ksadk/studio/dsh_capability_service.py +1107 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +320 -13
- ksadk/studio/hosted_kernel.py +88 -13
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +2 -2
- ksadk/studio/plugin_composition.py +190 -23
- ksadk/studio/plugin_kernel_adapter.py +12 -112
- ksadk/studio/plugin_runtime.py +224 -45
- ksadk/studio/resource_authority.py +637 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +143 -2
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_service.py +462 -52
- ksadk/studio/runtime_source.py +15 -7
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +9 -0
- ksadk/studio/scheduler_service.py +3 -0
- ksadk/studio/service.py +490 -44
- ksadk/studio/shared_web.py +446 -62
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
- ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
- ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
- ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/version.py +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
- ksadk/server/static/assets/index-B2k_urY8.js +0 -241
- ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
- ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
ksadk/knowledge_base/client.py
CHANGED
|
@@ -86,6 +86,8 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
86
86
|
# KnowledgeBaseService.build_context 区分"后端吞错返空"与"真无结果",
|
|
87
87
|
# 避免错误伪装成"未找到"注入模型上下文。
|
|
88
88
|
last_error: str = ""
|
|
89
|
+
last_request_id: str = ""
|
|
90
|
+
last_http_status: int | None = None
|
|
89
91
|
|
|
90
92
|
_aicp_client: Any = None
|
|
91
93
|
|
|
@@ -140,9 +142,7 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
140
142
|
"Ensure kingsoftcloud-sdk-python is installed and up to date."
|
|
141
143
|
)
|
|
142
144
|
|
|
143
|
-
cred = credential.Credential(
|
|
144
|
-
self.access_key, self.secret_key, self.session_token or None
|
|
145
|
-
)
|
|
145
|
+
cred = credential.Credential(self.access_key, self.secret_key, self.session_token or None)
|
|
146
146
|
|
|
147
147
|
http_profile = HttpProfile()
|
|
148
148
|
http_profile.endpoint = self.endpoint
|
|
@@ -153,17 +153,23 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
153
153
|
client_profile = ClientProfile()
|
|
154
154
|
client_profile.httpProfile = http_profile
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
owner = self
|
|
157
|
+
|
|
158
|
+
class ObservedAicpClient(aicp_module.AicpClient):
|
|
159
|
+
def _check_status(self, response):
|
|
160
|
+
# The upstream SDK discards HTTP status when raising its generic
|
|
161
|
+
# ServerNetworkError. Capture only the status before delegation;
|
|
162
|
+
# never infer authorization from exception text/response content.
|
|
163
|
+
owner.last_http_status = response.status
|
|
164
|
+
return super()._check_status(response)
|
|
165
|
+
|
|
166
|
+
self._aicp_client = ObservedAicpClient(cred, self.region, profile=client_profile)
|
|
157
167
|
|
|
158
168
|
# 强制覆写 API 版本为 RetrieveKnowledge 所需的 2025-11-14
|
|
159
169
|
# SDK 的 _apiVersion 由导入的模块版本决定,可能不匹配
|
|
160
170
|
self._aicp_client._apiVersion = "2025-11-14"
|
|
161
171
|
|
|
162
|
-
logger.
|
|
163
|
-
f"KnowledgeBaseClient initialized: "
|
|
164
|
-
f"dataset_id={self.dataset_id}, region={self.region}, "
|
|
165
|
-
f"endpoint={self.endpoint}"
|
|
166
|
-
)
|
|
172
|
+
logger.debug("KnowledgeBaseClient initialized")
|
|
167
173
|
return self._aicp_client
|
|
168
174
|
|
|
169
175
|
def _build_params(self, query: str, top_k: Optional[int] = None) -> dict:
|
|
@@ -192,11 +198,41 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
192
198
|
try:
|
|
193
199
|
data = json.loads(response) if isinstance(response, str) else response
|
|
194
200
|
except (json.JSONDecodeError, TypeError):
|
|
195
|
-
self.last_error =
|
|
196
|
-
logger.error(
|
|
201
|
+
self.last_error = "Invalid knowledge response JSON"
|
|
202
|
+
logger.error("Invalid knowledge response JSON")
|
|
203
|
+
return []
|
|
204
|
+
|
|
205
|
+
if not isinstance(data, dict):
|
|
206
|
+
self.last_error = "Knowledge response must be an object"
|
|
207
|
+
return []
|
|
208
|
+
metadata = data.get("ResponseMetadata") or {}
|
|
209
|
+
if not isinstance(metadata, dict):
|
|
210
|
+
self.last_error = "Invalid knowledge response metadata"
|
|
211
|
+
return []
|
|
212
|
+
request_id = data.get("RequestId") or metadata.get("RequestId")
|
|
213
|
+
self.last_request_id = (
|
|
214
|
+
request_id if isinstance(request_id, str) and len(request_id) <= 256 else ""
|
|
215
|
+
)
|
|
216
|
+
code = data.get("Code")
|
|
217
|
+
if "Code" in data:
|
|
218
|
+
valid_code = (
|
|
219
|
+
(type(code) is int and code in {0, 200})
|
|
220
|
+
or (type(code) is str and code in {"0", "200"})
|
|
221
|
+
)
|
|
222
|
+
if not valid_code:
|
|
223
|
+
self.last_error = "Knowledge service rejected the request"
|
|
224
|
+
return []
|
|
225
|
+
if data.get("Error") or metadata.get("Error"):
|
|
226
|
+
self.last_error = "Knowledge service rejected the request"
|
|
197
227
|
return []
|
|
198
228
|
|
|
199
|
-
|
|
229
|
+
if "Records" not in data:
|
|
230
|
+
self.last_error = "Knowledge response omitted records"
|
|
231
|
+
return []
|
|
232
|
+
records = data["Records"]
|
|
233
|
+
if not isinstance(records, list):
|
|
234
|
+
self.last_error = "Invalid knowledge records"
|
|
235
|
+
return []
|
|
200
236
|
results = []
|
|
201
237
|
|
|
202
238
|
for record in records:
|
|
@@ -228,24 +264,19 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
228
264
|
Returns:
|
|
229
265
|
匹配的文档片段列表
|
|
230
266
|
"""
|
|
231
|
-
client = self._get_client()
|
|
232
|
-
params = self._build_params(query, top_k)
|
|
233
|
-
|
|
234
|
-
logger.info(
|
|
235
|
-
f"Searching knowledge base: dataset_id={self.dataset_id}, " f"query='{query[:50]}'"
|
|
236
|
-
)
|
|
237
|
-
|
|
238
267
|
self.last_error = ""
|
|
268
|
+
self.last_request_id = ""
|
|
269
|
+
self.last_http_status = None
|
|
239
270
|
try:
|
|
271
|
+
client = self._get_client()
|
|
272
|
+
params = self._build_params(query, top_k)
|
|
240
273
|
response = client.call("RetrieveKnowledge", params, options={"IsPostJson": True})
|
|
241
274
|
results = self._parse_response(response)
|
|
242
|
-
logger.
|
|
243
|
-
f"Knowledge base returned {len(results)} results " f"for query='{query[:50]}'"
|
|
244
|
-
)
|
|
275
|
+
logger.debug("Knowledge base returned %d results", len(results))
|
|
245
276
|
return results
|
|
246
277
|
except Exception as e:
|
|
247
278
|
self.last_error = str(e)
|
|
248
|
-
logger.error(
|
|
279
|
+
logger.error("Knowledge base search failed (%s)", type(e).__name__)
|
|
249
280
|
raise
|
|
250
281
|
|
|
251
282
|
@classmethod
|
|
@@ -261,7 +292,7 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
261
292
|
dataset_id = os.environ.get("KSADK_KB_DATASET_ID", "")
|
|
262
293
|
if not dataset_id:
|
|
263
294
|
raise ValueError(
|
|
264
|
-
"KSADK_KB_DATASET_ID environment variable is required
|
|
295
|
+
"KSADK_KB_DATASET_ID environment variable is required to enable knowledge base."
|
|
265
296
|
)
|
|
266
297
|
|
|
267
298
|
access_key = (
|
|
@@ -275,9 +306,8 @@ class KnowledgeBaseClient(BaseModel):
|
|
|
275
306
|
or os.environ.get("KSYUN_SECRET_KEY")
|
|
276
307
|
or os.environ.get("KSYUN_SECRET_ACCESS_KEY", "")
|
|
277
308
|
)
|
|
278
|
-
session_token = (
|
|
279
|
-
|
|
280
|
-
or os.environ.get("KSYUN_SESSION_TOKEN", "")
|
|
309
|
+
session_token = os.environ.get("KSADK_KB_SESSION_TOKEN") or os.environ.get(
|
|
310
|
+
"KSYUN_SESSION_TOKEN", ""
|
|
281
311
|
)
|
|
282
312
|
|
|
283
313
|
score_threshold_str = os.environ.get("KSADK_KB_SCORE_THRESHOLD", "")
|
ksadk/mcp_runtime/__init__.py
CHANGED
|
@@ -3,11 +3,12 @@ from __future__ import annotations
|
|
|
3
3
|
import inspect
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
|
-
from dataclasses import dataclass
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
7
|
from typing import Any, Coroutine, Sequence, cast
|
|
8
8
|
from urllib.parse import urlparse
|
|
9
9
|
|
|
10
10
|
import httpx
|
|
11
|
+
from pydantic import Field
|
|
11
12
|
|
|
12
13
|
from ksadk.compat.adk_compat import (
|
|
13
14
|
CheckableMcpHttpClientFactory,
|
|
@@ -21,8 +22,8 @@ MCP_TOOLSET_KEY_ATTR = "_ksadk_mcp_toolset_key"
|
|
|
21
22
|
@dataclass(frozen=True)
|
|
22
23
|
class MCPServerConfig:
|
|
23
24
|
name: str
|
|
24
|
-
url: str
|
|
25
|
-
api_key: str | None = None
|
|
25
|
+
url: str = field(repr=False)
|
|
26
|
+
api_key: str | None = field(default=None, repr=False)
|
|
26
27
|
tool_filter: tuple[str, ...] = ()
|
|
27
28
|
tool_name_prefix: str | None = None
|
|
28
29
|
|
|
@@ -68,7 +69,14 @@ def build_connection_params(
|
|
|
68
69
|
kwargs["httpx_client_factory"] = httpx_client_factory or _default_httpx_client_factory(
|
|
69
70
|
config.url
|
|
70
71
|
)
|
|
71
|
-
return
|
|
72
|
+
return _RedactedStreamableHTTPConnectionParams(**kwargs)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class _RedactedStreamableHTTPConnectionParams(StreamableHTTPConnectionParams):
|
|
76
|
+
"""Keep process-scoped MCP connection material out of debug reprs."""
|
|
77
|
+
|
|
78
|
+
url: str = Field(repr=False)
|
|
79
|
+
headers: dict[str, Any] | None = Field(default=None, repr=False)
|
|
72
80
|
|
|
73
81
|
|
|
74
82
|
def build_mcp_toolset(
|
|
@@ -52,7 +52,8 @@ DEFAULT_SCENE_ID = "_sys_general"
|
|
|
52
52
|
# "记忆不存在"识别模式(方案 §17.4:准确错误码待真实 fixture 固化,
|
|
53
53
|
# 首版按保守中英文模式匹配,fixture 到位后收敛为精确匹配)。
|
|
54
54
|
_NOT_EXIST_RE = re.compile(
|
|
55
|
-
r"not[ _]?exist|does not exist|memory.*不存在|记忆不存在|记忆已被删除|
|
|
55
|
+
r"not[ _]?exist|does not exist|memory.*不存在|记忆不存在|记忆已被删除|"
|
|
56
|
+
r"resourcenotfound|notfound",
|
|
56
57
|
re.IGNORECASE,
|
|
57
58
|
)
|
|
58
59
|
|
|
@@ -98,6 +99,7 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
98
99
|
agent_id: str = ""
|
|
99
100
|
scene_id: str = DEFAULT_SCENE_ID
|
|
100
101
|
last_error: str = ""
|
|
102
|
+
last_http_status: int | None = None
|
|
101
103
|
last_create_response: dict[str, Any] = Field(default_factory=dict)
|
|
102
104
|
last_session_status: dict[str, Any] = Field(default_factory=dict)
|
|
103
105
|
|
|
@@ -176,7 +178,16 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
176
178
|
client_profile = ClientProfile()
|
|
177
179
|
client_profile.httpProfile = http_profile
|
|
178
180
|
|
|
179
|
-
|
|
181
|
+
owner = self
|
|
182
|
+
|
|
183
|
+
class ObservedAicpClient(aicp_module.AicpClient):
|
|
184
|
+
def _check_status(self, response):
|
|
185
|
+
# Preserve the status that the upstream SDK's generic exception
|
|
186
|
+
# otherwise discards. No response content is used as authority.
|
|
187
|
+
owner.last_http_status = response.status
|
|
188
|
+
return super()._check_status(response)
|
|
189
|
+
|
|
190
|
+
self._aicp_client = ObservedAicpClient(cred, self.region, profile=client_profile)
|
|
180
191
|
|
|
181
192
|
# 强制覆写 API 版本为记忆库 API 所需的 2025-11-14
|
|
182
193
|
self._aicp_client._apiVersion = "2025-11-14"
|
|
@@ -246,6 +257,7 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
246
257
|
|
|
247
258
|
try:
|
|
248
259
|
self.last_error = ""
|
|
260
|
+
self.last_create_response = {}
|
|
249
261
|
conversation = self._build_conversation(event_strings)
|
|
250
262
|
if not conversation:
|
|
251
263
|
logger.info("No valid conversation items to save")
|
|
@@ -278,6 +290,11 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
278
290
|
|
|
279
291
|
response = client.call("CreateMemorySdk", params, options={"IsPostJson": True})
|
|
280
292
|
self.last_create_response = self._parse_json_response(response) or {}
|
|
293
|
+
if kwargs.get("strict", False):
|
|
294
|
+
data = self.last_create_response
|
|
295
|
+
if not self._confirmed_mutation_response(data):
|
|
296
|
+
self.last_error = "MEMORY_WRITE_RESPONSE_UNKNOWN"
|
|
297
|
+
return False
|
|
281
298
|
self.last_session_status = {
|
|
282
299
|
"SessionId": session_id,
|
|
283
300
|
"AgentUserId": user_id,
|
|
@@ -290,8 +307,8 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
290
307
|
return True
|
|
291
308
|
|
|
292
309
|
except Exception as e:
|
|
293
|
-
self.last_error = str(e)
|
|
294
|
-
logger.error(
|
|
310
|
+
self.last_error = "MEMORY_WRITE_UNKNOWN" if kwargs.get("strict", False) else str(e)
|
|
311
|
+
logger.error("CreateMemorySdk did not return a confirmed acknowledgment")
|
|
295
312
|
return False
|
|
296
313
|
|
|
297
314
|
def search_memory(self, user_id: str, query: str, top_k: int = 5, **kwargs) -> list[str]:
|
|
@@ -379,7 +396,9 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
379
396
|
"SceneId": self._effective_scene_id(),
|
|
380
397
|
}
|
|
381
398
|
response = client.call("QueryMemorySdk", params, options={"IsPostJson": True})
|
|
382
|
-
records = self._parse_query_records_response(
|
|
399
|
+
records = self._parse_query_records_response(
|
|
400
|
+
response, user_id=user_id, strict=kwargs.get("strict", False)
|
|
401
|
+
)
|
|
383
402
|
logger.info(
|
|
384
403
|
f"QueryMemorySdk structured: user={user_id}, records={len(records)}"
|
|
385
404
|
)
|
|
@@ -452,9 +471,16 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
452
471
|
)
|
|
453
472
|
|
|
454
473
|
data = self._parse_json_response(response)
|
|
474
|
+
if kwargs.get("strict", False) and not self._confirmed_mutation_response(data):
|
|
475
|
+
return MemoryMutationResult(
|
|
476
|
+
ok=False, memory_id=memory_id, status="failed",
|
|
477
|
+
message="记忆更新结果未确认",
|
|
478
|
+
)
|
|
455
479
|
response_memory_id = self._parse_new_memory_id(data)
|
|
456
480
|
new_memory_id = response_memory_id
|
|
457
|
-
if not
|
|
481
|
+
if not kwargs.get("strict", False) and (
|
|
482
|
+
not response_memory_id or response_memory_id == memory_id
|
|
483
|
+
):
|
|
458
484
|
# The service can merge an edited memory into another record while
|
|
459
485
|
# returning no new ID (or echoing the old one). Do not expose that
|
|
460
486
|
# stale handle to callers: confirm the current handle by listing
|
|
@@ -512,7 +538,7 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
512
538
|
"AgentUserId": user_id,
|
|
513
539
|
}
|
|
514
540
|
try:
|
|
515
|
-
client.call("DeleteMemory", params, options={"IsPostJson": True})
|
|
541
|
+
response = client.call("DeleteMemory", params, options={"IsPostJson": True})
|
|
516
542
|
except Exception as exc:
|
|
517
543
|
if self._is_not_exist_error(exc):
|
|
518
544
|
return MemoryMutationResult(
|
|
@@ -529,6 +555,13 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
529
555
|
status="failed",
|
|
530
556
|
message="记忆删除失败",
|
|
531
557
|
)
|
|
558
|
+
if kwargs.get("strict", False) and not self._confirmed_mutation_response(
|
|
559
|
+
self._parse_json_response(response)
|
|
560
|
+
):
|
|
561
|
+
return MemoryMutationResult(
|
|
562
|
+
ok=False, memory_id=memory_id, status="failed",
|
|
563
|
+
message="记忆删除结果未确认",
|
|
564
|
+
)
|
|
532
565
|
return MemoryMutationResult(
|
|
533
566
|
ok=True,
|
|
534
567
|
memory_id=memory_id,
|
|
@@ -536,6 +569,19 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
536
569
|
message="已删除",
|
|
537
570
|
)
|
|
538
571
|
|
|
572
|
+
@staticmethod
|
|
573
|
+
def _confirmed_mutation_response(data: Any) -> bool:
|
|
574
|
+
metadata = data.get("ResponseMetadata", {}) if isinstance(data, dict) else {}
|
|
575
|
+
return bool(
|
|
576
|
+
isinstance(data, dict) and isinstance(metadata, dict)
|
|
577
|
+
and not data.get("Error") and not metadata.get("Error")
|
|
578
|
+
and ("Success" not in data or data["Success"] is True)
|
|
579
|
+
and type(data.get("Code")) is not bool
|
|
580
|
+
and data.get("Code") in (None, 0, "0", 200, "200")
|
|
581
|
+
and isinstance(data.get("RequestId", metadata.get("RequestId")), str)
|
|
582
|
+
and data.get("RequestId", metadata.get("RequestId"))
|
|
583
|
+
)
|
|
584
|
+
|
|
539
585
|
def get_extraction_status(
|
|
540
586
|
self,
|
|
541
587
|
*,
|
|
@@ -547,16 +593,21 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
547
593
|
State 映射 0/50/100/-50/-100;未找到 Session 返回 unknown。
|
|
548
594
|
searchable 需 Service 层结合 ListMemories 确认后置位。
|
|
549
595
|
"""
|
|
550
|
-
item = self.
|
|
596
|
+
item, error_code = self._lookup_session_status(user_id=user_id, session_id=session_id)
|
|
551
597
|
if not isinstance(item, dict):
|
|
552
598
|
return MemoryExtractionStatus(
|
|
553
599
|
session_id=session_id,
|
|
554
600
|
state=None,
|
|
555
601
|
status="unknown",
|
|
556
|
-
message="Session 状态未知",
|
|
602
|
+
message="Session 状态查询未完成" if error_code else "Session 状态未知",
|
|
603
|
+
error_code=error_code,
|
|
557
604
|
)
|
|
558
605
|
state = item.get("State")
|
|
559
|
-
state_int =
|
|
606
|
+
state_int = (
|
|
607
|
+
int(state)
|
|
608
|
+
if isinstance(state, (int, float, str)) and str(state).lstrip("-").isdigit()
|
|
609
|
+
else None
|
|
610
|
+
)
|
|
560
611
|
status = map_session_state(state_int)
|
|
561
612
|
message = {
|
|
562
613
|
"queued": "排队中",
|
|
@@ -617,19 +668,29 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
617
668
|
return ""
|
|
618
669
|
|
|
619
670
|
def _parse_query_records_response(
|
|
620
|
-
self, response: Any, *, user_id: str
|
|
671
|
+
self, response: Any, *, user_id: str, strict: bool = False
|
|
621
672
|
) -> List[LongTermMemoryRecord]:
|
|
622
673
|
"""严格解析 QueryMemorySdk 结构化响应:Data[].Memories[]。"""
|
|
623
674
|
try:
|
|
624
675
|
data = self._parse_json_response(response)
|
|
625
676
|
except (json.JSONDecodeError, TypeError):
|
|
677
|
+
if strict:
|
|
678
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID") from None
|
|
626
679
|
logger.error("QueryMemorySdk records: invalid JSON response")
|
|
627
680
|
return []
|
|
628
681
|
if not isinstance(data, dict):
|
|
682
|
+
if strict:
|
|
683
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID")
|
|
629
684
|
logger.error("QueryMemorySdk records: unexpected payload type")
|
|
630
685
|
return []
|
|
631
686
|
items = data.get("Data")
|
|
687
|
+
if strict and (
|
|
688
|
+
data.get("Error") or data.get("Code") not in (None, 0, "0", 200, "200")
|
|
689
|
+
):
|
|
690
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID")
|
|
632
691
|
if not isinstance(items, list):
|
|
692
|
+
if strict:
|
|
693
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID")
|
|
633
694
|
logger.warning(
|
|
634
695
|
"QueryMemorySdk records: unknown schema, keys=%s; fail closed",
|
|
635
696
|
list(data.keys()),
|
|
@@ -639,11 +700,15 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
639
700
|
for item in items:
|
|
640
701
|
memories = item.get("Memories") if isinstance(item, dict) else None
|
|
641
702
|
if not isinstance(memories, list):
|
|
703
|
+
if strict:
|
|
704
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID")
|
|
642
705
|
continue
|
|
643
706
|
for memory in memories:
|
|
644
707
|
record = self._record_from_item(memory, user_id=user_id)
|
|
645
708
|
if record is not None:
|
|
646
709
|
records.append(record)
|
|
710
|
+
elif strict:
|
|
711
|
+
raise ValueError("MEMORY_SEARCH_RESPONSE_INVALID")
|
|
647
712
|
return records
|
|
648
713
|
|
|
649
714
|
def _parse_list_memories_response(
|
|
@@ -717,38 +782,93 @@ class SdkLTMBackend(BaseLongTermMemoryBackend):
|
|
|
717
782
|
user_id: str,
|
|
718
783
|
session_id: str,
|
|
719
784
|
page_size: int = 20,
|
|
785
|
+
max_pages: int = 20,
|
|
720
786
|
) -> dict[str, Any] | None:
|
|
721
|
-
"""
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
787
|
+
"""Look up a session across bounded pages; preserve legacy raw return shape."""
|
|
788
|
+
item, error_code = self._lookup_session_status(
|
|
789
|
+
user_id=user_id, session_id=session_id, page_size=page_size, max_pages=max_pages
|
|
790
|
+
)
|
|
791
|
+
self.last_error = error_code
|
|
792
|
+
self.last_session_status = dict(item or {})
|
|
793
|
+
return item
|
|
794
|
+
|
|
795
|
+
def _lookup_session_status(
|
|
796
|
+
self, *, user_id: str, session_id: str, page_size: int = 20, max_pages: int = 20
|
|
797
|
+
) -> tuple[dict[str, Any] | None, str]:
|
|
798
|
+
if (type(page_size) is not int or not 1 <= page_size <= 100
|
|
799
|
+
or type(max_pages) is not int or not 1 <= max_pages <= 1000):
|
|
800
|
+
raise ValueError("Invalid memory status pagination budget")
|
|
801
|
+
if not user_id or not session_id:
|
|
802
|
+
return None, "MEMORY_STATUS_IDENTITY_REQUIRED"
|
|
803
|
+
seen: set[str] = set()
|
|
804
|
+
previous_total = None
|
|
734
805
|
try:
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
806
|
+
client = self._get_client()
|
|
807
|
+
collection = self._effective_memory_collection_id()
|
|
808
|
+
for page in range(1, max_pages + 1):
|
|
809
|
+
response = client.call("ListSessions", {
|
|
810
|
+
"MemoryCollectionId": collection, "AgentUserId": user_id,
|
|
811
|
+
"Page": page, "PageSize": page_size,
|
|
812
|
+
}, options={"IsPostJson": True})
|
|
813
|
+
data = self._parse_json_response(response)
|
|
814
|
+
metadata = data.get("ResponseMetadata", {}) if isinstance(data, dict) else {}
|
|
815
|
+
if (
|
|
816
|
+
not isinstance(data, dict) or data.get("Error")
|
|
817
|
+
or not isinstance(metadata, dict) or metadata.get("Error")
|
|
818
|
+
or type(data.get("Code")) is bool
|
|
819
|
+
or data.get("Code") not in (None, 0, "0", 200, "200")
|
|
820
|
+
):
|
|
821
|
+
return None, "MEMORY_STATUS_QUERY_FAILED"
|
|
822
|
+
payload = data.get("Data")
|
|
823
|
+
items = payload.get("Items") if isinstance(payload, dict) else None
|
|
824
|
+
if not isinstance(items, list) or len(items) > page_size or any(
|
|
825
|
+
not isinstance(item, dict) or not isinstance(item.get("SessionId"), str)
|
|
826
|
+
or not item["SessionId"] for item in items
|
|
827
|
+
):
|
|
828
|
+
return None, "MEMORY_STATUS_RESPONSE_INVALID"
|
|
829
|
+
total_count = payload.get("TotalCount")
|
|
830
|
+
total_alias = payload.get("Total")
|
|
831
|
+
if total_count is not None and total_alias is not None:
|
|
832
|
+
normalized_count = (
|
|
833
|
+
int(total_count)
|
|
834
|
+
if isinstance(total_count, str) and total_count.isdigit()
|
|
835
|
+
else total_count
|
|
836
|
+
)
|
|
837
|
+
normalized_alias = (
|
|
838
|
+
int(total_alias)
|
|
839
|
+
if isinstance(total_alias, str) and total_alias.isdigit()
|
|
840
|
+
else total_alias
|
|
841
|
+
)
|
|
842
|
+
if normalized_count != normalized_alias:
|
|
843
|
+
return None, "MEMORY_STATUS_RESPONSE_INVALID"
|
|
844
|
+
total = total_count if total_count is not None else total_alias
|
|
845
|
+
if isinstance(total, str) and total.isdigit():
|
|
846
|
+
total = int(total)
|
|
847
|
+
if total is not None and (type(total) is not int or total < 0):
|
|
848
|
+
return None, "MEMORY_STATUS_RESPONSE_INVALID"
|
|
849
|
+
if page > 1 and total != previous_total:
|
|
850
|
+
return None, "MEMORY_STATUS_DIRECTORY_CHANGED"
|
|
851
|
+
previous_total = total
|
|
852
|
+
ids = [item["SessionId"] for item in items]
|
|
853
|
+
if len(set(ids)) != len(ids) or seen.intersection(ids):
|
|
854
|
+
return None, "MEMORY_STATUS_PAGINATION_REPEATED"
|
|
855
|
+
seen.update(ids)
|
|
856
|
+
for item in items:
|
|
857
|
+
if item["SessionId"] == session_id:
|
|
858
|
+
if (
|
|
859
|
+
item.get("AgentUserId", user_id) != user_id
|
|
860
|
+
or item.get("MemoryCollectionId", collection) != collection
|
|
861
|
+
):
|
|
862
|
+
return None, "MEMORY_STATUS_SCOPE_MISMATCH"
|
|
863
|
+
return dict(item), ""
|
|
864
|
+
if total is not None and len(seen) >= total:
|
|
865
|
+
return None, "" if len(seen) == total else "MEMORY_STATUS_DIRECTORY_CHANGED"
|
|
866
|
+
if len(items) < page_size:
|
|
867
|
+
return None, "" if total is None else "MEMORY_STATUS_DIRECTORY_INCOMPLETE"
|
|
868
|
+
return None, "MEMORY_STATUS_PAGE_BUDGET_EXHAUSTED"
|
|
869
|
+
except Exception:
|
|
870
|
+
logger.warning("ListSessions status query failed")
|
|
871
|
+
return None, "MEMORY_STATUS_QUERY_FAILED"
|
|
752
872
|
|
|
753
873
|
def _parse_query_response(self, response: str) -> list[str]:
|
|
754
874
|
"""解析 QueryMemorySdk 响应
|
|
@@ -38,11 +38,11 @@ class ResilientADKSessionService(BaseSessionService):
|
|
|
38
38
|
return
|
|
39
39
|
self._primary_enabled = False
|
|
40
40
|
logger.error(
|
|
41
|
-
"ADK session persistence degraded; using in-memory live session
|
|
42
|
-
exc,
|
|
41
|
+
"ADK session persistence degraded; using in-memory live session",
|
|
43
42
|
extra={
|
|
44
43
|
"session_backend_state": "degraded",
|
|
45
44
|
"session_backend": type(self.primary).__name__,
|
|
45
|
+
"session_backend_reason_code": "SESSION_STORE_UNREACHABLE",
|
|
46
46
|
},
|
|
47
47
|
)
|
|
48
48
|
self._start_probe()
|
|
@@ -63,22 +63,30 @@ class ResilientADKSessionService(BaseSessionService):
|
|
|
63
63
|
await asyncio.sleep(self._probe_interval_seconds)
|
|
64
64
|
if self._primary_enabled:
|
|
65
65
|
break
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
77
|
-
extra={
|
|
78
|
-
"session_backend_state": "recovered",
|
|
79
|
-
"session_backend": type(self.primary).__name__,
|
|
80
|
-
},
|
|
66
|
+
await self.refresh_persistence_capability()
|
|
67
|
+
|
|
68
|
+
async def refresh_persistence_capability(self) -> bool:
|
|
69
|
+
"""Probe a degraded ADK database service without rebuilding the runner."""
|
|
70
|
+
if self._primary_enabled:
|
|
71
|
+
return True
|
|
72
|
+
try:
|
|
73
|
+
await self.primary.get_session(
|
|
74
|
+
app_name="__ksadk_probe__",
|
|
75
|
+
user_id="__ksadk_probe__",
|
|
76
|
+
session_id="__ksadk_probe__",
|
|
81
77
|
)
|
|
78
|
+
except Exception:
|
|
79
|
+
return False
|
|
80
|
+
self._primary_enabled = True
|
|
81
|
+
logger.info(
|
|
82
|
+
"ADK session persistence recovered; durable backend re-enabled",
|
|
83
|
+
extra={
|
|
84
|
+
"session_backend_state": "recovered",
|
|
85
|
+
"session_backend": type(self.primary).__name__,
|
|
86
|
+
"session_backend_reason_code": "READY",
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
return True
|
|
82
90
|
|
|
83
91
|
@staticmethod
|
|
84
92
|
def _key(app_name: str, user_id: str, session_id: str) -> tuple[str, str, str]:
|
|
@@ -33,6 +33,7 @@ from ksadk.compat.adk_compat import (
|
|
|
33
33
|
InMemorySessionService,
|
|
34
34
|
Session,
|
|
35
35
|
)
|
|
36
|
+
from ksadk.sessions.topology import StorageTarget, resolve_persistence_topology
|
|
36
37
|
|
|
37
38
|
logger = logging.getLogger(__name__)
|
|
38
39
|
|
|
@@ -55,14 +56,20 @@ def _normalize_backend_name(backend: str) -> str:
|
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
def _normalize_database_url(db_url: str) -> str:
|
|
58
|
-
"""Normalize
|
|
59
|
+
"""Normalize database URLs for google.adk DatabaseSessionService.
|
|
59
60
|
|
|
60
|
-
ADK uses SQLAlchemy async engines underneath, so plain
|
|
61
|
-
URLs
|
|
61
|
+
ADK uses SQLAlchemy async engines underneath, so plain PostgreSQL and
|
|
62
|
+
SQLite URLs need their corresponding async driver schemes.
|
|
62
63
|
"""
|
|
63
64
|
normalized = str(db_url or "").strip()
|
|
64
65
|
if not normalized:
|
|
65
66
|
return ""
|
|
67
|
+
if normalized.startswith("postgresql+asyncpg:"):
|
|
68
|
+
return normalized
|
|
69
|
+
if normalized.startswith("postgresql:"):
|
|
70
|
+
return "postgresql+asyncpg:" + normalized[len("postgresql:") :]
|
|
71
|
+
if normalized.startswith("postgres:"):
|
|
72
|
+
return "postgresql+asyncpg:" + normalized[len("postgres:") :]
|
|
66
73
|
if normalized.startswith("sqlite+aiosqlite:"):
|
|
67
74
|
return normalized
|
|
68
75
|
if normalized.startswith("sqlite:"):
|
|
@@ -159,9 +166,7 @@ class ShortTermMemory(BaseModel):
|
|
|
159
166
|
self._session_service = ResilientADKSessionService(
|
|
160
167
|
DatabaseSessionService(db_url=normalized_db_url, **service_kwargs)
|
|
161
168
|
)
|
|
162
|
-
logger.info(
|
|
163
|
-
f"ShortTermMemory: using DatabaseSessionService " f"({normalized_db_url[:30]}...)"
|
|
164
|
-
)
|
|
169
|
+
logger.info("ShortTermMemory: using DatabaseSessionService")
|
|
165
170
|
except ImportError:
|
|
166
171
|
logger.warning(
|
|
167
172
|
"DatabaseSessionService not available. "
|
|
@@ -170,10 +175,11 @@ class ShortTermMemory(BaseModel):
|
|
|
170
175
|
)
|
|
171
176
|
self._session_service = InMemorySessionService()
|
|
172
177
|
self.backend = "local"
|
|
173
|
-
except Exception as
|
|
178
|
+
except Exception as exc:
|
|
174
179
|
logger.error(
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
"Failed to create DatabaseSessionService (%s); "
|
|
181
|
+
"falling back to InMemorySessionService.",
|
|
182
|
+
type(exc).__name__,
|
|
177
183
|
)
|
|
178
184
|
self._session_service = InMemorySessionService()
|
|
179
185
|
self.backend = "local"
|
|
@@ -237,6 +243,13 @@ class ShortTermMemory(BaseModel):
|
|
|
237
243
|
logger.error(f"Failed to create session: {e}")
|
|
238
244
|
return None
|
|
239
245
|
|
|
246
|
+
@classmethod
|
|
247
|
+
def from_persistence_target(cls, target: StorageTarget) -> "ShortTermMemory":
|
|
248
|
+
"""Build ADK-native state from an effective Checkpoint storage target."""
|
|
249
|
+
if target.backend == "postgres" and target.dsn:
|
|
250
|
+
return cls(backend="database", db_url=_normalize_database_url(target.dsn))
|
|
251
|
+
return cls(backend="local")
|
|
252
|
+
|
|
240
253
|
@classmethod
|
|
241
254
|
def from_env(cls) -> "ShortTermMemory":
|
|
242
255
|
"""从环境变量创建 ShortTermMemory
|
|
@@ -251,6 +264,10 @@ class ShortTermMemory(BaseModel):
|
|
|
251
264
|
KSADK_SESSION_BACKEND: 统一 session backend fallback
|
|
252
265
|
KSADK_SESSION_DSN: 统一 session DSN fallback
|
|
253
266
|
"""
|
|
267
|
+
topology = resolve_persistence_topology(framework="adk")
|
|
268
|
+
if topology.checkpoint.backend == "postgres" and topology.checkpoint.dsn:
|
|
269
|
+
return cls.from_persistence_target(topology.checkpoint)
|
|
270
|
+
|
|
254
271
|
explicit_backend = _normalize_backend_name(
|
|
255
272
|
_env_first(
|
|
256
273
|
"KSADK_ADK_SESSION_BACKEND",
|