agentengine-sdk-python 0.8.2__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 (563) hide show
  1. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +22 -28
  2. agentengine_sdk_python-0.8.4.dist-info/RECORD +1070 -0
  3. ksadk/_build_provenance.json +1 -0
  4. ksadk/agui/_agent_helpers.py +4 -0
  5. ksadk/api/client.py +108 -91
  6. ksadk/builders/code_builder.py +36 -9
  7. ksadk/builders/framework_requirements.py +2 -1
  8. ksadk/builders/ks3_uploader.py +36 -7
  9. ksadk/builders/managed_runtime_builder.py +4 -0
  10. ksadk/cli/__init__.py +38 -3
  11. ksadk/cli/cmd_managed_runtime.py +13 -1
  12. ksadk/cli/cmd_plugin.py +662 -0
  13. ksadk/cli/cmd_web.py +2 -5
  14. ksadk/cli/runtime_bootstrap.py +23 -1
  15. ksadk/codex/client.py +424 -96
  16. ksadk/codex/projection.py +24 -0
  17. ksadk/codex/runtime.py +83 -283
  18. ksadk/common/auth.py +16 -10
  19. ksadk/configs/env_registry.py +59 -3
  20. ksadk/configs/settings.py +9 -0
  21. ksadk/context_engine/contributors.py +73 -8
  22. ksadk/conversations/__init__.py +19 -0
  23. ksadk/conversations/context.py +104 -24
  24. ksadk/conversations/contracts.py +266 -0
  25. ksadk/conversations/message_projection.py +154 -15
  26. ksadk/conversations/projector.py +614 -0
  27. ksadk/conversations/reducer.py +98 -0
  28. ksadk/conversations/runtime_invocation.py +5 -0
  29. ksadk/conversations/runtime_payloads.py +1 -0
  30. ksadk/conversations/runtime_preparation.py +30 -27
  31. ksadk/conversations/runtime_resume.py +50 -2
  32. ksadk/conversations/runtime_stream_events.py +5 -0
  33. ksadk/conversations/runtime_streaming.py +25 -7
  34. ksadk/deployment/env_forward.py +2 -2
  35. ksadk/deployment/providers/serverless.py +1 -1
  36. ksadk/events/_v1_compat/projection.py +2 -0
  37. ksadk/events/adapters/_codex_validators.py +18 -7
  38. ksadk/events/adapters/codex.py +190 -0
  39. ksadk/events/adapters/langgraph.py +15 -1
  40. ksadk/events/canonical_store.py +3 -1
  41. ksadk/events/projections.py +1 -1
  42. ksadk/harness/__init__.py +45 -35
  43. ksadk/harness/config.py +2 -2
  44. ksadk/harness/runtime.py +75 -16
  45. ksadk/harness/tools.py +38 -13
  46. ksadk/interaction/provider.py +1 -0
  47. ksadk/interaction/providers/langgraph.py +1 -0
  48. ksadk/kernel/bootstrap.py +28 -4
  49. ksadk/kernel/contract_fingerprints.py +5 -4
  50. ksadk/kernel/contracts.py +8 -0
  51. ksadk/kernel/control.py +1 -0
  52. ksadk/kernel/ingress.py +36 -2
  53. ksadk/kernel/memory_store.py +1 -0
  54. ksadk/kernel/postgres_store.py +1 -0
  55. ksadk/kernel/sqlite_store.py +28 -0
  56. ksadk/kernel/store.py +3 -0
  57. ksadk/kernel/worker.py +76 -10
  58. ksadk/knowledge_base/client.py +57 -27
  59. ksadk/mcp_runtime/__init__.py +12 -4
  60. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  61. ksadk/memory/adk/resilient_session_service.py +25 -17
  62. ksadk/memory/adk/short_term_memory.py +26 -9
  63. ksadk/memory/models.py +7 -4
  64. ksadk/memory/provider_resolver.py +3 -0
  65. ksadk/memory/providers/local_sqlite.py +7 -0
  66. ksadk/model_proxy/server.py +10 -5
  67. ksadk/plugins/__init__.py +171 -0
  68. ksadk/plugins/artifacts.py +275 -0
  69. ksadk/plugins/bridges/__init__.py +47 -0
  70. ksadk/plugins/bridges/codex.py +659 -0
  71. ksadk/plugins/bridges/dsh.py +1300 -0
  72. ksadk/plugins/builtins.py +746 -0
  73. ksadk/plugins/bundle.py +246 -0
  74. ksadk/plugins/bundle_security.py +191 -0
  75. ksadk/plugins/codex_manifest.py +983 -0
  76. ksadk/plugins/composition.py +537 -0
  77. ksadk/plugins/context_contributor.py +437 -0
  78. ksadk/plugins/contracts.py +569 -0
  79. ksadk/plugins/delivery.py +153 -0
  80. ksadk/plugins/dsh_installation_digest.py +71 -0
  81. ksadk/plugins/dsh_toolchain.py +1024 -0
  82. ksadk/plugins/ecosystem_bridge.py +1105 -0
  83. ksadk/plugins/ecosystem_probe.py +191 -0
  84. ksadk/plugins/host.py +787 -0
  85. ksadk/plugins/kernel_adapter.py +205 -0
  86. ksadk/plugins/providers/__init__.py +108 -0
  87. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  88. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  89. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  90. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  91. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  92. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  93. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  94. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  95. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  96. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  97. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  98. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  99. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  100. ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
  101. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
  102. ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
  103. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  104. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
  105. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  106. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
  107. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
  108. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  109. ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
  110. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
  111. ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
  112. ksadk/plugins/providers/codex.py +988 -0
  113. ksadk/plugins/providers/codex_dsh.py +83 -0
  114. ksadk/plugins/providers/codex_native.py +368 -0
  115. ksadk/plugins/providers/codex_turn.py +301 -0
  116. ksadk/plugins/providers/dsh.py +951 -0
  117. ksadk/plugins/providers/dsh_capabilities.py +1389 -0
  118. ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
  119. ksadk/plugins/providers/dsh_mcp.py +467 -0
  120. ksadk/plugins/providers/harness.py +632 -0
  121. ksadk/plugins/providers/harness_dsh.py +91 -0
  122. ksadk/plugins/providers/legacy.py +215 -0
  123. ksadk/plugins/providers/legacy_catalog.py +100 -0
  124. ksadk/plugins/providers/mcp_projection.py +150 -0
  125. ksadk/plugins/providers/platform_resources.py +657 -0
  126. ksadk/plugins/providers/shipped_dsh.py +370 -0
  127. ksadk/plugins/resolver.py +338 -0
  128. ksadk/plugins/subagent_providers/__init__.py +12 -0
  129. ksadk/plugins/subagent_providers/codex.py +443 -0
  130. ksadk/plugins/subagents.py +333 -0
  131. ksadk/resource_runtime/__init__.py +4 -0
  132. ksadk/resource_runtime/broker.py +616 -0
  133. ksadk/resource_runtime/build_artifacts.py +165 -0
  134. ksadk/resource_runtime/contracts.py +138 -0
  135. ksadk/resource_runtime/discovery_receipts.py +100 -0
  136. ksadk/resource_runtime/discovery_skills.py +172 -0
  137. ksadk/resource_runtime/errors.py +6 -0
  138. ksadk/resource_runtime/ipc.py +142 -0
  139. ksadk/resource_runtime/kernel_approval.py +165 -0
  140. ksadk/resource_runtime/knowledge.py +114 -0
  141. ksadk/resource_runtime/langgraph.py +94 -0
  142. ksadk/resource_runtime/leases.py +191 -0
  143. ksadk/resource_runtime/managed_projection.py +186 -0
  144. ksadk/resource_runtime/mcp_server.py +138 -0
  145. ksadk/resource_runtime/memory_provider.py +318 -0
  146. ksadk/resource_runtime/memory_receipts.py +34 -0
  147. ksadk/resource_runtime/operation_ledger.py +211 -0
  148. ksadk/resource_runtime/plugin_config.py +48 -0
  149. ksadk/resource_runtime/policy_authorization.py +54 -0
  150. ksadk/resource_runtime/process.py +110 -0
  151. ksadk/resource_runtime/skill_artifacts.py +153 -0
  152. ksadk/resource_runtime/skill_runtime.py +42 -0
  153. ksadk/resource_runtime/skill_workspace.py +118 -0
  154. ksadk/resource_runtime/skills.py +215 -0
  155. ksadk/resource_runtime/snapshots.py +180 -0
  156. ksadk/resource_runtime/socket_server.py +103 -0
  157. ksadk/resource_runtime/supervisor.py +380 -0
  158. ksadk/resource_runtime/worker.py +504 -0
  159. ksadk/runners/_langgraph_runner_streams.py +74 -6
  160. ksadk/runners/adk_runner.py +149 -11
  161. ksadk/runners/base_runner.py +29 -1
  162. ksadk/runners/langgraph_runner.py +475 -145
  163. ksadk/runtime/_runner_adapter/stream_mapping.py +193 -60
  164. ksadk/runtime/adapter.py +3 -0
  165. ksadk/runtime/conversation_execution.py +92 -16
  166. ksadk/runtime/executor.py +78 -2
  167. ksadk/runtime/factory.py +30 -200
  168. ksadk/runtime/framework_adapters.py +41 -0
  169. ksadk/runtime/preprocessing.py +10 -2
  170. ksadk/runtime/runner_adapter.py +78 -14
  171. ksadk/runtime_context.py +40 -2
  172. ksadk/sandbox/__init__.py +2 -1
  173. ksadk/sandbox/backends/e2b.py +52 -11
  174. ksadk/sandbox/backends/local_process.py +9 -0
  175. ksadk/sandbox/base.py +2 -0
  176. ksadk/sandbox/e2b_connection.py +66 -0
  177. ksadk/sandbox/factory.py +72 -0
  178. ksadk/scheduler/__init__.py +18 -0
  179. ksadk/scheduler/calendar.py +102 -0
  180. ksadk/scheduler/contracts.py +254 -0
  181. ksadk/scheduler/dispatcher.py +129 -0
  182. ksadk/scheduler/engine.py +416 -0
  183. ksadk/scheduler/sqlite_store.py +581 -0
  184. ksadk/server/composition.py +2 -0
  185. ksadk/server/factory.py +5 -0
  186. ksadk/server/persistence_capability.py +516 -0
  187. ksadk/server/routes/control.py +210 -46
  188. ksadk/server/routes/dependencies.py +15 -0
  189. ksadk/server/routes/models.py +47 -4
  190. ksadk/server/routes/projection.py +252 -12
  191. ksadk/server/routes/sessions.py +284 -107
  192. ksadk/server/routes/streaming.py +43 -9
  193. ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
  194. ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-b4C7upmO.js} +3 -3
  195. ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
  196. ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock-BEBN4Ksz.js} +6 -6
  197. ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
  198. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
  199. ksadk/server/static/assets/{arc-C4FzinUA.js → arc-bTohInsS.js} +1 -1
  200. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
  201. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
  202. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
  203. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
  204. ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
  205. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
  206. ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
  207. ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
  208. ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
  209. ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
  210. ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
  211. ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
  212. ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
  213. ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
  214. ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
  215. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
  216. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
  217. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
  218. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
  219. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
  220. ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
  221. ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-UBpgon5q.js} +1 -1
  222. ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
  223. ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
  224. ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
  225. ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
  226. ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
  227. ksadk/server/static/assets/{dist-B7seoj3d.js → dist-B2_CVgKv.js} +1 -1
  228. ksadk/server/static/assets/{dist-CSh_DE14.js → dist-B3FR1SKK.js} +1 -1
  229. ksadk/server/static/assets/{dist-DUX-id_F.js → dist-BIr4DSRq.js} +1 -1
  230. ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-BgV_owcB.js} +1 -1
  231. ksadk/server/static/assets/{dist-W-TIVntx.js → dist-Bj730Ib4.js} +1 -1
  232. ksadk/server/static/assets/{dist-BytlxIDT.js → dist-BnaTiyzN.js} +1 -1
  233. ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C1NMAY5a.js} +1 -1
  234. ksadk/server/static/assets/{dist-dDdADKFA.js → dist-C5_ZAZsG.js} +1 -1
  235. ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-CB9iJrvg.js} +1 -1
  236. ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-CFzsn6BG.js} +1 -1
  237. ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-Cf125P_m.js} +1 -1
  238. ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-ClYUxfeK.js} +1 -1
  239. ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DFD6Qa6T.js} +1 -1
  240. ksadk/server/static/assets/{dist-BX8z72IC.js → dist-DVCOWtha.js} +1 -1
  241. ksadk/server/static/assets/{dist-dydu68Fl.js → dist-D_ctSS2i.js} +1 -1
  242. ksadk/server/static/assets/{dist-ClxGviKw.js → dist-DiixqL0J.js} +1 -1
  243. ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-DoVSwoDb.js} +1 -1
  244. ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-DvFK7p5S.js} +1 -1
  245. ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-QfkEHOlb.js} +1 -1
  246. ksadk/server/static/assets/{dist-CttYUqzS.js → dist-btbmmX5O.js} +1 -1
  247. ksadk/server/static/assets/{dist-DmldrHd_.js → dist-fBO2v5Kt.js} +1 -1
  248. ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-ufY3F5p6.js} +1 -1
  249. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
  250. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
  251. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
  252. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
  253. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
  254. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
  255. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
  256. ksadk/server/static/assets/index-DcTML1Up.css +2 -0
  257. ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
  258. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
  259. ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
  260. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
  261. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
  262. ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
  263. ksadk/server/static/assets/{katex-vFWytM5c.js → katex-B4weu383.js} +1 -1
  264. ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-V-MgYHW1.js} +1 -1
  265. ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-CBijEX_c.js} +2 -2
  266. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
  267. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
  268. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
  269. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
  270. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
  271. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
  272. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
  273. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
  274. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
  275. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
  276. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
  277. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
  278. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
  279. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
  280. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
  281. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
  282. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
  283. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
  284. ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
  285. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
  286. ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
  287. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
  288. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
  289. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
  290. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
  291. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
  292. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
  293. ksadk/server/static/index.html +2 -2
  294. ksadk/session_context.py +66 -0
  295. ksadk/sessions/__init__.py +11 -21
  296. ksadk/sessions/_local_service_sync.py +263 -1
  297. ksadk/sessions/base.py +176 -0
  298. ksadk/sessions/errors.py +4 -0
  299. ksadk/sessions/in_memory.py +309 -19
  300. ksadk/sessions/local_service.py +83 -1
  301. ksadk/sessions/persistence.py +275 -0
  302. ksadk/sessions/postgres_service.py +358 -0
  303. ksadk/sessions/resilience.py +8 -0
  304. ksadk/sessions/resilient.py +362 -4
  305. ksadk/sessions/topology.py +135 -0
  306. ksadk/skills/models.py +26 -4
  307. ksadk/skills/package_store.py +186 -38
  308. ksadk/skills/runtime/agent.py +31 -6
  309. ksadk/skills/runtime/artifact_delivery.py +139 -0
  310. ksadk/skills/runtime/backends/e2b.py +98 -6
  311. ksadk/skills/runtime/backends/local.py +73 -8
  312. ksadk/skills/runtime/base.py +3 -0
  313. ksadk/skills/runtime/executor.py +2 -0
  314. ksadk/skills/runtime/loader.py +10 -2
  315. ksadk/skills/runtime/pinned.py +114 -0
  316. ksadk/skills/runtime/request.py +31 -0
  317. ksadk/skills/service_client.py +211 -24
  318. ksadk/studio/agent_lifecycle.py +26 -20
  319. ksadk/studio/api.py +714 -90
  320. ksadk/studio/api_catalog_routes.py +23 -0
  321. ksadk/studio/api_contracts.py +34 -1
  322. ksadk/studio/api_plugin_routes.py +911 -0
  323. ksadk/studio/api_resource_connections.py +183 -0
  324. ksadk/studio/attachment_store.py +187 -0
  325. ksadk/studio/authoring.py +10 -4
  326. ksadk/studio/authoring_coordinator.py +31 -16
  327. ksadk/studio/builder.py +199 -43
  328. ksadk/studio/cloud.py +346 -104
  329. ksadk/studio/cloud_shared_web.py +565 -0
  330. ksadk/studio/codex_agent_service.py +140 -27
  331. ksadk/studio/codex_builder.py +294 -16
  332. ksadk/studio/codex_credentials.py +90 -0
  333. ksadk/studio/codex_manifest.py +51 -4
  334. ksadk/studio/codex_plugin_store.py +746 -0
  335. ksadk/studio/codex_provider_build.py +231 -0
  336. ksadk/studio/codex_run.py +200 -29
  337. ksadk/studio/compatibility_report.py +456 -0
  338. ksadk/studio/compiler.py +84 -15
  339. ksadk/studio/contracts.py +249 -4
  340. ksadk/studio/dsh_application.py +137 -0
  341. ksadk/studio/dsh_capability_service.py +1107 -0
  342. ksadk/studio/dsh_models.py +59 -0
  343. ksadk/studio/dsh_provider_registration.py +1075 -0
  344. ksadk/studio/event_store.py +54 -6
  345. ksadk/studio/framework_run.py +37 -4
  346. ksadk/studio/hosted_kernel.py +89 -14
  347. ksadk/studio/mcp_runtime.py +11 -3
  348. ksadk/studio/model_client.py +2 -2
  349. ksadk/studio/operations.py +12 -2
  350. ksadk/studio/plugin_composition.py +468 -0
  351. ksadk/studio/plugin_kernel_adapter.py +28 -0
  352. ksadk/studio/plugin_runtime.py +831 -0
  353. ksadk/studio/resource_authority.py +637 -0
  354. ksadk/studio/resource_binding_validation.py +77 -0
  355. ksadk/studio/resource_build_admission.py +196 -0
  356. ksadk/studio/resource_build_materializer.py +149 -0
  357. ksadk/studio/resource_catalog.py +149 -3
  358. ksadk/studio/resource_connections.py +220 -0
  359. ksadk/studio/run_service.py +1144 -96
  360. ksadk/studio/runtime_source.py +24 -8
  361. ksadk/studio/scheduler_assistant.py +317 -0
  362. ksadk/studio/scheduler_runtime.py +383 -0
  363. ksadk/studio/scheduler_service.py +214 -0
  364. ksadk/studio/service.py +1131 -95
  365. ksadk/studio/shared_web.py +610 -87
  366. ksadk/studio/soul.py +52 -0
  367. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
  368. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  369. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  370. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  371. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  372. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  373. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  374. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  375. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  376. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  377. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  378. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  379. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  380. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  381. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  382. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  383. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  384. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  385. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  386. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  387. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  388. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  389. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  390. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  391. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  392. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  393. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  394. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  395. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  396. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  397. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  398. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  399. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  400. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  401. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  402. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  403. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  404. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  405. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  406. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  407. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  408. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  409. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  410. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  411. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  412. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  413. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  414. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  415. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  416. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  417. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  418. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  419. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  420. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  421. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  422. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  423. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  424. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  425. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  426. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  427. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
  428. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
  429. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
  430. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
  431. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
  432. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  433. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
  434. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
  435. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  436. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
  437. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
  438. ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
  439. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  440. ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
  441. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  442. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
  443. ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
  444. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
  445. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  446. ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
  447. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
  448. ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
  449. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  450. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
  451. ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
  452. ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
  453. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
  454. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
  455. ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
  456. ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
  457. ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
  458. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
  459. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  460. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
  461. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
  462. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
  463. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
  464. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
  465. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  466. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
  467. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  468. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  469. ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
  470. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
  471. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
  472. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
  473. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
  474. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  475. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
  476. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
  477. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
  478. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
  479. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
  480. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
  481. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
  482. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  483. ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
  484. ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
  485. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
  486. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
  487. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  488. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
  489. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
  490. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
  491. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  492. ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
  493. ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
  494. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
  495. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
  496. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  497. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
  498. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  499. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
  500. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
  501. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
  502. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
  503. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
  504. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
  505. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
  506. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
  507. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
  508. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
  509. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
  510. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  511. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  512. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
  513. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
  514. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  515. ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
  516. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
  517. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
  518. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
  519. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
  520. ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
  521. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
  522. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
  523. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
  524. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
  525. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
  526. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
  527. ksadk/studio/static/index.html +2 -2
  528. ksadk/studio/validator.py +1 -1
  529. ksadk/studio/workspace.py +1 -0
  530. ksadk/version.py +1 -1
  531. ksadk_runtime_common/workspace_files/path_utils.py +41 -0
  532. agentengine_sdk_python-0.8.2.dist-info/RECORD +0 -778
  533. ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
  534. ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
  535. ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
  536. ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
  537. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
  538. ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
  539. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
  540. ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
  541. ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
  542. ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
  543. ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
  544. ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
  545. ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
  546. ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
  547. ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
  548. ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
  549. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
  550. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
  551. ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
  552. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
  553. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
  554. ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
  555. ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
  556. ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
  557. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  558. ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
  559. ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
  560. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
  561. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
  562. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
  563. {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
@@ -4,12 +4,12 @@ LangGraphRunner - LangGraph 框架运行时
4
4
  直接透传 LangGraph 原生能力,最小化封装
5
5
  """
6
6
 
7
- from __future__ import annotations
8
-
9
7
  import asyncio
10
8
  import base64
9
+ import inspect
11
10
  import os
12
11
  import re
12
+ import sqlite3
13
13
  import uuid
14
14
  from typing import Any, AsyncIterator, Dict, Mapping
15
15
 
@@ -19,6 +19,7 @@ from ksadk.conversations.attachments import classify_attachment_kind, read_attac
19
19
  from ksadk.runners._langgraph_runner_streams import _LangGraphStreamMixin
20
20
  from ksadk.runners.base_runner import BaseRunner
21
21
  from ksadk.runners.utils import load_agent_module
22
+ from ksadk.sessions import resolve_persistence_topology
22
23
  from ksadk.sessions.continuity import LangGraphSessionAdapter
23
24
 
24
25
 
@@ -28,14 +29,15 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
28
29
  透传原生 LangGraph 功能,支持任意 State 格式
29
30
  """
30
31
 
31
- # ToolGateway approvals can arise after an otherwise terminal tool call;
32
- # this runner opts into the runtime's semantic follow-up continuation.
32
+ # ToolGateway approvals can occur after a terminal-looking tool call, so
33
+ # the semantic stream must remain resumable for a follow-up decision.
33
34
  supports_gateway_approval_semantic_resume = True
34
35
 
35
36
  def __init__(self, detection_result: Any, project_dir: str):
36
37
  super().__init__(detection_result, project_dir)
37
38
  self._managed_checkpoint_lock = asyncio.Lock()
38
39
  self._managed_checkpoint_prepared = False
40
+ self._managed_checkpoint_state = "uninitialized"
39
41
  self._managed_checkpoint_error: tuple[str, str] | None = None
40
42
  self._managed_checkpoint_pool: Any = None
41
43
  self._managed_checkpoint_namespace = ""
@@ -62,86 +64,243 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
62
64
  normalized = self.sync_process_model_env(model)
63
65
  if normalized is None or self._agent is None:
64
66
  return
65
- # Studio's generated graph reads the model environment while building
66
- # each model turn. Reloading it here would discard the managed
67
- # PostgreSQL checkpointer that was installed asynchronously below.
68
- if (
69
- normalized == getattr(self, "_loaded_model_name", None)
70
- or self._managed_checkpoint_pool is not None
71
- ):
67
+ if normalized == getattr(self, "_loaded_model_name", None):
72
68
  return
73
69
  self._load_agent(force_reload=True)
74
70
 
75
71
  def get_session_adapter(self):
76
72
  return LangGraphSessionAdapter()
77
73
 
78
- def describe_checkpoint_capability(self) -> dict[str, Any]:
79
- agent = getattr(self, "_agent", None)
80
- checkpointer = getattr(agent, "checkpointer", None)
81
- if checkpointer is None:
82
- checkpointer = getattr(agent, "_checkpointer", None)
83
- if checkpointer is None:
84
- error_code, error_reason = self._managed_checkpoint_error or ("", "")
74
+ def describe_lazy_checkpoint_capability(self) -> dict[str, Any] | None:
75
+ """Describe a checkpointer created lazily by a custom runner.
76
+
77
+ Standard LangGraph runners expose the compiled graph through ``_agent``.
78
+ Custom runners that construct a graph per invocation can override this
79
+ hook so bootstrap capability discovery does not depend on a resident
80
+ graph object.
81
+ """
82
+ return None
83
+
84
+ @staticmethod
85
+ def _checkpoint_backend_from_saver(checkpointer: Any) -> str:
86
+ for saver_type in type(checkpointer).__mro__:
87
+ qualified_name = f"{saver_type.__module__}.{saver_type.__name__}".lower()
88
+ if "checkpoint.postgres" in qualified_name or "postgressaver" in qualified_name:
89
+ return "postgres"
90
+ if "checkpoint.sqlite" in qualified_name or "sqlitesaver" in qualified_name:
91
+ return "sqlite"
92
+ if "checkpoint.memory" in qualified_name or saver_type.__name__.lower() in {
93
+ "memorysaver",
94
+ "inmemorysaver",
95
+ }:
96
+ return "memory"
97
+ return "unknown"
98
+
99
+ @staticmethod
100
+ def _sqlite_target_storage(database: Any) -> str:
101
+ target = os.fspath(database).strip() if isinstance(database, (str, os.PathLike)) else ""
102
+ if not target:
103
+ return "memory"
104
+ lowered = target.lower()
105
+ if lowered == ":memory:":
106
+ return "memory"
107
+ if lowered.startswith("file:"):
108
+ path, _, query = lowered.partition("?")
109
+ if path in {"file:", "file::memory:"} or "mode=memory" in query.split("&"):
110
+ return "memory"
111
+ return "file"
112
+
113
+ @classmethod
114
+ def _sqlite_checkpoint_storage(cls, checkpointer: Any) -> str:
115
+ connection = getattr(checkpointer, "conn", None)
116
+ if isinstance(connection, sqlite3.Connection):
117
+ try:
118
+ rows = connection.execute("PRAGMA database_list").fetchall()
119
+ except Exception:
120
+ return "unknown"
121
+ for row in rows:
122
+ if len(row) >= 3 and row[1] == "main":
123
+ return "file" if str(row[2] or "").strip() else "memory"
124
+ return "unknown"
125
+
126
+ # AsyncSqliteSaver keeps the original aiosqlite connector closure. Its
127
+ # public PRAGMA API is async, while capability discovery is synchronous,
128
+ # so inspect the connection target and fail closed if it is unavailable.
129
+ connector = getattr(connection, "_connector", None)
130
+ code = getattr(connector, "__code__", None)
131
+ closure = getattr(connector, "__closure__", None)
132
+ if code is None or closure is None:
133
+ return "unknown"
134
+ try:
135
+ closed_values = {
136
+ name: cell.cell_contents
137
+ for name, cell in zip(code.co_freevars, closure)
138
+ }
139
+ except (AttributeError, ValueError):
140
+ return "unknown"
141
+ if "database" not in closed_values:
142
+ return "unknown"
143
+ return cls._sqlite_target_storage(closed_values["database"])
144
+
145
+ @classmethod
146
+ def _checkpoint_capability_for_backend(
147
+ cls,
148
+ backend: str,
149
+ *,
150
+ checkpointer: Any = None,
151
+ ) -> dict[str, Any]:
152
+ if backend == "postgres":
153
+ return {
154
+ "Supported": True,
155
+ "Backend": "postgres",
156
+ "Scope": "shared",
157
+ "Durable": True,
158
+ "SharedAcrossPods": True,
159
+ "ResumeMode": "time_travel",
160
+ "Reason": "",
161
+ }
162
+ if backend == "sqlite":
163
+ if checkpointer is not None:
164
+ storage = cls._sqlite_checkpoint_storage(checkpointer)
165
+ if storage != "file":
166
+ return {
167
+ "Supported": False,
168
+ "Backend": "sqlite",
169
+ "Scope": "process_local" if storage == "memory" else "unknown",
170
+ "Durable": False,
171
+ "SharedAcrossPods": False,
172
+ "ResumeMode": "none",
173
+ "ReasonCode": "CHECKPOINTER_NOT_DURABLE",
174
+ "Reason": (
175
+ "In-memory SQLite checkpoint cannot be recovered after process restart"
176
+ if storage == "memory"
177
+ else "SQLite checkpoint file target cannot be verified as durable"
178
+ ),
179
+ }
180
+ return {
181
+ "Supported": True,
182
+ "Backend": "sqlite",
183
+ "Scope": "pod_local",
184
+ "Durable": True,
185
+ "SharedAcrossPods": False,
186
+ "ResumeMode": "time_travel",
187
+ "Reason": (
188
+ "SQLite checkpoint is durable for local web debugging "
189
+ "but is not shared across pods"
190
+ ),
191
+ }
192
+ if backend == "memory":
85
193
  return {
86
194
  "Supported": False,
87
- "Backend": "none",
88
- "Scope": "unknown",
195
+ "Backend": "memory",
196
+ "Scope": "process_local",
89
197
  "Durable": False,
90
198
  "SharedAcrossPods": False,
91
199
  "ResumeMode": "none",
92
- **({"ReasonCode": error_code} if error_code else {}),
93
- "Reason": error_reason or "LangGraph graph has no configured checkpointer",
200
+ "ReasonCode": "CHECKPOINTER_NOT_DURABLE",
201
+ "Reason": (
202
+ "In-memory checkpoint cannot be recovered after process restart "
203
+ "or across pods"
204
+ ),
94
205
  }
206
+ return {
207
+ "Supported": False,
208
+ "Backend": "unknown",
209
+ "Scope": "unknown",
210
+ "Durable": False,
211
+ "SharedAcrossPods": False,
212
+ "ResumeMode": "none",
213
+ "ReasonCode": "CHECKPOINTER_NOT_DURABLE",
214
+ "Reason": "LangGraph checkpointer backend is not recognized as durable",
215
+ }
95
216
 
96
- backend = self._checkpoint_backend_from_saver(checkpointer)
97
- if backend == "unknown":
98
- # Some third-party savers hide their concrete type. Preserve the
99
- # explicit legacy declaration for those cases, but never let it
100
- # override a detectable in-memory saver.
101
- backend = str(os.getenv("KSADK_CHECKPOINT_BACKEND") or "").strip().lower()
102
- if backend == "local":
103
- backend = "sqlite"
104
- if not backend:
105
- backend = "unknown"
106
- scope = "unknown"
107
- durable = False
108
- shared = False
109
- reason = ""
110
- if backend == "postgres":
111
- scope = "shared"
112
- durable = True
113
- shared = True
114
- elif backend == "sqlite":
115
- scope = "pod_local"
116
- durable = True
117
- shared = False
118
- reason = (
119
- "SQLite checkpoint is durable for local web debugging but is not shared across pods"
217
+ @staticmethod
218
+ def _invalid_lazy_checkpoint_capability(
219
+ capability: Mapping[str, Any] | None = None,
220
+ ) -> dict[str, Any]:
221
+ source = capability or {}
222
+ return {
223
+ "Supported": False,
224
+ "Backend": str(source.get("Backend") or "unknown").strip().lower(),
225
+ "Scope": str(source.get("Scope") or "unknown").strip().lower(),
226
+ "Durable": bool(source.get("Durable")),
227
+ "SharedAcrossPods": bool(source.get("SharedAcrossPods")),
228
+ "ResumeMode": "none",
229
+ "ReasonCode": "CHECKPOINTER_NOT_DURABLE",
230
+ "Reason": "Lazy LangGraph checkpoint capability is invalid or not durably resumable",
231
+ }
232
+
233
+ @classmethod
234
+ def _normalize_lazy_checkpoint_capability(cls, capability: Any) -> dict[str, Any]:
235
+ if not isinstance(capability, Mapping):
236
+ return cls._invalid_lazy_checkpoint_capability()
237
+
238
+ backend = str(capability.get("Backend") or "unknown").strip().lower()
239
+ scope = str(capability.get("Scope") or "unknown").strip().lower()
240
+ durable = capability.get("Durable") is True
241
+ shared = capability.get("SharedAcrossPods") is True
242
+ resume_mode = str(capability.get("ResumeMode") or "none").strip().lower()
243
+ supported = capability.get("Supported") is True
244
+
245
+ if supported:
246
+ valid = (
247
+ durable
248
+ and resume_mode == "time_travel"
249
+ and (
250
+ (backend == "postgres" and scope == "shared" and shared)
251
+ or (backend == "sqlite" and scope == "pod_local" and not shared)
252
+ )
120
253
  )
121
- elif backend in {"memory", "inmemory"}:
122
- backend = "memory"
123
- scope = "process_local"
124
- durable = False
125
- shared = False
126
- reason = "In-memory checkpoint cannot be recovered after process restart or across pods"
254
+ if not valid:
255
+ return cls._invalid_lazy_checkpoint_capability(capability)
127
256
 
128
257
  return {
129
- # A local saver may be useful for interactive development, but it
130
- # is not a native durable-resume capability in a hosted runtime.
131
- "Supported": backend not in {"memory", "inmemory", "unknown", ""},
258
+ "Supported": supported,
132
259
  "Backend": backend,
133
260
  "Scope": scope,
134
261
  "Durable": durable,
135
262
  "SharedAcrossPods": shared,
136
- "ResumeMode": "time_travel" if durable else "none",
137
- **(
138
- {"ReasonCode": "CHECKPOINTER_NOT_DURABLE"}
139
- if backend in {"memory", "inmemory", "unknown", ""}
140
- else {}
141
- ),
142
- "Reason": reason,
263
+ "ResumeMode": resume_mode if supported else "none",
264
+ "Reason": str(capability.get("Reason") or "").strip(),
143
265
  }
144
266
 
267
+ def describe_checkpoint_capability(self) -> dict[str, Any]:
268
+ agent = getattr(self, "_agent", None)
269
+ checkpointer = getattr(agent, "checkpointer", None)
270
+ if checkpointer is None:
271
+ checkpointer = getattr(agent, "_checkpointer", None)
272
+ if checkpointer is None:
273
+ lazy_capability = self.describe_lazy_checkpoint_capability()
274
+ if lazy_capability is not None:
275
+ return self._normalize_lazy_checkpoint_capability(lazy_capability)
276
+ if self._managed_checkpoint_error is not None:
277
+ reason_code, reason = self._managed_checkpoint_error
278
+ return {
279
+ "Supported": False,
280
+ "Backend": "postgres",
281
+ "Scope": "unknown",
282
+ "Durable": False,
283
+ "SharedAcrossPods": False,
284
+ "ResumeMode": "none",
285
+ "ReasonCode": reason_code,
286
+ "Reason": reason,
287
+ }
288
+ return {
289
+ "Supported": False,
290
+ "Backend": "none",
291
+ "Scope": "unknown",
292
+ "Durable": False,
293
+ "SharedAcrossPods": False,
294
+ "ReasonCode": "CHECKPOINTER_NOT_DURABLE",
295
+ "Reason": "LangGraph graph has no configured checkpointer",
296
+ }
297
+ backend = self._checkpoint_backend_from_saver(checkpointer)
298
+ if backend == "unknown":
299
+ configured_backend = str(os.getenv("KSADK_CHECKPOINT_BACKEND") or "").strip().lower()
300
+ if configured_backend in {"postgres", "sqlite", "memory"}:
301
+ backend = configured_backend
302
+ return self._checkpoint_capability_for_backend(backend, checkpointer=checkpointer)
303
+
145
304
  def get_runtime_capabilities(self) -> dict[str, Any]:
146
305
  capabilities = super().get_runtime_capabilities()
147
306
  capabilities["model_call_boundaries"] = True
@@ -158,26 +317,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
158
317
  }
159
318
  return capabilities
160
319
 
161
- @staticmethod
162
- def _checkpoint_backend_from_saver(checkpointer: Any) -> str:
163
- if checkpointer is None:
164
- return "unknown"
165
- for saver_type in type(checkpointer).__mro__:
166
- qualified_name = f"{saver_type.__module__}.{saver_type.__name__}".lower()
167
- if "checkpoint.postgres" in qualified_name or "postgressaver" in qualified_name:
168
- return "postgres"
169
- if "checkpoint.sqlite" in qualified_name or "sqlitesaver" in qualified_name:
170
- return "sqlite"
171
- if "checkpoint.memory" in qualified_name or saver_type.__name__.lower() in {
172
- "memorysaver",
173
- "inmemorysaver",
174
- }:
175
- return "memory"
176
- return "unknown"
177
-
178
320
  @staticmethod
179
321
  def _env_flag(name: str) -> bool:
180
- return str(os.getenv(name) or "").strip().lower() in {"1", "true", "yes", "on"}
322
+ return str(os.getenv(name) or "").strip().lower() in {
323
+ "1",
324
+ "true",
325
+ "yes",
326
+ "on",
327
+ }
181
328
 
182
329
  @staticmethod
183
330
  def _resolve_checkpoint_namespace() -> str:
@@ -185,7 +332,9 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
185
332
  if session_namespace:
186
333
  return session_namespace
187
334
  agent_id = str(
188
- os.getenv("AGENTENGINE_AGENT_ID") or os.getenv("KSADK_AGENT_ID") or "default"
335
+ os.getenv("AGENTENGINE_AGENT_ID")
336
+ or os.getenv("KSADK_AGENT_ID")
337
+ or "default"
189
338
  ).strip()
190
339
  return f"agent:{agent_id}"
191
340
 
@@ -217,34 +366,175 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
217
366
  raise
218
367
 
219
368
  async def prepare_runtime_capabilities(self) -> None:
220
- """Install the managed saver before a graph can begin an interaction.
369
+ await self._prepare_managed_checkpoint(allow_transient_retry=False)
370
+
371
+ async def refresh_runtime_capabilities(self) -> None:
372
+ await self._prepare_managed_checkpoint(allow_transient_retry=True)
373
+
374
+ async def attach_runtime_handle(self, handle: Any) -> bool:
375
+ """Validate a persisted LangGraph checkpoint handle for Runtime v2.
221
376
 
222
- The graph module must opt into this seam by exporting
223
- ``ksadk_graph_factory(*, checkpointer)``. We never mutate a compiled
224
- graph's private attributes: failed configuration remains fail-closed
225
- and capability discovery honestly reports why native resume is absent.
377
+ The concrete graph resolves the checkpoint during its native resume
378
+ call. Attachment verifies the durable backend and the complete native
379
+ address without fabricating process-local ownership.
226
380
  """
227
- if self._managed_checkpoint_prepared:
381
+
382
+ if str(getattr(handle, "runtime_type", "") or "").strip().lower() != "langgraph":
383
+ return False
384
+ native_ref = getattr(handle, "native_ref", None)
385
+ if not isinstance(native_ref, Mapping):
386
+ return False
387
+ framework_ref = native_ref.get("framework_ref")
388
+ langgraph_ref = (
389
+ framework_ref.get("langgraph") if isinstance(framework_ref, Mapping) else None
390
+ )
391
+ checkpoint_id = str(
392
+ native_ref.get("checkpoint_id")
393
+ or (
394
+ langgraph_ref.get("checkpoint_id")
395
+ if isinstance(langgraph_ref, Mapping)
396
+ else ""
397
+ )
398
+ or ""
399
+ ).strip()
400
+ thread_id = str(
401
+ native_ref.get("thread_id")
402
+ or (
403
+ langgraph_ref.get("thread_id")
404
+ if isinstance(langgraph_ref, Mapping)
405
+ else ""
406
+ )
407
+ or ""
408
+ ).strip()
409
+ if not checkpoint_id or not thread_id:
410
+ return False
411
+
412
+ await self.prepare_runtime_capabilities()
413
+ capability = self.describe_checkpoint_capability()
414
+ if not bool(
415
+ capability.get("Supported")
416
+ and capability.get("Durable")
417
+ and capability.get("SharedAcrossPods")
418
+ ):
419
+ return False
420
+
421
+ configurable = {
422
+ "thread_id": thread_id,
423
+ "checkpoint_id": checkpoint_id,
424
+ }
425
+ checkpoint_ns = str(
426
+ native_ref.get("checkpoint_ns")
427
+ or (
428
+ langgraph_ref.get("checkpoint_ns")
429
+ if isinstance(langgraph_ref, Mapping)
430
+ else ""
431
+ )
432
+ or ""
433
+ ).strip()
434
+ if checkpoint_ns:
435
+ configurable["checkpoint_ns"] = checkpoint_ns
436
+ config = {"configurable": configurable}
437
+
438
+ if callable(
439
+ getattr(self._agent, "aget_state", None)
440
+ or getattr(self._agent, "get_state", None)
441
+ ):
442
+ return await self._checkpoint_state_resolves(
443
+ config,
444
+ thread_id=thread_id,
445
+ checkpoint_id=checkpoint_id,
446
+ checkpoint_ns=checkpoint_ns,
447
+ )
448
+
449
+ with_graph = getattr(self, "_with_graph", None)
450
+ if not callable(with_graph):
451
+ return False
452
+
453
+ async def validate_lazy_graph() -> bool:
454
+ return await self._checkpoint_state_resolves(
455
+ config,
456
+ thread_id=thread_id,
457
+ checkpoint_id=checkpoint_id,
458
+ checkpoint_ns=checkpoint_ns,
459
+ )
460
+
461
+ return bool(await with_graph(validate_lazy_graph))
462
+
463
+ async def _checkpoint_state_resolves(
464
+ self,
465
+ config: Mapping[str, Any],
466
+ *,
467
+ thread_id: str,
468
+ checkpoint_id: str,
469
+ checkpoint_ns: str,
470
+ ) -> bool:
471
+ """Confirm one exact persisted checkpoint through the active graph."""
472
+
473
+ get_state = getattr(self._agent, "aget_state", None) or getattr(
474
+ self._agent, "get_state", None
475
+ )
476
+ if not callable(get_state):
477
+ return False
478
+ state = get_state(config)
479
+ if inspect.isawaitable(state):
480
+ state = await state
481
+ state_created_at = (
482
+ state.get("created_at")
483
+ if isinstance(state, Mapping)
484
+ else getattr(state, "created_at", None)
485
+ )
486
+ state_metadata = (
487
+ state.get("metadata")
488
+ if isinstance(state, Mapping)
489
+ else getattr(state, "metadata", None)
490
+ )
491
+ if state_created_at is None and state_metadata is None:
492
+ return False
493
+ resolved_ref = self._checkpoint_ref_from_state(state).get("langgraph", {})
494
+ if not isinstance(resolved_ref, Mapping):
495
+ return False
496
+ if str(resolved_ref.get("thread_id") or "").strip() != thread_id:
497
+ return False
498
+ if str(resolved_ref.get("checkpoint_id") or "").strip() != checkpoint_id:
499
+ return False
500
+ if checkpoint_ns and str(resolved_ref.get("checkpoint_ns") or "").strip() != checkpoint_ns:
501
+ return False
502
+ return True
503
+
504
+ async def _prepare_managed_checkpoint(self, *, allow_transient_retry: bool) -> None:
505
+ if self._managed_checkpoint_state in {"ready", "terminal_failure"}:
506
+ return
507
+ if self._managed_checkpoint_state == "transient_failure" and not allow_transient_retry:
228
508
  return
229
509
  async with self._managed_checkpoint_lock:
230
- if self._managed_checkpoint_prepared:
510
+ if self._managed_checkpoint_state in {"ready", "terminal_failure"}:
511
+ return
512
+ if (
513
+ self._managed_checkpoint_state == "transient_failure"
514
+ and not allow_transient_retry
515
+ ):
231
516
  return
232
517
 
233
518
  checkpointer = getattr(self._agent, "checkpointer", None)
234
519
  if checkpointer is None:
235
520
  checkpointer = getattr(self._agent, "_checkpointer", None)
236
521
  if self._checkpoint_backend_from_saver(checkpointer) == "postgres":
237
- self._managed_checkpoint_namespace = self._resolve_checkpoint_namespace()
522
+ self._managed_checkpoint_namespace = (
523
+ self._resolve_checkpoint_namespace()
524
+ )
238
525
  self._managed_checkpoint_prepared = True
526
+ self._managed_checkpoint_state = "ready"
239
527
  return
240
528
 
241
- dsn = str(
242
- os.getenv("KSADK_LANGGRAPH_CHECKPOINT_DSN")
243
- or os.getenv("KSADK_SESSION_DSN")
244
- or ""
245
- ).strip()
246
- if not self._env_flag("KSADK_LANGGRAPH_AUTO_CHECKPOINT") or not dsn:
529
+ auto_enabled = self._env_flag("KSADK_LANGGRAPH_AUTO_CHECKPOINT")
530
+ checkpoint_target = resolve_persistence_topology(framework="langgraph").checkpoint
531
+ if (
532
+ not auto_enabled
533
+ or checkpoint_target.backend != "postgres"
534
+ or not checkpoint_target.dsn
535
+ ):
247
536
  self._managed_checkpoint_prepared = True
537
+ self._managed_checkpoint_state = "terminal_failure"
248
538
  return
249
539
 
250
540
  factory = getattr(self._module, "ksadk_graph_factory", None)
@@ -255,37 +545,62 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
255
545
  "ksadk_graph_factory(*, checkpointer) for managed PostgreSQL checkpoints",
256
546
  )
257
547
  self._managed_checkpoint_prepared = True
548
+ self._managed_checkpoint_state = "terminal_failure"
258
549
  return
259
550
 
260
551
  pool = None
261
552
  try:
262
- saver, pool = await self._create_managed_postgres_saver(dsn)
553
+ saver, pool = await self._create_managed_postgres_saver(checkpoint_target.dsn)
263
554
  managed_graph = factory(checkpointer=saver)
264
555
  if not callable(getattr(managed_graph, "invoke", None)):
265
556
  raise TypeError("ksadk_graph_factory must return a compiled LangGraph graph")
266
557
  self._agent = managed_graph
267
558
  self._managed_checkpoint_pool = pool
268
- self._managed_checkpoint_namespace = self._resolve_checkpoint_namespace()
559
+ self._managed_checkpoint_namespace = (
560
+ self._resolve_checkpoint_namespace()
561
+ )
269
562
  self._managed_checkpoint_error = None
563
+ self._managed_checkpoint_state = "ready"
270
564
  except (ModuleNotFoundError, ImportError):
271
565
  self._managed_checkpoint_error = (
272
566
  "DEPENDENCY_MISSING",
273
567
  "langgraph-checkpoint-postgres and psycopg are required "
274
568
  "for managed checkpoints",
275
569
  )
276
- except Exception as exc: # noqa: BLE001
570
+ self._managed_checkpoint_state = "terminal_failure"
571
+ except Exception as exc:
277
572
  error_name = type(exc).__name__.lower()
573
+ authentication_failure = any(
574
+ marker in error_name
575
+ for marker in ("password", "authentication", "authorization")
576
+ )
577
+ permission_failure = any(
578
+ marker in error_name for marker in ("privilege", "permission")
579
+ )
580
+ terminal = authentication_failure or permission_failure or isinstance(
581
+ exc, (TypeError, ValueError)
582
+ )
583
+ reason_code = (
584
+ "AUTH_FAILED"
585
+ if authentication_failure
586
+ else "SCHEMA_PERMISSION_DENIED"
587
+ if permission_failure
588
+ else "CHECKPOINTER_NOT_DURABLE"
589
+ if terminal
590
+ else "CHECKPOINT_STORE_UNREACHABLE"
591
+ )
278
592
  self._managed_checkpoint_error = (
279
- "SCHEMA_PERMISSION_DENIED"
280
- if "privilege" in error_name or "permission" in error_name
281
- else "DB_UNREACHABLE",
593
+ reason_code,
282
594
  "Managed LangGraph PostgreSQL checkpointer initialization failed",
283
595
  )
596
+ self._managed_checkpoint_state = (
597
+ "terminal_failure" if terminal else "transient_failure"
598
+ )
284
599
  finally:
285
600
  if pool is not None and self._managed_checkpoint_pool is None:
286
601
  try:
287
602
  await pool.close()
288
- except Exception: # noqa: BLE001
603
+ except Exception:
289
604
  pass
290
605
  self._managed_checkpoint_prepared = True
291
606
 
@@ -298,7 +613,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
298
613
 
299
614
  def _get_config(self, session_id: str) -> dict:
300
615
  """获取运行配置"""
301
- config = {"configurable": {"thread_id": session_id}}
616
+ config: dict[str, Any] = {"configurable": {"thread_id": session_id}}
302
617
  if self._managed_checkpoint_namespace:
303
618
  config["configurable"]["checkpoint_ns"] = self._managed_checkpoint_namespace
304
619
  return config
@@ -339,6 +654,36 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
339
654
  next_config["configurable"] = configurable
340
655
  return next_config
341
656
 
657
+ @staticmethod
658
+ def _unwrap_resume_value(resume_value: Any) -> Any:
659
+ """从 ksadk_resume 包装中提取实际 resume value。
660
+
661
+ KsADK 的 ksadk_resume 协议把用户决策包在 ``{"type":"ksadk_resume",
662
+ "interrupt_id":..., "value":{...}}`` 里,但 ``Command(resume=...)``
663
+ 期望直接收到框架能识别的值(如 HumanInTheLoopMiddleware 的
664
+ ``{"decisions":[...]}``)。这里拆掉外层包装,把 ``value`` 内容
665
+ 作为 resume value 返回。有 interrupt_id 时保留原生 {id: value} 定向
666
+ 恢复语义,避免并行 interrupt 丢失目标;无 ID 时保留单 interrupt 值路径。
667
+
668
+ 非 ksadk_resume 类型(mcp_approval_response 等)原样返回,保持
669
+ 既有内置工具审批路径不变;ToolGateway 走 semantic resume 分支,
670
+ 不经过此处。
671
+ """
672
+ if isinstance(resume_value, Mapping):
673
+ item_type = str(resume_value.get("type") or "").strip()
674
+ if item_type in {"ksadk_resume", "ksadk.approval_response"}:
675
+ inner = resume_value.get("value")
676
+ if inner is not None:
677
+ interrupt_id = str(
678
+ resume_value.get("interrupt_id")
679
+ or resume_value.get("approval_request_id")
680
+ or resume_value.get("id")
681
+ or ""
682
+ ).strip()
683
+ # Parallel graph tasks must receive only their own decision.
684
+ return {interrupt_id: inner} if interrupt_id else inner
685
+ return resume_value
686
+
342
687
  @staticmethod
343
688
  def _checkpoint_resume_input(
344
689
  value: Any,
@@ -353,14 +698,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
353
698
 
354
699
  @staticmethod
355
700
  def _is_gateway_approval_semantic_resume(value: Any) -> bool:
356
- """Whether ``value`` came from a completed ToolGateway approval.
357
-
358
- Native LangGraph ``interrupt()`` values must keep using
359
- ``Command(resume=...)``. In contrast, a ToolGateway can return an
360
- ``approval_required`` result from an otherwise normal tool call; the
361
- graph then reaches its terminal node before KsADK shows the approval
362
- card. Its approved tool result needs a new semantic graph turn.
363
- """
701
+ """Return whether a completed ToolGateway approval needs a fresh turn."""
364
702
 
365
703
  return bool(
366
704
  isinstance(value, Mapping)
@@ -370,13 +708,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
370
708
 
371
709
  @staticmethod
372
710
  def _gateway_approval_follow_up_input() -> str:
373
- """A neutral prompt for the post-approval semantic continuation.
374
-
375
- The actual approval response and durable tool result are already in
376
- the session history. Do not repeat their contents here: project hooks
377
- commonly route by input keywords, and copying a workspace path back
378
- into a synthetic user message can accidentally trigger another tool.
379
- """
711
+ """Build the neutral prompt used after an approved terminal tool call."""
380
712
 
381
713
  return (
382
714
  "系统已完成此前获批的操作。请基于会话记录中的真实结果,直接向用户说明完成情况;"
@@ -788,19 +1120,12 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
788
1120
  resume_payload_provided = bool(payload.pop("resume_payload_provided", False))
789
1121
  resume_interrupt_id = str(payload.pop("resume_interrupt_id", "") or "")
790
1122
  resume_value = payload.get("input")
791
- is_gateway_approval_resume = bool(
792
- is_resume and self._is_gateway_approval_semantic_resume(resume_value)
793
- )
794
- if is_gateway_approval_resume:
795
- # ``Command(resume=...)`` only works for a graph that actually
796
- # yielded LangGraph's native interrupt. ToolGateway approvals are
797
- # intercepted after a normal tool result, when the graph already
798
- # ended, so restart a normal turn from the persisted transcript.
799
- payload["input"] = self._gateway_approval_follow_up_input()
800
- resume_value = payload["input"]
801
1123
  checkpoint_ref = self._extract_langgraph_checkpoint_ref(payload)
802
1124
  history = payload.pop("history", [])
803
- native_context = self.build_native_context(payload.get("platform_context"))
1125
+ native_context = self.build_native_context(
1126
+ payload.get("platform_context"),
1127
+ context_schema=getattr(self._agent, "context_schema", None),
1128
+ )
804
1129
  config = self._get_config(session_id)
805
1130
  if is_checkpoint_resume:
806
1131
  config = self._apply_checkpoint_resume_config(
@@ -812,19 +1137,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
812
1137
  # 判断输入格式 / resume
813
1138
  if is_checkpoint_resume:
814
1139
  state = resume_value
815
- elif is_resume and not is_gateway_approval_resume:
1140
+ elif is_resume:
816
1141
  # ``Command(resume=...)`` is delivered to the graph's suspended
817
1142
  # interrupt. A custom prepare-state hook is for new user input;
818
1143
  # applying it here can rewrite an approval decision into ordinary
819
1144
  # graph state and turn an approved HITL action into a rejection.
820
- state = resume_value
1145
+ state = self._unwrap_resume_value(resume_value)
821
1146
  elif self._has_prepare_state_hook():
822
- state = self._prepare_state_with_hook(
823
- payload,
824
- session_id,
825
- history,
826
- is_resume=is_gateway_approval_resume,
827
- )
1147
+ state = self._prepare_state_with_hook(payload, session_id, history)
828
1148
  else:
829
1149
  state = self._to_state(payload, history)
830
1150
 
@@ -839,7 +1159,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
839
1159
  config=config,
840
1160
  context=native_context,
841
1161
  )
842
- elif is_resume and not is_gateway_approval_resume:
1162
+ elif is_resume:
843
1163
  result = await self._invoke_graph(
844
1164
  Command(resume=state),
845
1165
  config=config,
@@ -913,6 +1233,21 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
913
1233
  interrupt_id = str(getattr(intr, "id", "") or "")
914
1234
  if interrupt_id:
915
1235
  info.setdefault("approval_request_id", interrupt_id)
1236
+ # HumanInTheLoopMiddleware 的 interrupt value 把
1237
+ # tool_name/arguments 嵌在 action_requests[0] 里;
1238
+ # 下游期望顶层字段,这里提取并保留原 action_requests。
1239
+ action_requests = info.get("action_requests")
1240
+ if isinstance(action_requests, list) and action_requests:
1241
+ first = action_requests[0]
1242
+ if isinstance(first, Mapping):
1243
+ info.setdefault("tool_name", str(first.get("name") or ""))
1244
+ raw_args = first.get("args") or first.get("arguments")
1245
+ if raw_args is not None:
1246
+ info.setdefault("arguments", raw_args)
1247
+ if first.get("description") is not None:
1248
+ info.setdefault(
1249
+ "description", str(first.get("description"))
1250
+ )
916
1251
  return info
917
1252
  return {}
918
1253
 
@@ -1051,16 +1386,11 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
1051
1386
  )
1052
1387
  return events
1053
1388
 
1389
+
1054
1390
  def _filter_tool_tags(self, content: str) -> str:
1055
- """过滤完整的 XML tool_call 标签。"""
1391
+ """过滤 <tool_call> 标签"""
1056
1392
  if not isinstance(content, str):
1057
1393
  return content
1058
1394
  content = re.sub(r"<tool_call>.*?</tool_call>", "", content, flags=re.DOTALL)
1059
1395
  content = re.sub(r"</?(?:tool_call|arg_key|arg_value)>", "", content)
1060
1396
  return content
1061
-
1062
- async def stream(self, input_data: Dict[str, Any]) -> AsyncIterator[Dict[str, Any]]:
1063
- """Prepare the managed checkpoint before yielding the first event."""
1064
- await self.prepare_runtime_capabilities()
1065
- async for event in super().stream(input_data):
1066
- yield event