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
@@ -0,0 +1,318 @@
1
+ """Bound structured AICP MemoryProvider; asynchronous writes use a separate receipt path."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+ import math
8
+ import threading
9
+ import time
10
+ from contextlib import contextmanager
11
+
12
+ from pydantic import Field
13
+
14
+ from ksadk.memory.adk.backends.sdk_ltm_backend import SdkLTMBackend
15
+ from ksadk.memory.models import (
16
+ CoreMemoryRequest,
17
+ MemoryCapabilities,
18
+ MemoryDeleteRequest,
19
+ MemoryDeleteResult,
20
+ MemoryRecord,
21
+ MemorySearchRequest,
22
+ MemorySearchResult,
23
+ UnsupportedMemoryOperation,
24
+ )
25
+ from ksadk.plugins.contracts import PluginContractModel
26
+ from ksadk.resource_runtime.contracts import InvocationIdentity, ResourceConfig
27
+ from ksadk.resource_runtime.errors import ResourceUpstreamAuthorizationError
28
+
29
+
30
+ class MemoryQuery(PluginContractModel):
31
+ query: str = Field(strict=True, max_length=16000)
32
+
33
+
34
+ class MemoryWrite(PluginContractModel):
35
+ content: str = Field(strict=True, min_length=1, max_length=8192)
36
+
37
+
38
+ class MemoryStatusQuery(PluginContractModel):
39
+ operation_id: str = Field(strict=True, pattern=r"^[0-9a-f]{64}$")
40
+
41
+
42
+ class MemoryRecordSelector(PluginContractModel):
43
+ memory_id: str = Field(strict=True, min_length=1, max_length=256)
44
+
45
+
46
+ class MemoryUpdate(MemoryRecordSelector, MemoryWrite):
47
+ pass
48
+
49
+
50
+ class AicpMemoryProvider:
51
+ """An explicit activation instance. Never resolves credentials or user IDs from env.
52
+
53
+ The caller supplies an admitted backend and identity. This search adapter does
54
+ not turn an asynchronous submission into the synchronous upsert contract.
55
+ """
56
+
57
+ def __init__(
58
+ self, config: ResourceConfig, identity: InvocationIdentity, backend: SdkLTMBackend
59
+ ):
60
+ if config.binding.resource.kind != "memory-instance":
61
+ raise ValueError("MemoryProvider requires a memory-instance binding")
62
+ if not backend.access_key or not backend.secret_key:
63
+ raise ValueError("MemoryProvider requires explicit signing credentials")
64
+ if (
65
+ backend._effective_memory_collection_id() != config.binding.resource.id
66
+ or backend.region != config.binding.resource.region
67
+ ):
68
+ raise ValueError("Memory backend does not match the resource binding")
69
+ self.config = config
70
+ self.identity = identity
71
+ self.partition = identity.memory_partition(config.binding.resource)
72
+ self._backend = backend
73
+ self._lock = threading.Lock()
74
+ self._observed_ids: dict[str, None] = {}
75
+ self._upstream_forbidden = False
76
+
77
+ @contextmanager
78
+ def _backend_call(self):
79
+ """Keep observed authorization failures sticky for this activation."""
80
+ with self._lock:
81
+ if self._upstream_forbidden:
82
+ raise ResourceUpstreamAuthorizationError()
83
+ self._backend.last_http_status = None
84
+ try:
85
+ yield
86
+ finally:
87
+ if self._backend.last_http_status in {401, 403}:
88
+ self._upstream_forbidden = True
89
+ self._observed_ids.clear()
90
+ raise ResourceUpstreamAuthorizationError() from None
91
+
92
+ def capabilities(self) -> MemoryCapabilities:
93
+ # The SDK exposes a query operation but no advertised search-mode or CAS
94
+ # guarantee. Do not invent capabilities from the presence of a method.
95
+ return MemoryCapabilities(
96
+ semantic_search=False,
97
+ keyword_search=False,
98
+ metadata_filter=False,
99
+ versioned_update=False,
100
+ hard_delete=False,
101
+ ttl=False,
102
+ max_record_chars=8192,
103
+ )
104
+
105
+ def search(self, request: MemorySearchRequest) -> MemorySearchResult:
106
+ started = time.monotonic()
107
+
108
+ def result(status, records=None, error=None, truncated=False):
109
+ return MemorySearchResult(
110
+ status=status,
111
+ records=records or [],
112
+ error_code=error,
113
+ provider="aicp",
114
+ latency_ms=int((time.monotonic() - started) * 1000),
115
+ accounting_accuracy="estimated",
116
+ truncated_by_budget=truncated,
117
+ )
118
+
119
+ if request.scopes != [("user", self.partition)]:
120
+ return result("unauthorized", error="MEMORY_SCOPE_MISMATCH")
121
+ if request.filters or request.as_of or request.memory_types or request.min_score != 0:
122
+ return result("failed", error="MEMORY_SEARCH_POLICY_UNSUPPORTED")
123
+ if (
124
+ type(request.top_k) is not int
125
+ or not 1 <= request.top_k <= 64
126
+ or type(request.max_tokens) is not int
127
+ or not 0 <= request.max_tokens <= 100000
128
+ or not isinstance(request.query, str)
129
+ or len(request.query) > 16000
130
+ ):
131
+ return result("failed", error="MEMORY_SEARCH_ARGUMENTS_INVALID")
132
+ if request.max_tokens == 0:
133
+ return result("ok", truncated=True)
134
+ try:
135
+ with self._backend_call():
136
+ records = self._backend.search_records(
137
+ self.partition, request.query, request.top_k, strict=True
138
+ )
139
+ projected = []
140
+ remaining = request.max_tokens
141
+ truncated = len(records) > request.top_k
142
+ for item in records[: request.top_k]:
143
+ if (
144
+ item.user_id != self.partition
145
+ or item.metadata.get("AgentUserId", self.partition) != self.partition
146
+ or not item.memory_id
147
+ or item.score is not None
148
+ and not math.isfinite(item.score)
149
+ ):
150
+ return result("failed", error="MEMORY_SEARCH_RESPONSE_INVALID")
151
+ content = item.content[:8192]
152
+ # Byte accounting is conservative for ordinary text tokenizers;
153
+ # accuracy remains explicitly estimated in the public result.
154
+ cost = len(content.encode("utf-8"))
155
+ if cost > remaining:
156
+ truncated = True
157
+ break
158
+ remaining -= cost
159
+ truncated |= len(content) != len(item.content)
160
+ projected.append(
161
+ MemoryRecord(
162
+ memory_id=item.memory_id,
163
+ tenant_id=self.identity.tenant_ref,
164
+ workspace_id="",
165
+ scope="user",
166
+ scope_id=self.partition,
167
+ memory_type="unknown",
168
+ content=content,
169
+ summary=content,
170
+ status="active",
171
+ confidence=None,
172
+ importance=None,
173
+ valid_from="",
174
+ valid_to="",
175
+ expires_at="",
176
+ source_session_id=item.session_id,
177
+ source_event_ids=[],
178
+ source_seq_range=None,
179
+ content_hash="sha256:" + hashlib.sha256(content.encode()).hexdigest(),
180
+ version=None,
181
+ metadata={"bindingId": self.config.binding.id, "score": item.score},
182
+ created_at=item.created_at or "",
183
+ updated_at=item.updated_at or "",
184
+ )
185
+ )
186
+ with self._lock:
187
+ for record in projected:
188
+ self._observed_ids[record.memory_id] = None
189
+ while len(self._observed_ids) > 256:
190
+ del self._observed_ids[next(iter(self._observed_ids))]
191
+ return result("ok", projected, truncated=truncated)
192
+ except ResourceUpstreamAuthorizationError:
193
+ return result("unauthorized", error="RESOURCE_FORBIDDEN")
194
+ except Exception:
195
+ return result("failed", error="MEMORY_SEARCH_FAILED")
196
+
197
+ def get(self, memory_id: str) -> MemoryRecord | None:
198
+ raise UnsupportedMemoryOperation("AICP does not expose a bound get-by-ID contract")
199
+
200
+ def submit(self, arguments: dict, *, operation_id: str) -> dict:
201
+ """Host-approved submission; each operation has a separate extraction session.
202
+
203
+ The broker supplies the durable operation ID, never a model parameter.
204
+ A transport acknowledgment proves acceptance only, not indexing or IDs.
205
+ """
206
+ request = MemoryWrite.model_validate(arguments)
207
+ if (
208
+ not request.content.strip()
209
+ or len(operation_id) != 64
210
+ or any(char not in "0123456789abcdef" for char in operation_id)
211
+ ):
212
+ raise ValueError("MEMORY_WRITE_ARGUMENTS_INVALID")
213
+ # AICP limits SessionId to 64 characters. The broker operation ID is
214
+ # already a 64-character lowercase hex digest, so use it directly.
215
+ # Prefixing it made every real submission 73 characters long and the
216
+ # service rejected the write before extraction could start.
217
+ session_id = operation_id
218
+ event = json.dumps({"role": "user", "parts": [{"text": request.content}]})
219
+ with self._backend_call():
220
+ try:
221
+ accepted = self._backend.save_memory(
222
+ self.partition, [event], session_id=session_id, flush=True, strict=True
223
+ )
224
+ except Exception:
225
+ accepted = False
226
+ return {
227
+ "status": "accepted_pending" if accepted else "unknown",
228
+ "operationId": operation_id,
229
+ "searchable": False,
230
+ "errorCode": None if accepted else "MEMORY_WRITE_UNKNOWN",
231
+ }
232
+
233
+ def extraction_status(self, arguments: dict) -> dict:
234
+ query = MemoryStatusQuery.model_validate(arguments)
235
+ with self._backend_call():
236
+ result = self._backend.get_extraction_status(
237
+ user_id=self.partition,
238
+ session_id=query.operation_id,
239
+ )
240
+ return {
241
+ "operationId": query.operation_id,
242
+ "extractionStatus": result.status,
243
+ "searchable": False,
244
+ "errorCode": result.error_code or None,
245
+ }
246
+
247
+ def mutate(self, operation: str, arguments: dict, *, operation_id: str) -> dict:
248
+ """Post-approval management of IDs observed in this bound user partition.
249
+
250
+ IDs are not authorization tokens: upstream receives the bound user on every
251
+ request. Restart requires fresh search. No CAS, hard deletion, or retry is
252
+ implied, and an ambiguous response permanently consumes the observed ID.
253
+ """
254
+ MemoryStatusQuery(operation_id=operation_id)
255
+ if operation == "update_memory":
256
+ query = MemoryUpdate.model_validate(arguments)
257
+ if not query.content.strip():
258
+ raise ValueError("MEMORY_WRITE_ARGUMENTS_INVALID")
259
+ elif operation == "delete_memory":
260
+ query = MemoryRecordSelector.model_validate(arguments)
261
+ else:
262
+ raise ValueError("Unsupported memory mutation")
263
+ reply = {
264
+ "operationId": operation_id,
265
+ "memoryId": query.memory_id,
266
+ "newMemoryId": "",
267
+ "status": "unknown",
268
+ "errorCode": "MEMORY_MUTATION_UNKNOWN",
269
+ }
270
+ with self._backend_call():
271
+ if query.memory_id not in self._observed_ids:
272
+ return {**reply, "status": "failed", "errorCode": "MEMORY_RECORD_NOT_OBSERVED"}
273
+ del self._observed_ids[query.memory_id]
274
+ try:
275
+ if operation == "update_memory":
276
+ outcome = self._backend.update_memory(
277
+ user_id=self.partition,
278
+ memory_id=query.memory_id,
279
+ content=query.content,
280
+ strict=True,
281
+ )
282
+ else:
283
+ outcome = self._backend.delete_memory(
284
+ user_id=self.partition,
285
+ memory_id=query.memory_id,
286
+ strict=True,
287
+ )
288
+ expected = (
289
+ {"updated"} if operation == "update_memory" else {"deleted", "already_absent"}
290
+ )
291
+ if outcome.ok and outcome.status in expected:
292
+ new_id = outcome.new_memory_id if operation == "update_memory" else ""
293
+ if not isinstance(new_id, str) or len(new_id) > 256:
294
+ return reply
295
+ if new_id:
296
+ self._observed_ids[new_id] = None
297
+ return {
298
+ **reply,
299
+ "status": "succeeded",
300
+ "newMemoryId": new_id,
301
+ "errorCode": None,
302
+ }
303
+ if outcome.status == "not_found":
304
+ return {**reply, "status": "failed", "errorCode": "MEMORY_RECORD_NOT_FOUND"}
305
+ except Exception:
306
+ pass
307
+ return reply
308
+
309
+ def upsert(self, record: MemoryRecord, *, expected_version: int | None) -> MemoryRecord:
310
+ raise UnsupportedMemoryOperation(
311
+ "AICP writes require an approved asynchronous operation receipt"
312
+ )
313
+
314
+ def delete(self, request: MemoryDeleteRequest) -> MemoryDeleteResult:
315
+ raise UnsupportedMemoryOperation("AICP deletion requires an approved operation receipt")
316
+
317
+ def list_core(self, request: CoreMemoryRequest) -> list[MemoryRecord]:
318
+ raise UnsupportedMemoryOperation("AICP does not expose core-memory blocks")
@@ -0,0 +1,34 @@
1
+ """Bounded memory mutation metadata; never includes the stored memory body."""
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field, model_validator
6
+
7
+ from ksadk.plugins.contracts import PluginContractModel
8
+
9
+
10
+ class MemoryMutationReceipt(PluginContractModel):
11
+ operation_id: str = Field(strict=True, pattern=r"^[0-9a-f]{64}$")
12
+ memory_id: str = Field(strict=True, min_length=1, max_length=256)
13
+ new_memory_id: str = Field(default="", strict=True, max_length=256)
14
+ status: Literal["succeeded", "failed", "unknown"]
15
+ error_code: (
16
+ Literal["MEMORY_MUTATION_UNKNOWN", "MEMORY_RECORD_NOT_OBSERVED", "MEMORY_RECORD_NOT_FOUND"]
17
+ | None
18
+ )
19
+
20
+ @model_validator(mode="after")
21
+ def consistent_result(self):
22
+ if self.status == "succeeded":
23
+ if self.error_code is not None:
24
+ raise ValueError("Successful mutation cannot carry an error")
25
+ elif self.new_memory_id:
26
+ raise ValueError("Unconfirmed mutation cannot grant a new record ID")
27
+ elif self.status == "unknown" and self.error_code != "MEMORY_MUTATION_UNKNOWN":
28
+ raise ValueError("Unknown mutation requires an unknown result code")
29
+ elif self.status == "failed" and self.error_code not in {
30
+ "MEMORY_RECORD_NOT_OBSERVED",
31
+ "MEMORY_RECORD_NOT_FOUND",
32
+ }:
33
+ raise ValueError("Failed mutation requires a confirmed rejection")
34
+ return self
@@ -0,0 +1,211 @@
1
+ """Durable duplicate suppression for host-authorized resource writes.
2
+
3
+ This ledger is not an approval authority. The host supplies a stable event ID
4
+ across checkpoint recovery and an identity/binding digest after admission.
5
+ Claiming commits before dispatch. A lost claimant leaves an unknown operation;
6
+ opening the database never grants permission to resend it.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import sqlite3
14
+ from contextlib import contextmanager
15
+ from dataclasses import dataclass
16
+ from pathlib import Path
17
+ from typing import Literal
18
+
19
+ from ksadk.resource_runtime.memory_receipts import MemoryMutationReceipt
20
+
21
+ OperationState = Literal["unknown", "accepted_pending", "searchable", "succeeded", "failed"]
22
+ _TRANSITIONS = {
23
+ "unknown": {"accepted_pending", "searchable", "succeeded", "failed"},
24
+ "accepted_pending": {"searchable", "failed"},
25
+ "searchable": set(),
26
+ "succeeded": set(),
27
+ "failed": set(),
28
+ }
29
+
30
+
31
+ @dataclass(frozen=True)
32
+ class OperationReceipt:
33
+ operation_id: str
34
+ state: OperationState
35
+ claimed: bool
36
+
37
+
38
+ class OperationConflict(ValueError):
39
+ """The same event was reused with different arguments or an invalid transition."""
40
+
41
+
42
+ class OperationLedger:
43
+ """SQLite ledger in a host-owned private directory; no request bodies stored.
44
+
45
+ Each method uses its own transaction so independent runtime processes share
46
+ duplicate suppression. Retention must cover all recoverable checkpoints.
47
+ Callers may record failed only after authoritative failure, never timeout.
48
+ """
49
+
50
+ def __init__(self, directory: Path):
51
+ directory = Path(directory)
52
+ directory.mkdir(mode=0o700, parents=True, exist_ok=True)
53
+ if directory.is_symlink() or directory.stat().st_mode & 0o077:
54
+ raise ValueError("Operation ledger requires a private directory")
55
+ self.path = directory / "resource-operations.sqlite3"
56
+ if self.path.is_symlink():
57
+ raise ValueError("Operation ledger cannot be a symbolic link")
58
+ with self._connect() as connection:
59
+ connection.execute(
60
+ "CREATE TABLE IF NOT EXISTS operations ("
61
+ "id TEXT PRIMARY KEY, request_digest TEXT NOT NULL, state TEXT NOT NULL)"
62
+ )
63
+ connection.execute(
64
+ "CREATE TABLE IF NOT EXISTS operation_owners ("
65
+ "id TEXT PRIMARY KEY, authority_digest TEXT NOT NULL, operation TEXT NOT NULL)"
66
+ )
67
+ connection.execute(
68
+ "CREATE TABLE IF NOT EXISTS memory_mutation_results ("
69
+ "id TEXT PRIMARY KEY, payload TEXT NOT NULL)"
70
+ )
71
+ self.path.chmod(0o600)
72
+
73
+ @contextmanager
74
+ def _connect(self):
75
+ connection = sqlite3.connect(self.path, timeout=10)
76
+ try:
77
+ with connection:
78
+ yield connection
79
+ finally:
80
+ connection.close()
81
+
82
+ @staticmethod
83
+ def _key(authority_digest: str, event_id: str, operation: str) -> str:
84
+ if not all(
85
+ isinstance(v, str) and 0 < len(v) <= 1024
86
+ for v in (authority_digest, event_id, operation)
87
+ ):
88
+ raise ValueError("Invalid operation identity")
89
+ payload = json.dumps(
90
+ ["resource-operation-v1", authority_digest, event_id, operation],
91
+ separators=(",", ":"),
92
+ ensure_ascii=True,
93
+ )
94
+ return hashlib.sha256(payload.encode()).hexdigest()
95
+
96
+ def claim(
97
+ self, *, authority_digest: str, event_id: str, operation: str, arguments: dict
98
+ ) -> OperationReceipt:
99
+ operation_id = self._key(authority_digest, event_id, operation)
100
+ encoded = json.dumps(arguments, sort_keys=True, separators=(",", ":"), allow_nan=False)
101
+ request_digest = hashlib.sha256(encoded.encode()).hexdigest()
102
+ with self._connect() as connection:
103
+ connection.execute("BEGIN IMMEDIATE")
104
+ row = connection.execute(
105
+ "SELECT request_digest, state FROM operations WHERE id = ?", (operation_id,)
106
+ ).fetchone()
107
+ if row is not None:
108
+ if row[0] != request_digest:
109
+ raise OperationConflict("RESOURCE_OPERATION_ARGUMENTS_CHANGED")
110
+ connection.execute(
111
+ "INSERT OR IGNORE INTO operation_owners VALUES (?, ?, ?)",
112
+ (operation_id, authority_digest, operation),
113
+ )
114
+ return OperationReceipt(operation_id, row[1], False)
115
+ connection.execute(
116
+ "INSERT INTO operations VALUES (?, ?, 'unknown')", (operation_id, request_digest)
117
+ )
118
+ connection.execute(
119
+ "INSERT INTO operation_owners VALUES (?, ?, ?)",
120
+ (operation_id, authority_digest, operation),
121
+ )
122
+ return OperationReceipt(operation_id, "unknown", True)
123
+
124
+ def lookup(
125
+ self, operation_id: str, *, authority_digest: str, operation: str
126
+ ) -> OperationReceipt | None:
127
+ """Opaque IDs alone grant no access. Legacy rows without owners stay hidden."""
128
+ with self._connect() as connection:
129
+ row = connection.execute(
130
+ "SELECT o.state FROM operations o JOIN operation_owners p ON o.id=p.id "
131
+ "WHERE o.id=? AND p.authority_digest=? AND p.operation=?",
132
+ (operation_id, authority_digest, operation),
133
+ ).fetchone()
134
+ return None if row is None else OperationReceipt(operation_id, row[0], False)
135
+
136
+ def record(self, operation_id: str, state: OperationState) -> OperationReceipt:
137
+ with self._connect() as connection:
138
+ connection.execute("BEGIN IMMEDIATE")
139
+ row = connection.execute(
140
+ "SELECT state FROM operations WHERE id = ?", (operation_id,)
141
+ ).fetchone()
142
+ if row is None or state not in _TRANSITIONS:
143
+ raise OperationConflict("RESOURCE_OPERATION_UNKNOWN")
144
+ if state != row[0] and state not in _TRANSITIONS[row[0]]:
145
+ raise OperationConflict("RESOURCE_OPERATION_STATE_CONFLICT")
146
+ connection.execute(
147
+ "UPDATE operations SET state = ? WHERE id = ?", (state, operation_id)
148
+ )
149
+ return OperationReceipt(operation_id, state, False)
150
+
151
+ def record_memory_mutation(
152
+ self,
153
+ result: MemoryMutationReceipt,
154
+ *,
155
+ authority_digest: str,
156
+ operation: str,
157
+ ) -> OperationReceipt:
158
+ """Commit terminal state and returned record IDs in one transaction."""
159
+ result = MemoryMutationReceipt.model_validate(result.model_dump())
160
+ if operation not in {"update_memory", "delete_memory"} or result.status == "unknown":
161
+ raise OperationConflict("RESOURCE_OPERATION_RESULT_INVALID")
162
+ if operation == "delete_memory" and result.new_memory_id:
163
+ raise OperationConflict("RESOURCE_OPERATION_RESULT_INVALID")
164
+ payload = result.model_dump_json(by_alias=True)
165
+ with self._connect() as connection:
166
+ connection.execute("BEGIN IMMEDIATE")
167
+ row = connection.execute(
168
+ "SELECT o.state FROM operations o JOIN operation_owners p ON o.id=p.id "
169
+ "WHERE o.id=? AND p.authority_digest=? AND p.operation=?",
170
+ (result.operation_id, authority_digest, operation),
171
+ ).fetchone()
172
+ if row is None:
173
+ raise OperationConflict("RESOURCE_OPERATION_UNKNOWN")
174
+ if result.status != row[0] and result.status not in _TRANSITIONS[row[0]]:
175
+ raise OperationConflict("RESOURCE_OPERATION_STATE_CONFLICT")
176
+ previous = connection.execute(
177
+ "SELECT payload FROM memory_mutation_results WHERE id=?",
178
+ (result.operation_id,),
179
+ ).fetchone()
180
+ if previous is not None and previous[0] != payload:
181
+ raise OperationConflict("RESOURCE_OPERATION_RESULT_CONFLICT")
182
+ connection.execute(
183
+ "INSERT OR IGNORE INTO memory_mutation_results VALUES (?, ?)",
184
+ (result.operation_id, payload),
185
+ )
186
+ connection.execute(
187
+ "UPDATE operations SET state=? WHERE id=?",
188
+ (result.status, result.operation_id),
189
+ )
190
+ return OperationReceipt(result.operation_id, result.status, False)
191
+
192
+ def memory_mutation_result(
193
+ self,
194
+ operation_id: str,
195
+ *,
196
+ authority_digest: str,
197
+ operation: str,
198
+ ) -> dict | None:
199
+ with self._connect() as connection:
200
+ row = connection.execute(
201
+ "SELECT r.payload, o.state FROM memory_mutation_results r "
202
+ "JOIN operations o ON o.id=r.id JOIN operation_owners p ON p.id=r.id "
203
+ "WHERE r.id=? AND p.authority_digest=? AND p.operation=?",
204
+ (operation_id, authority_digest, operation),
205
+ ).fetchone()
206
+ if row is None:
207
+ return None
208
+ result = MemoryMutationReceipt.model_validate_json(row[0])
209
+ if result.operation_id != operation_id or result.status != row[1]:
210
+ raise OperationConflict("RESOURCE_OPERATION_RESULT_CONFLICT")
211
+ return result.model_dump(by_alias=True, mode="json")
@@ -0,0 +1,48 @@
1
+ """Data-only configuration contracts for the three official resource bundles.
2
+
3
+ These reserved plugin IDs map to scoped npm packages; recognizing an ID validates
4
+ configuration only. Installation identity and authorization still require Build
5
+ receipts and trusted activation admission.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Mapping, Sequence
11
+ from typing import Any
12
+
13
+ from ksadk.resource_runtime.contracts import ResourceConfig, validate_resource_bindings
14
+
15
+ OFFICIAL_RESOURCE_PLUGINS = {
16
+ "kingsoftcloud.dsh-knowledge": "knowledge-base",
17
+ "kingsoftcloud.dsh-memory": "memory-instance",
18
+ "kingsoftcloud.dsh-skill-center": "skill-space",
19
+ }
20
+
21
+
22
+ def resource_plugin_config(
23
+ plugin_ref: str, ecosystem: str, config: Mapping[str, Any], *, enabled: bool
24
+ ) -> ResourceConfig | None:
25
+ plugin_id = plugin_ref.removeprefix("plugin://").rsplit("@", 1)[0]
26
+ kind = OFFICIAL_RESOURCE_PLUGINS.get(plugin_id)
27
+ if kind is None:
28
+ return None
29
+ if ecosystem != "dsh":
30
+ raise ValueError("Official platform resource plugins require the DSH ecosystem")
31
+ if not config and not enabled:
32
+ return None
33
+ parsed = ResourceConfig.model_validate(config)
34
+ if parsed.binding.resource.kind != kind:
35
+ raise ValueError("Resource kind does not match the official plugin")
36
+ return parsed
37
+
38
+
39
+ def validate_resource_plugin_bindings(bindings: Sequence[Any]) -> None:
40
+ resources = []
41
+ for binding in bindings:
42
+ if binding.enabled:
43
+ resource = resource_plugin_config(
44
+ binding.plugin_ref, binding.ecosystem, binding.config, enabled=True
45
+ )
46
+ if resource is not None:
47
+ resources.append(resource)
48
+ validate_resource_bindings(tuple(resources))
@@ -0,0 +1,54 @@
1
+ """Request-scoped host authorization for resource writes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import json
7
+
8
+ from ksadk.resource_runtime.ipc import ResourceRequest
9
+ from ksadk.resource_runtime.leases import ResourceScope
10
+
11
+ _WRITES = frozenset({"save_memory", "update_memory", "delete_memory", "execute_skills"})
12
+
13
+
14
+ class FullAccessResourceWriteAuthorizer:
15
+ """Authorize exact writes covered by a trusted full-access invocation.
16
+
17
+ The Studio/API ingress chooses the approval profile. Capability plugins only
18
+ receive this authorizer after the trusted host has resolved that profile for
19
+ the current activation. The returned event reference binds the decision to
20
+ the exact scope and arguments so OperationLedger can fence retries.
21
+ """
22
+
23
+ def __init__(self, *, activation_key: str) -> None:
24
+ if not activation_key or any(character.isspace() for character in activation_key):
25
+ raise ValueError("RESOURCE_APPROVAL_ACTIVATION_INVALID")
26
+ self._activation_key = activation_key
27
+
28
+ async def authorize(self, request: ResourceRequest, scope: ResourceScope) -> str | None:
29
+ if request.operation not in _WRITES or request.operation not in scope.allowed_operations:
30
+ return None
31
+ payload = {
32
+ "version": 1,
33
+ "approvalProfile": "full",
34
+ "activationKey": self._activation_key,
35
+ "identity": scope.identity.model_dump(mode="json"),
36
+ "build": scope.build_digest,
37
+ "binding": scope.binding_id,
38
+ "snapshot": scope.binding_snapshot_digest,
39
+ "operation": request.operation,
40
+ "arguments": request.arguments,
41
+ }
42
+ digest = hashlib.sha256(
43
+ json.dumps(
44
+ payload,
45
+ ensure_ascii=False,
46
+ sort_keys=True,
47
+ separators=(",", ":"),
48
+ allow_nan=False,
49
+ ).encode()
50
+ ).hexdigest()
51
+ return f"studio-full-access:{digest}"
52
+
53
+
54
+ __all__ = ["FullAccessResourceWriteAuthorizer"]