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.
Files changed (509) hide show
  1. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
  2. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
  3. ksadk/_build_provenance.json +1 -1
  4. ksadk/api/client.py +105 -91
  5. ksadk/builders/code_builder.py +36 -9
  6. ksadk/builders/framework_requirements.py +2 -1
  7. ksadk/builders/ks3_uploader.py +36 -7
  8. ksadk/builders/managed_runtime_builder.py +1 -0
  9. ksadk/cli/__init__.py +32 -3
  10. ksadk/cli/cmd_managed_runtime.py +13 -1
  11. ksadk/cli/cmd_plugin.py +6 -1
  12. ksadk/cli/cmd_web.py +2 -5
  13. ksadk/cli/runtime_bootstrap.py +23 -1
  14. ksadk/codex/client.py +424 -96
  15. ksadk/codex/projection.py +24 -0
  16. ksadk/codex/runtime.py +56 -298
  17. ksadk/common/auth.py +16 -10
  18. ksadk/configs/env_registry.py +29 -1
  19. ksadk/conversations/message_projection.py +135 -14
  20. ksadk/conversations/projector.py +4 -6
  21. ksadk/conversations/runtime_invocation.py +5 -0
  22. ksadk/conversations/runtime_payloads.py +1 -0
  23. ksadk/conversations/runtime_preparation.py +30 -27
  24. ksadk/conversations/runtime_resume.py +50 -2
  25. ksadk/conversations/runtime_stream_events.py +5 -0
  26. ksadk/conversations/runtime_streaming.py +25 -7
  27. ksadk/deployment/env_forward.py +2 -2
  28. ksadk/deployment/providers/serverless.py +1 -1
  29. ksadk/events/adapters/_codex_validators.py +18 -7
  30. ksadk/events/adapters/langgraph.py +15 -1
  31. ksadk/events/canonical_store.py +3 -1
  32. ksadk/events/projections.py +1 -1
  33. ksadk/harness/config.py +2 -2
  34. ksadk/harness/runtime.py +27 -27
  35. ksadk/harness/tools.py +38 -13
  36. ksadk/interaction/provider.py +1 -0
  37. ksadk/interaction/providers/langgraph.py +1 -0
  38. ksadk/kernel/bootstrap.py +28 -4
  39. ksadk/kernel/ingress.py +15 -2
  40. ksadk/kernel/sqlite_store.py +27 -0
  41. ksadk/kernel/store.py +3 -0
  42. ksadk/kernel/worker.py +65 -10
  43. ksadk/knowledge_base/client.py +57 -27
  44. ksadk/mcp_runtime/__init__.py +12 -4
  45. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  46. ksadk/memory/adk/resilient_session_service.py +25 -17
  47. ksadk/memory/adk/short_term_memory.py +26 -9
  48. ksadk/memory/models.py +7 -4
  49. ksadk/memory/provider_resolver.py +3 -0
  50. ksadk/model_proxy/server.py +10 -5
  51. ksadk/plugins/__init__.py +4 -0
  52. ksadk/plugins/artifacts.py +275 -0
  53. ksadk/plugins/bridges/__init__.py +4 -2
  54. ksadk/plugins/bridges/codex.py +120 -13
  55. ksadk/plugins/bridges/dsh.py +340 -156
  56. ksadk/plugins/builtins.py +35 -36
  57. ksadk/plugins/bundle_security.py +28 -4
  58. ksadk/plugins/codex_manifest.py +983 -0
  59. ksadk/plugins/composition.py +8 -0
  60. ksadk/plugins/contracts.py +118 -0
  61. ksadk/plugins/delivery.py +153 -0
  62. ksadk/plugins/dsh_installation_digest.py +71 -0
  63. ksadk/plugins/dsh_toolchain.py +110 -21
  64. ksadk/plugins/ecosystem_probe.py +6 -6
  65. ksadk/plugins/host.py +102 -39
  66. ksadk/plugins/kernel_adapter.py +205 -0
  67. ksadk/plugins/providers/__init__.py +23 -0
  68. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  69. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  70. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  71. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  72. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  73. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  74. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  75. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  76. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  77. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  78. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  79. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  80. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  81. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  82. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  83. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  84. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  85. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  86. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  87. ksadk/plugins/providers/codex.py +335 -69
  88. ksadk/plugins/providers/codex_native.py +368 -0
  89. ksadk/plugins/providers/codex_turn.py +301 -0
  90. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  91. ksadk/plugins/providers/dsh_mcp.py +467 -0
  92. ksadk/plugins/providers/harness.py +118 -113
  93. ksadk/plugins/providers/mcp_projection.py +150 -0
  94. ksadk/plugins/providers/platform_resources.py +657 -0
  95. ksadk/plugins/resolver.py +8 -1
  96. ksadk/resource_runtime/__init__.py +4 -0
  97. ksadk/resource_runtime/broker.py +616 -0
  98. ksadk/resource_runtime/build_artifacts.py +165 -0
  99. ksadk/resource_runtime/contracts.py +138 -0
  100. ksadk/resource_runtime/discovery_receipts.py +100 -0
  101. ksadk/resource_runtime/discovery_skills.py +172 -0
  102. ksadk/resource_runtime/errors.py +6 -0
  103. ksadk/resource_runtime/ipc.py +142 -0
  104. ksadk/resource_runtime/kernel_approval.py +165 -0
  105. ksadk/resource_runtime/knowledge.py +114 -0
  106. ksadk/resource_runtime/langgraph.py +94 -0
  107. ksadk/resource_runtime/leases.py +191 -0
  108. ksadk/resource_runtime/managed_projection.py +186 -0
  109. ksadk/resource_runtime/mcp_server.py +138 -0
  110. ksadk/resource_runtime/memory_provider.py +318 -0
  111. ksadk/resource_runtime/memory_receipts.py +34 -0
  112. ksadk/resource_runtime/operation_ledger.py +211 -0
  113. ksadk/resource_runtime/plugin_config.py +48 -0
  114. ksadk/resource_runtime/policy_authorization.py +54 -0
  115. ksadk/resource_runtime/process.py +110 -0
  116. ksadk/resource_runtime/skill_artifacts.py +153 -0
  117. ksadk/resource_runtime/skill_runtime.py +42 -0
  118. ksadk/resource_runtime/skill_workspace.py +118 -0
  119. ksadk/resource_runtime/skills.py +215 -0
  120. ksadk/resource_runtime/snapshots.py +180 -0
  121. ksadk/resource_runtime/socket_server.py +103 -0
  122. ksadk/resource_runtime/supervisor.py +380 -0
  123. ksadk/resource_runtime/worker.py +504 -0
  124. ksadk/runners/_langgraph_runner_streams.py +74 -6
  125. ksadk/runners/adk_runner.py +149 -11
  126. ksadk/runners/base_runner.py +29 -1
  127. ksadk/runners/langgraph_runner.py +475 -145
  128. ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
  129. ksadk/runtime/adapter.py +2 -0
  130. ksadk/runtime/conversation_execution.py +92 -16
  131. ksadk/runtime/executor.py +78 -2
  132. ksadk/runtime/factory.py +29 -273
  133. ksadk/runtime/framework_adapters.py +23 -0
  134. ksadk/runtime/preprocessing.py +10 -2
  135. ksadk/runtime/runner_adapter.py +73 -14
  136. ksadk/runtime_context.py +40 -2
  137. ksadk/sandbox/backends/e2b.py +52 -11
  138. ksadk/sandbox/backends/local_process.py +9 -0
  139. ksadk/sandbox/base.py +2 -0
  140. ksadk/sandbox/e2b_connection.py +66 -0
  141. ksadk/scheduler/sqlite_store.py +18 -0
  142. ksadk/server/composition.py +2 -0
  143. ksadk/server/factory.py +5 -0
  144. ksadk/server/persistence_capability.py +516 -0
  145. ksadk/server/routes/control.py +210 -46
  146. ksadk/server/routes/dependencies.py +15 -0
  147. ksadk/server/routes/models.py +47 -4
  148. ksadk/server/routes/projection.py +252 -12
  149. ksadk/server/routes/sessions.py +284 -107
  150. ksadk/server/routes/streaming.py +43 -9
  151. ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  152. ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
  153. ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  154. ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  155. ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  156. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  157. ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
  158. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  159. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  160. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  161. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  162. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  163. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  164. ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  165. ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  166. ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  167. ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  168. ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  169. ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  170. ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  171. ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  172. ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  173. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  174. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  175. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  176. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  177. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  178. ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  179. ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
  180. ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  181. ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  182. ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  183. ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  184. ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  185. ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
  186. ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
  187. ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
  188. ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
  189. ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
  190. ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
  191. ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
  192. ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
  193. ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
  194. ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
  195. ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
  196. ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
  197. ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
  198. ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
  199. ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
  200. ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
  201. ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
  202. ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
  203. ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
  204. ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
  205. ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
  206. ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
  207. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  208. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  209. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  210. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  211. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  212. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  213. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  214. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  215. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  216. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  217. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  218. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  219. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  220. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  221. ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
  222. ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
  223. ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  224. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  225. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  226. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  227. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  228. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  229. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  230. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  231. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  232. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  233. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  234. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  235. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  236. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  237. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  238. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  239. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  240. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  241. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  242. ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  243. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  244. ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  245. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  246. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  247. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  248. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  249. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  250. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  251. ksadk/server/static/index.html +2 -2
  252. ksadk/session_context.py +66 -0
  253. ksadk/sessions/__init__.py +11 -21
  254. ksadk/sessions/_local_service_sync.py +263 -1
  255. ksadk/sessions/base.py +176 -0
  256. ksadk/sessions/errors.py +4 -0
  257. ksadk/sessions/in_memory.py +309 -19
  258. ksadk/sessions/local_service.py +83 -1
  259. ksadk/sessions/persistence.py +275 -0
  260. ksadk/sessions/postgres_service.py +358 -0
  261. ksadk/sessions/resilience.py +8 -0
  262. ksadk/sessions/resilient.py +362 -4
  263. ksadk/sessions/topology.py +135 -0
  264. ksadk/skills/models.py +26 -4
  265. ksadk/skills/package_store.py +186 -38
  266. ksadk/skills/runtime/agent.py +31 -6
  267. ksadk/skills/runtime/artifact_delivery.py +139 -0
  268. ksadk/skills/runtime/backends/e2b.py +98 -6
  269. ksadk/skills/runtime/backends/local.py +73 -8
  270. ksadk/skills/runtime/base.py +3 -0
  271. ksadk/skills/runtime/executor.py +2 -0
  272. ksadk/skills/runtime/loader.py +10 -2
  273. ksadk/skills/runtime/pinned.py +114 -0
  274. ksadk/skills/runtime/request.py +31 -0
  275. ksadk/skills/service_client.py +167 -28
  276. ksadk/studio/api.py +224 -42
  277. ksadk/studio/api_catalog_routes.py +18 -0
  278. ksadk/studio/api_plugin_routes.py +526 -95
  279. ksadk/studio/api_resource_connections.py +183 -0
  280. ksadk/studio/authoring_coordinator.py +19 -14
  281. ksadk/studio/builder.py +76 -0
  282. ksadk/studio/cloud.py +342 -104
  283. ksadk/studio/cloud_shared_web.py +565 -0
  284. ksadk/studio/codex_agent_service.py +128 -26
  285. ksadk/studio/codex_builder.py +241 -2
  286. ksadk/studio/codex_credentials.py +90 -0
  287. ksadk/studio/codex_manifest.py +31 -4
  288. ksadk/studio/codex_plugin_store.py +746 -0
  289. ksadk/studio/codex_provider_build.py +231 -0
  290. ksadk/studio/codex_run.py +184 -25
  291. ksadk/studio/compatibility_report.py +12 -1
  292. ksadk/studio/compiler.py +78 -14
  293. ksadk/studio/contracts.py +132 -6
  294. ksadk/studio/dsh_application.py +137 -0
  295. ksadk/studio/dsh_capability_service.py +1107 -0
  296. ksadk/studio/dsh_models.py +59 -0
  297. ksadk/studio/dsh_provider_registration.py +320 -13
  298. ksadk/studio/hosted_kernel.py +88 -13
  299. ksadk/studio/mcp_runtime.py +11 -3
  300. ksadk/studio/model_client.py +2 -2
  301. ksadk/studio/plugin_composition.py +190 -23
  302. ksadk/studio/plugin_kernel_adapter.py +12 -112
  303. ksadk/studio/plugin_runtime.py +224 -45
  304. ksadk/studio/resource_authority.py +637 -0
  305. ksadk/studio/resource_binding_validation.py +77 -0
  306. ksadk/studio/resource_build_admission.py +196 -0
  307. ksadk/studio/resource_build_materializer.py +149 -0
  308. ksadk/studio/resource_catalog.py +143 -2
  309. ksadk/studio/resource_connections.py +220 -0
  310. ksadk/studio/run_service.py +462 -52
  311. ksadk/studio/runtime_source.py +15 -7
  312. ksadk/studio/scheduler_assistant.py +317 -0
  313. ksadk/studio/scheduler_runtime.py +9 -0
  314. ksadk/studio/scheduler_service.py +3 -0
  315. ksadk/studio/service.py +490 -44
  316. ksadk/studio/shared_web.py +446 -62
  317. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  318. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  319. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  320. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  321. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  322. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  323. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  324. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  325. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  326. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  327. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  328. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  329. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  330. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  331. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  332. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  333. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  334. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  335. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  336. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  337. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  338. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  339. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  340. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  341. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  342. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  343. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  344. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  345. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  346. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  347. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  348. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  349. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  350. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  351. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  352. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  353. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  354. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  355. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  356. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  357. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  358. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  359. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  360. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  361. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  362. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  363. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  364. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  365. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  366. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  367. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  368. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  369. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  372. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  373. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  377. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  378. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  379. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  380. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  381. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  382. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  383. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  384. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  385. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  386. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  387. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  388. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  389. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  390. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  391. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  392. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  393. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  394. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  395. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  396. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  397. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  398. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  399. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  400. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  401. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  402. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  403. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  404. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  405. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  406. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  407. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  408. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  409. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  410. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  411. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  412. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  413. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  414. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  415. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  416. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  417. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  418. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  419. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  420. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  421. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  422. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  423. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  424. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  425. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  426. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  427. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  428. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  429. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  430. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  431. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  432. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  433. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  434. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  435. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  436. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  437. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  438. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  439. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  440. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  441. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  442. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  443. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  444. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  445. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  446. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  447. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  448. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  449. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  450. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  451. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  452. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  453. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  454. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  455. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  456. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  457. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  458. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  459. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  460. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  461. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  462. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  463. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  464. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  465. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  466. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  467. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  468. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  469. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  470. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  471. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  472. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  473. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  474. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  475. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  476. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  477. ksadk/studio/static/index.html +2 -2
  478. ksadk/version.py +1 -1
  479. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
  480. ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
  481. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
  482. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
  483. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
  484. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
  485. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
  486. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
  487. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
  488. ksadk/server/static/assets/index-B2k_urY8.js +0 -241
  489. ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
  490. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
  491. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
  492. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
  493. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
  494. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
  495. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
  496. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
  497. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
  498. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
  499. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
  500. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
  501. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
  502. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
  503. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  504. ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
  505. ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
  506. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  507. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  508. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  509. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
@@ -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
- self._aicp_client = aicp_module.AicpClient(cred, self.region, profile=client_profile)
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.info(
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 = f"Failed to parse response: {str(response)[:200]}"
196
- logger.error(f"Failed to parse response: {str(response)[:200]}")
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
- records = data.get("Records", [])
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.info(
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(f"Knowledge base search failed: {e}")
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 " "to enable knowledge base."
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
- os.environ.get("KSADK_KB_SESSION_TOKEN")
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", "")
@@ -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 StreamableHTTPConnectionParams(**kwargs)
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.*不存在|记忆不存在|记忆已被删除|resourcenotfound|notfound",
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
- self._aicp_client = aicp_module.AicpClient(cred, self.region, profile=client_profile)
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(f"CreateMemorySdk failed: {e}")
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(response, user_id=user_id)
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 response_memory_id or response_memory_id == memory_id:
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.get_session_status(user_id=user_id, session_id=session_id)
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 = int(state) if isinstance(state, (int, float, str)) and str(state).lstrip("-").isdigit() else None
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
- """Return raw AICP session status for a recently submitted memory session."""
722
- if not session_id:
723
- return None
724
-
725
- client = self._get_client()
726
- memory_collection_id = self._effective_memory_collection_id()
727
- params = {
728
- "MemoryCollectionId": memory_collection_id,
729
- "AgentUserId": user_id,
730
- "Page": 1,
731
- "PageSize": page_size,
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
- response = client.call("ListSessions", params, options={"IsPostJson": True})
736
- data = self._parse_json_response(response)
737
- except Exception as e:
738
- self.last_error = str(e)
739
- logger.warning(f"ListSessions failed while checking memory status: {e}")
740
- return None
741
-
742
- payload = data.get("Data") if isinstance(data, dict) else None
743
- items = payload.get("Items") if isinstance(payload, dict) else None
744
- if not isinstance(items, list):
745
- return None
746
-
747
- for item in items:
748
- if isinstance(item, dict) and item.get("SessionId") == session_id:
749
- self.last_session_status = item
750
- return item
751
- return None
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: %s",
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
- try:
67
- await self.primary.get_session(
68
- app_name="__ksadk_probe__",
69
- user_id="__ksadk_probe__",
70
- session_id="__ksadk_probe__",
71
- )
72
- except Exception:
73
- continue
74
- self._primary_enabled = True
75
- logger.info(
76
- "ADK session persistence recovered; durable backend re-enabled",
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 sqlite URLs for google.adk DatabaseSessionService.
59
+ """Normalize database URLs for google.adk DatabaseSessionService.
59
60
 
60
- ADK uses SQLAlchemy async engines underneath, so plain `sqlite:///...`
61
- URLs fail while `sqlite+aiosqlite:///...` works.
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 e:
178
+ except Exception as exc:
174
179
  logger.error(
175
- f"Failed to create DatabaseSessionService: {e}. "
176
- f"Falling back to InMemorySessionService."
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",