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
ksadk/studio/api.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
+ import base64
6
7
  import hmac
7
8
  import json
8
9
  import os
@@ -18,8 +19,18 @@ from fastapi.responses import FileResponse, JSONResponse, StreamingResponse
18
19
  from fastapi.staticfiles import StaticFiles
19
20
  from starlette.background import BackgroundTask
20
21
 
22
+ from ksadk.api.client import AgentEngineAPIError
23
+ from ksadk.conversations.contracts import (
24
+ ConversationAttachmentPart,
25
+ ConversationTextPart,
26
+ validate_conversation_input,
27
+ )
28
+ from ksadk.conversations.projector import project_conversation_item
29
+ from ksadk.events.canonical import parse_runtime_event_lenient
30
+ from ksadk.scheduler.contracts import ScheduledTask
21
31
  from ksadk.studio.api_catalog_routes import register_catalog_routes
22
32
  from ksadk.studio.api_contracts import (
33
+ AgentScheduleRequest,
23
34
  AuthoringCommitRequest,
24
35
  BuildRequest,
25
36
  CloudAgentVersionRollbackRequest,
@@ -27,6 +38,7 @@ from ksadk.studio.api_contracts import (
27
38
  CloudChatMessageRequest,
28
39
  ContextPreviewRequest,
29
40
  ConversationAuthoringRequest,
41
+ ConversationTurnRequest,
30
42
  CreateAgentRequest,
31
43
  ImportRootRequest,
32
44
  InteractionSubmitRequest,
@@ -65,6 +77,9 @@ from ksadk.studio.api_helpers import (
65
77
  sse as _sse,
66
78
  )
67
79
  from ksadk.studio.api_memory_routes import register_memory_routes
80
+ from ksadk.studio.api_plugin_routes import register_plugin_routes
81
+ from ksadk.studio.api_resource_connections import register_resource_connection_routes
82
+ from ksadk.studio.cloud_shared_web import CloudSharedWebBridge, cloud_chat_target, is_cloud_agent_id
68
83
  from ksadk.studio.codex_manifest import CodexAgentManifest
69
84
  from ksadk.studio.contracts import (
70
85
  AgentAppearance,
@@ -85,6 +100,113 @@ _PUBLIC_API_PATHS = {
85
100
  }
86
101
  _LOCAL_HOSTS = {"127.0.0.1", "::1", "localhost", "testserver"}
87
102
 
103
+ # RuntimeEvent/v2 itself is snake_case. Some pre-existing cloud SessionEvent
104
+ # projections, however, serialized the *envelope* with the REST camelCase
105
+ # convention. This is a narrow transport normalizer, not a provider payload
106
+ # rewrite: only fields owned by the frozen RuntimeEvent envelope/content
107
+ # contracts are translated before strict parsing.
108
+ _RUNTIME_EVENT_WIRE_ALIASES = {
109
+ "schemaVersion": "schema_version",
110
+ "eventId": "event_id",
111
+ "runId": "run_id",
112
+ "runSeq": "run_seq",
113
+ "scopeId": "scope_id",
114
+ "parentScopeId": "parent_scope_id",
115
+ "eventType": "event_type",
116
+ "itemId": "item_id",
117
+ "itemKind": "item_kind",
118
+ "interactionId": "interaction_id",
119
+ "interactionKind": "interaction_kind",
120
+ "continuationId": "continuation_id",
121
+ "resumeAttemptId": "resume_attempt_id",
122
+ "outputRefs": "output_refs",
123
+ "inputTokens": "input_tokens",
124
+ "outputTokens": "output_tokens",
125
+ "totalTokens": "total_tokens",
126
+ "cachedTokens": "cached_tokens",
127
+ "reasoningTokens": "reasoning_tokens",
128
+ }
129
+ _SOURCE_WIRE_ALIASES = {
130
+ "nativeEventId": "native_event_id",
131
+ "nativeCursor": "native_cursor",
132
+ "nativeRunId": "native_run_id",
133
+ "nativeItemId": "native_item_id",
134
+ }
135
+ _CONTENT_WIRE_ALIASES = {
136
+ "contentType": "content_type",
137
+ "partId": "part_id",
138
+ "callId": "call_id",
139
+ "artifactId": "artifact_id",
140
+ "mimeType": "mime_type",
141
+ "isError": "is_error",
142
+ }
143
+
144
+
145
+ def _normalize_cloud_runtime_event_wire(value: dict[str, Any]) -> dict[str, Any]:
146
+ """Normalize only historic REST casing at the RuntimeEvent boundary."""
147
+
148
+ normalized = {_RUNTIME_EVENT_WIRE_ALIASES.get(key, key): item for key, item in value.items()}
149
+ source = normalized.get("source")
150
+ if isinstance(source, dict):
151
+ normalized["source"] = {
152
+ _SOURCE_WIRE_ALIASES.get(key, key): item for key, item in source.items()
153
+ }
154
+
155
+ def normalize_content(content: Any) -> Any:
156
+ if not isinstance(content, dict):
157
+ return content
158
+ return {_CONTENT_WIRE_ALIASES.get(key, key): item for key, item in content.items()}
159
+
160
+ normalized["update"] = normalize_content(normalized.get("update"))
161
+ for key in ("initial", "snapshot"):
162
+ snapshot = normalized.get(key)
163
+ if not isinstance(snapshot, dict):
164
+ continue
165
+ parts = snapshot.get("parts")
166
+ if isinstance(parts, list):
167
+ normalized[key] = {
168
+ **snapshot,
169
+ "parts": [normalize_content(part) for part in parts],
170
+ }
171
+ return normalized
172
+
173
+
174
+ def _cloud_event_conversation_item(
175
+ event: dict[str, Any], *, session_id: str
176
+ ) -> dict[str, Any] | None:
177
+ """Project a complete cloud RuntimeEvent without inventing a browser item.
178
+
179
+ Cloud SessionEvent history has a compatibility envelope around the runtime
180
+ payload. Keep the source event untouched, but add the same typed
181
+ ConversationItem that local Studio streams use whenever the nested event
182
+ validates against RuntimeEvent/v2. A malformed or older envelope is still
183
+ observable to diagnostics, never guessed into an actionable chat card.
184
+ """
185
+
186
+ payload = event.get("payload") if isinstance(event.get("payload"), dict) else event
187
+ content = payload.get("content") if isinstance(payload.get("content"), dict) else {}
188
+ candidates = (
189
+ content.get("runtime_event"),
190
+ content.get("runtimeEvent"),
191
+ payload.get("runtime_event"),
192
+ payload.get("runtimeEvent"),
193
+ event.get("runtime_event"),
194
+ event.get("runtimeEvent"),
195
+ )
196
+ raw_event = next((candidate for candidate in candidates if isinstance(candidate, dict)), None)
197
+ if raw_event is None:
198
+ return None
199
+ try:
200
+ runtime_event = parse_runtime_event_lenient(_normalize_cloud_runtime_event_wire(raw_event))
201
+ item = project_conversation_item(
202
+ runtime_event, # type: ignore[arg-type]
203
+ session_id=session_id,
204
+ run_id=runtime_event.run_id,
205
+ )
206
+ except (TypeError, ValueError):
207
+ return None
208
+ return item.model_dump(by_alias=True, exclude_none=True, mode="json")
209
+
88
210
 
89
211
  def create_studio_app(
90
212
  root: Path | str,
@@ -101,9 +223,13 @@ def create_studio_app(
101
223
  @asynccontextmanager
102
224
  async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
103
225
  try:
226
+ await studio.start()
104
227
  await studio.run_service.recover_interrupted()
228
+ await studio.scheduler.start_if_available()
105
229
  yield
106
230
  finally:
231
+ await studio.scheduler.stop()
232
+ await studio.aclose()
107
233
  studio.credentials.clear_session()
108
234
 
109
235
  app = FastAPI(
@@ -117,8 +243,88 @@ def create_studio_app(
117
243
  app.state.studio_service = studio
118
244
  app.state.session_token = session_secret
119
245
  app.state.csrf_token = csrf_secret
246
+ from ksadk.studio.dsh_models import studio_model_projection
247
+
248
+ studio.dsh_capabilities.model_projection = lambda: studio_model_projection(
249
+ studio.catalog, studio.credentials
250
+ )
251
+
252
+ def _stream_studio_run(
253
+ build_id: str,
254
+ *,
255
+ user_input: str,
256
+ session_id: str | None,
257
+ model: str | None,
258
+ sandbox: str | None,
259
+ reasoning_effort: str | None = None,
260
+ approval_mode: str | None = None,
261
+ collaboration_mode: str | None = None,
262
+ goal_objective: str | None = None,
263
+ runtime_input: Any = None,
264
+ idempotency_key: str,
265
+ ) -> StreamingResponse:
266
+ """Create an observer-only SSE response for one durable Studio run."""
267
+
268
+ queue: asyncio.Queue = asyncio.Queue()
269
+
270
+ def observe(event):
271
+ queue.put_nowait(event)
272
+
273
+ # The Operation owns the runtime task. The SSE response is only one
274
+ # observer, so refreshing or switching chats cannot cancel the Run.
275
+ operation = studio.submit_studio_run(
276
+ build_id,
277
+ user_input,
278
+ session_id=session_id,
279
+ model=model,
280
+ sandbox=sandbox,
281
+ reasoning_effort=reasoning_effort,
282
+ approval_mode=approval_mode,
283
+ collaboration_mode=collaboration_mode,
284
+ goal_objective=goal_objective,
285
+ runtime_input=runtime_input,
286
+ idempotency_key=idempotency_key,
287
+ on_event=observe,
288
+ )
289
+
290
+ async def render():
291
+ while True:
292
+ try:
293
+ event = await asyncio.wait_for(queue.get(), timeout=0.1)
294
+ except TimeoutError:
295
+ event = None
296
+ if event is not None:
297
+ data = json.dumps(
298
+ event.data,
299
+ ensure_ascii=False,
300
+ separators=(",", ":"),
301
+ )
302
+ yield f"id: {event.id}\nevent: {event.type}\ndata: {data}\n\n"
303
+ current = studio.operations.get(operation.id)
304
+ if (
305
+ current.status
306
+ in {
307
+ OperationStatus.SUCCEEDED,
308
+ OperationStatus.FAILED,
309
+ OperationStatus.CANCELLED,
310
+ OperationStatus.INTERRUPTED,
311
+ }
312
+ and queue.empty()
313
+ ):
314
+ if current.status == OperationStatus.FAILED:
315
+ data = json.dumps(current.error or {}, ensure_ascii=False)
316
+ yield f"event: run.failed\ndata: {data}\n\n"
317
+ break
318
+
319
+ return StreamingResponse(
320
+ render(),
321
+ media_type="text/event-stream",
322
+ headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
323
+ )
324
+
120
325
  static_root = Path(__file__).with_name("static")
121
326
  shared_web = StudioSharedWebBridge(studio)
327
+ cloud_web = CloudSharedWebBridge(studio.cloud)
122
328
  app.state.shared_web_bridge = shared_web
123
329
  app.mount("/static", StaticFiles(directory=static_root), name="studio-static")
124
330
 
@@ -212,6 +418,39 @@ def create_studio_app(
212
418
  async def studio_error_handler(request: Request, exc: StudioError):
213
419
  return _error_response(exc, request)
214
420
 
421
+ @app.exception_handler(AgentEngineAPIError)
422
+ async def agentengine_api_error_handler(request: Request, exc: AgentEngineAPIError):
423
+ http_status = exc.details.get("http_status", 502)
424
+ status_code = (
425
+ http_status if isinstance(http_status, int) and 400 <= http_status < 600 else 502
426
+ )
427
+ return _error_response(
428
+ StudioError(
429
+ "CLOUD_API_ERROR",
430
+ exc.message or "云端服务返回错误",
431
+ status_code=status_code,
432
+ details={"api_code": exc.code, "raw_code": exc.raw_code},
433
+ ),
434
+ request,
435
+ )
436
+
437
+ @app.exception_handler(Exception)
438
+ async def generic_error_handler(request: Request, exc: Exception):
439
+ # Catch-all for bare Exception raises from the API client (e.g. HTTP
440
+ # errors, JSON parse failures) so they surface as structured JSON
441
+ # instead of opaque 500s. StudioError and AgentEngineAPIError are
442
+ # handled by their own dedicated handlers above.
443
+ if isinstance(exc, StudioError):
444
+ return _error_response(exc, request)
445
+ return _error_response(
446
+ StudioError(
447
+ "INTERNAL_ERROR",
448
+ "Studio 内部错误,请根据请求 ID 查看本地诊断日志。",
449
+ status_code=500,
450
+ ),
451
+ request,
452
+ )
453
+
215
454
  @app.exception_handler(RequestValidationError)
216
455
  async def validation_error_handler(request: Request, exc: RequestValidationError):
217
456
  first = exc.errors()[0] if exc.errors() else {}
@@ -229,7 +468,13 @@ def create_studio_app(
229
468
  @app.get("/")
230
469
  async def index():
231
470
  path = static_root / "index.html"
232
- response = FileResponse(path, media_type="text/html")
471
+ html = path.read_text(encoding="utf-8")
472
+ # Vite filenames are content hashed and index.html is no-store. Keep
473
+ # entry module URLs byte-for-byte identical to their internal imports:
474
+ # adding a query only to the HTML entry makes browsers evaluate that
475
+ # module again when a lazy chunk imports the unversioned URL.
476
+ response = Response(content=html, media_type="text/html")
477
+ response.headers["Cache-Control"] = "no-store"
233
478
  if security_enabled:
234
479
  response.set_cookie(
235
480
  "agentkit_studio_session",
@@ -272,9 +517,31 @@ def create_studio_app(
272
517
  async def openai_responses(payload: dict[str, Any]):
273
518
  metadata = payload.get("metadata")
274
519
  metadata = metadata if isinstance(metadata, dict) else {}
275
- agent_id = str(metadata.get("agent_id") or metadata.get("agentId") or "") or None
520
+ agentengine_metadata = metadata.get("agentengine")
521
+ agentengine_metadata = (
522
+ agentengine_metadata if isinstance(agentengine_metadata, dict) else {}
523
+ )
524
+ agent_id = (
525
+ str(
526
+ metadata.get("agent_id")
527
+ or metadata.get("agentId")
528
+ or agentengine_metadata.get("agent_id")
529
+ or agentengine_metadata.get("agentId")
530
+ or ""
531
+ )
532
+ or None
533
+ )
276
534
  requested_approval_mode = (
277
- str(metadata.get("approval_mode") or metadata.get("approvalMode") or "").strip().lower()
535
+ str(
536
+ metadata.get("approval_mode")
537
+ or metadata.get("approvalMode")
538
+ or agentengine_metadata.get("tool_approval_mode")
539
+ or agentengine_metadata.get("approval_mode")
540
+ or agentengine_metadata.get("approvalMode")
541
+ or ""
542
+ )
543
+ .strip()
544
+ .lower()
278
545
  )
279
546
  if requested_approval_mode and requested_approval_mode not in {"ask", "risk", "full"}:
280
547
  raise StudioError(
@@ -284,7 +551,13 @@ def create_studio_app(
284
551
  field="metadata.approval_mode",
285
552
  )
286
553
  collaboration_mode = (
287
- str(metadata.get("collaboration_mode") or metadata.get("collaborationMode") or "")
554
+ str(
555
+ metadata.get("collaboration_mode")
556
+ or metadata.get("collaborationMode")
557
+ or agentengine_metadata.get("collaboration_mode")
558
+ or agentengine_metadata.get("collaborationMode")
559
+ or ""
560
+ )
288
561
  .strip()
289
562
  .lower()
290
563
  )
@@ -296,7 +569,11 @@ def create_studio_app(
296
569
  field="metadata.collaboration_mode",
297
570
  )
298
571
  goal_objective = str(
299
- metadata.get("goal_objective") or metadata.get("goalObjective") or ""
572
+ metadata.get("goal_objective")
573
+ or metadata.get("goalObjective")
574
+ or agentengine_metadata.get("goal_objective")
575
+ or agentengine_metadata.get("goalObjective")
576
+ or ""
300
577
  ).strip()
301
578
  reasoning = payload.get("reasoning")
302
579
  reasoning = reasoning if isinstance(reasoning, dict) else {}
@@ -324,6 +601,7 @@ def create_studio_app(
324
601
  "CollaborationMode": collaboration_mode,
325
602
  "GoalObjective": goal_objective,
326
603
  "ReasoningEffort": reasoning_effort,
604
+ "ModelExplicit": bool(str(payload.get("model") or "").strip()),
327
605
  }
328
606
  bridge_payload["Model"] = shared_web.select_model(
329
607
  bridge_payload["AgentId"],
@@ -363,26 +641,113 @@ def create_studio_app(
363
641
  try:
364
642
  cookie_agent_id = request.cookies.get("agentkit_studio_chat_agent")
365
643
  requested_agent_id = str(payload.get("AgentId") or cookie_agent_id or "")
644
+ cloud_mode = is_cloud_agent_id(requested_agent_id)
645
+ if cloud_mode:
646
+ # Cloud agents project onto the same shared-web action
647
+ # contract through the cloud-chat proxy, so the ksadk-web
648
+ # headless data layer drives them like hosted-ui does.
649
+ cloud_target = cloud_chat_target(requested_agent_id)
650
+ data = None
651
+ if action == "GetAgentUiBootstrap":
652
+ data = await cloud_web.bootstrap(cloud_target)
653
+ elif action == "ListAgentModels":
654
+ data = await cloud_web.list_models(cloud_target)
655
+ elif action == "ListSessions":
656
+ data = await cloud_web.list_sessions(
657
+ cloud_target,
658
+ page=int(payload.get("Page") or 1),
659
+ page_size=int(payload.get("PageSize") or 30),
660
+ )
661
+ elif action == "CreateSession":
662
+ data = await cloud_web.create_session(cloud_target)
663
+ elif action == "GetSession":
664
+ data = await cloud_web.get_session(
665
+ cloud_target, str(payload.get("SessionId") or "")
666
+ )
667
+ elif action == "DeleteSession":
668
+ data = await cloud_web.delete_session(
669
+ cloud_target, str(payload.get("SessionId") or "")
670
+ )
671
+ elif action == "ListSessionMessages":
672
+ data = await cloud_web.list_messages(
673
+ cloud_target,
674
+ str(payload.get("SessionId") or ""),
675
+ after_seq_id=_optional_int(payload.get("AfterSeqId")),
676
+ before_seq_id=_optional_int(payload.get("BeforeSeqId")),
677
+ limit=int(payload.get("Limit") or 50),
678
+ )
679
+ elif action == "ListSessionEvents":
680
+ data = await cloud_web.list_session_events(
681
+ cloud_target,
682
+ str(payload.get("SessionId") or ""),
683
+ after_seq_id=_optional_int(payload.get("AfterSeqId")),
684
+ offset=_optional_int(payload.get("Offset")),
685
+ limit=int(payload.get("Limit") or 200),
686
+ )
687
+ elif action == "SubmitInteraction":
688
+ data = await cloud_web.submit_interaction(
689
+ cloud_target, str(payload.get("SessionId") or ""), payload
690
+ )
691
+ elif action == "RunAgent":
692
+ # Open the upstream connection before StreamingResponse
693
+ # commits status 200, so admission failures remain a
694
+ # structured HTTP error instead of an empty SSE body.
695
+ upstream_stream = await cloud_web.open_run_stream(cloud_target, payload)
696
+ return StreamingResponse(
697
+ cloud_web.stream_run(
698
+ cloud_target,
699
+ payload,
700
+ upstream_stream=upstream_stream,
701
+ ),
702
+ media_type="text/event-stream",
703
+ headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
704
+ )
705
+ elif action in {
706
+ "GetResponseFeedback",
707
+ "UpsertResponseFeedback",
708
+ "DeleteResponseFeedback",
709
+ "ListSessionCheckpoints",
710
+ "ListToolReceipts",
711
+ }:
712
+ data = {"Feedback": None} if action == "GetResponseFeedback" else {}
713
+ else:
714
+ return JSONResponse(
715
+ status_code=404,
716
+ content={
717
+ "Code": 404,
718
+ "Message": f"Studio 尚未实现云端共享 Web 动作:{action}",
719
+ "Data": {},
720
+ },
721
+ )
722
+ return {"Code": 0, "Message": "OK", "Data": data}
366
723
  if action == "GetAgentUiBootstrap":
367
724
  data = shared_web.bootstrap(shared_web.resolve_agent_id(requested_agent_id or None))
368
725
  elif action == "ListAgentModels":
369
- data = shared_web.list_models(
370
- shared_web.resolve_agent_id(requested_agent_id or None)
371
- )
726
+ model_agent_id = shared_web.resolve_agent_id(requested_agent_id or None)
727
+ # A cold Studio process has no discovered provider descriptors.
728
+ # Resolve the same cached catalog as Resources before projecting
729
+ # model windows; visiting Resources must not be a prerequisite.
730
+ await runtime_model_catalog()
731
+ data = shared_web.list_models(model_agent_id)
372
732
  elif action == "ListSessions":
373
- data = shared_web.list_sessions(
733
+ data = await shared_web.list_sessions(
374
734
  shared_web.resolve_agent_id(requested_agent_id or None),
375
735
  page=int(payload.get("Page") or 1),
376
736
  page_size=int(payload.get("PageSize") or 30),
377
737
  )
378
738
  elif action == "CreateSession":
379
- data = shared_web.create_session(
739
+ data = await shared_web.create_session(
380
740
  shared_web.resolve_agent_id(requested_agent_id or None)
381
741
  )
382
742
  elif action == "GetSession":
383
- data = shared_web.get_session(str(payload.get("SessionId") or ""))
743
+ data = await shared_web.get_session(str(payload.get("SessionId") or ""))
744
+ elif action == "CompactSession":
745
+ data = await shared_web.compact_session(
746
+ shared_web.resolve_agent_id(requested_agent_id or None),
747
+ str(payload.get("SessionId") or ""),
748
+ )
384
749
  elif action == "DeleteSession":
385
- data = shared_web.delete_session(str(payload.get("SessionId") or ""))
750
+ data = await shared_web.delete_session(str(payload.get("SessionId") or ""))
386
751
  elif action == "ListSessionMessages":
387
752
  data = await shared_web.list_messages(
388
753
  str(payload.get("SessionId") or ""),
@@ -393,8 +758,12 @@ def create_studio_app(
393
758
  elif action == "ListSessionEvents":
394
759
  data = await shared_web.list_session_events(str(payload.get("SessionId") or ""))
395
760
  elif action == "RunAgent":
761
+ # A cold process has not discovered provider model descriptors
762
+ # yet. Run admission may need to materialize a current Build,
763
+ # so chat must not depend on visiting the Models page first.
764
+ await runtime_model_catalog()
396
765
  return StreamingResponse(
397
- shared_web.stream_run(payload),
766
+ shared_web.stream_run(payload, shared_ui=True),
398
767
  media_type="text/event-stream",
399
768
  headers={
400
769
  "Cache-Control": "no-store",
@@ -403,6 +772,33 @@ def create_studio_app(
403
772
  )
404
773
  elif action == "CancelRun":
405
774
  data = shared_web.cancel_run(str(payload.get("InvocationId") or ""))
775
+ elif action == "SubmitInteraction":
776
+ run_id = str(payload.get("RunId") or "")
777
+ interaction_id = str(payload.get("InteractionId") or "")
778
+ resolved = await studio.run_service.submit_interaction(
779
+ run_id,
780
+ interaction_id,
781
+ name=str(payload.get("Action") or "submit"),
782
+ data=(
783
+ dict(payload.get("Response"))
784
+ if isinstance(payload.get("Response"), dict)
785
+ else {}
786
+ ),
787
+ expected_revision=int(payload.get("ExpectedRevision") or 0),
788
+ idempotency_key=str(payload.get("IdempotencyKey") or ""),
789
+ )
790
+ data = {
791
+ "schema_version": 1,
792
+ "command_id": str(
793
+ resolved.get("eventId")
794
+ or resolved.get("resolutionEventId")
795
+ or f"interaction:{interaction_id}"
796
+ ),
797
+ "status": "accepted",
798
+ "message_id": None,
799
+ "run_id": run_id,
800
+ "accepted_seq": int(resolved.get("eventId") or 0),
801
+ }
406
802
  elif action in {
407
803
  "GetResponseFeedback",
408
804
  "UpsertResponseFeedback",
@@ -434,12 +830,37 @@ def create_studio_app(
434
830
  )
435
831
 
436
832
  @app.get("/agentengine/api/v1/SubscribeRunEvents")
437
- async def shared_chat_subscribe_run_events():
438
- async def completed_stream():
439
- yield "event: done\ndata: [DONE]\n\n"
440
-
833
+ async def shared_chat_subscribe_run_events(
834
+ request: Request,
835
+ session_id: str = Query(alias="SessionId"),
836
+ invocation_id: str = Query(alias="InvocationId"),
837
+ after_seq_id: int = Query(default=0, alias="AfterSeqId", ge=0),
838
+ agent_id: str | None = Query(default=None, alias="AgentId"),
839
+ ):
840
+ requested_agent_id = str(
841
+ agent_id or request.cookies.get("agentkit_studio_chat_agent") or ""
842
+ )
843
+ if is_cloud_agent_id(requested_agent_id):
844
+ cloud_target = cloud_chat_target(requested_agent_id)
845
+ return StreamingResponse(
846
+ cloud_web.subscribe_run_events(
847
+ cloud_target,
848
+ session_id,
849
+ invocation_id,
850
+ after_seq_id=after_seq_id,
851
+ ),
852
+ media_type="text/event-stream",
853
+ headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
854
+ )
855
+ # Validate before StreamingResponse sends headers; invalid identities
856
+ # remain ordinary actionable HTTP errors.
857
+ await shared_web.subscription_run_id(session_id, invocation_id)
441
858
  return StreamingResponse(
442
- completed_stream(),
859
+ shared_web.subscribe_run_events(
860
+ session_id,
861
+ invocation_id,
862
+ after_seq_id=after_seq_id,
863
+ ),
443
864
  media_type="text/event-stream",
444
865
  headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
445
866
  )
@@ -491,6 +912,7 @@ def create_studio_app(
491
912
  "deployment": True,
492
913
  "cloudRebuild": False,
493
914
  "reactChat": True,
915
+ "scheduler": studio.scheduler.availability(),
494
916
  },
495
917
  "runtimes": studio.runtime_catalog(),
496
918
  "importableProject": studio.detect_importable_project(),
@@ -504,6 +926,116 @@ def create_studio_app(
504
926
  async def update_settings(payload: dict[str, Any]):
505
927
  return studio.update_settings(payload)
506
928
 
929
+ @app.get("/api/v1/schedules")
930
+ async def list_schedules():
931
+ return {
932
+ "items": studio.scheduler.list_tasks(),
933
+ "taskOccurrences": studio.scheduler.task_occurrence_summaries(),
934
+ "availability": studio.scheduler.availability(),
935
+ }
936
+
937
+ @app.post("/api/v1/schedules", status_code=201)
938
+ async def create_schedule(payload: ScheduledTask):
939
+ studio.validate_schedule_build(
940
+ payload.target.agent_version_ref,
941
+ agent_id=payload.target.agent_id,
942
+ )
943
+ return studio.scheduler.create_task(payload)
944
+
945
+ @app.get("/api/v1/schedules/{task_id}")
946
+ async def get_schedule(task_id: str):
947
+ return studio.scheduler.get_task(task_id)
948
+
949
+ @app.put("/api/v1/schedules/{task_id}")
950
+ async def update_schedule(task_id: str, payload: ScheduledTask):
951
+ studio.validate_schedule_build(
952
+ payload.target.agent_version_ref,
953
+ agent_id=payload.target.agent_id,
954
+ )
955
+ return studio.scheduler.update_task(task_id, payload)
956
+
957
+ @app.delete("/api/v1/schedules/{task_id}", status_code=204)
958
+ async def delete_schedule(task_id: str):
959
+ studio.scheduler.delete_task(task_id)
960
+ return Response(status_code=204)
961
+
962
+ @app.post("/api/v1/schedules/{task_id}:run", status_code=202)
963
+ async def run_schedule_now(task_id: str):
964
+ return await studio.scheduler.run_now(task_id)
965
+
966
+ @app.get("/api/v1/schedules/{task_id}/occurrences")
967
+ async def list_schedule_occurrences(task_id: str, limit: int = Query(default=50, ge=1, le=200)):
968
+ return {"items": studio.scheduler.list_occurrences(task_id, limit=limit)}
969
+
970
+ @app.get("/api/v1/schedule-occurrences")
971
+ async def list_all_schedule_occurrences(
972
+ limit: int = Query(default=200, ge=1, le=500),
973
+ ):
974
+ return {"items": studio.scheduler.list_all_occurrences(limit=limit)}
975
+
976
+ @app.get("/api/v1/agents/{agent_id}/schedules")
977
+ async def list_agent_schedules(agent_id: str):
978
+ return {
979
+ "items": studio.list_agent_schedules(agent_id),
980
+ "availability": studio.scheduler.availability(),
981
+ }
982
+
983
+ @app.post("/api/v1/agents/{agent_id}/schedules", status_code=201)
984
+ async def create_agent_schedule(agent_id: str, payload: AgentScheduleRequest):
985
+ return await studio.create_agent_schedule(
986
+ agent_id,
987
+ display_name=payload.display_name,
988
+ prompt=payload.prompt,
989
+ schedule=payload.schedule,
990
+ enabled=payload.enabled,
991
+ continuity=payload.continuity,
992
+ session_id=payload.session_id,
993
+ )
994
+
995
+ @app.get("/api/v1/agents/{agent_id}/schedules/{task_id}")
996
+ async def get_agent_schedule(agent_id: str, task_id: str):
997
+ return studio.get_agent_schedule(agent_id, task_id)
998
+
999
+ @app.put("/api/v1/agents/{agent_id}/schedules/{task_id}")
1000
+ async def update_agent_schedule(
1001
+ agent_id: str,
1002
+ task_id: str,
1003
+ payload: AgentScheduleRequest,
1004
+ ):
1005
+ existing = studio.get_agent_schedule(agent_id, task_id)
1006
+ await studio.validate_schedule_session(
1007
+ agent_id, payload.continuity, payload.session_id, existing.target.agent_version_ref
1008
+ )
1009
+ return studio.update_agent_schedule(
1010
+ agent_id,
1011
+ task_id,
1012
+ display_name=payload.display_name,
1013
+ prompt=payload.prompt,
1014
+ schedule=payload.schedule,
1015
+ enabled=payload.enabled,
1016
+ continuity=payload.continuity,
1017
+ session_id=payload.session_id,
1018
+ )
1019
+
1020
+ @app.delete("/api/v1/agents/{agent_id}/schedules/{task_id}", status_code=204)
1021
+ async def delete_agent_schedule(agent_id: str, task_id: str):
1022
+ studio.get_agent_schedule(agent_id, task_id)
1023
+ studio.scheduler.delete_task(task_id)
1024
+ return Response(status_code=204)
1025
+
1026
+ @app.post("/api/v1/agents/{agent_id}/schedules/{task_id}:run", status_code=202)
1027
+ async def run_agent_schedule_now(agent_id: str, task_id: str):
1028
+ return await studio.run_agent_schedule_now(agent_id, task_id)
1029
+
1030
+ @app.get("/api/v1/agents/{agent_id}/schedules/{task_id}/occurrences")
1031
+ async def list_agent_schedule_occurrences(
1032
+ agent_id: str,
1033
+ task_id: str,
1034
+ limit: int = Query(default=50, ge=1, le=200),
1035
+ ):
1036
+ studio.get_agent_schedule(agent_id, task_id)
1037
+ return {"items": studio.scheduler.list_occurrences(task_id, limit=limit)}
1038
+
507
1039
  @app.post("/api/v1/workspaces:open")
508
1040
  async def open_workspace(payload: WorkspaceOpenRequest):
509
1041
  # This endpoint only reconnects to the daemon's already-bound root. Do
@@ -580,57 +1112,118 @@ def create_studio_app(
580
1112
  "Codex Studio 只支持只读本地运行",
581
1113
  status_code=422,
582
1114
  )
583
-
584
- queue: asyncio.Queue = asyncio.Queue()
585
-
586
- def observe(event):
587
- queue.put_nowait(event)
588
-
589
- # The Operation owns the runtime task. The SSE response is only one
590
- # observer, so refreshing or switching chats cannot cancel the Run.
591
- operation = studio.submit_studio_run(
1115
+ return _stream_studio_run(
592
1116
  build_id,
593
- payload.input.content,
1117
+ user_input=payload.input.content,
594
1118
  session_id=payload.session_id,
595
1119
  model=payload.model,
596
1120
  sandbox=payload.sandbox,
597
1121
  idempotency_key=key,
598
- on_event=observe,
599
1122
  )
600
1123
 
601
- async def render():
602
- while True:
603
- try:
604
- event = await asyncio.wait_for(queue.get(), timeout=0.1)
605
- except TimeoutError:
606
- event = None
607
- if event is not None:
608
- data = json.dumps(
609
- event.data,
610
- ensure_ascii=False,
611
- separators=(",", ":"),
612
- )
613
- yield f"id: {event.id}\nevent: {event.type}\ndata: {data}\n\n"
614
- current = studio.operations.get(operation.id)
615
- if (
616
- current.status
617
- in {
618
- OperationStatus.SUCCEEDED,
619
- OperationStatus.FAILED,
620
- OperationStatus.CANCELLED,
621
- OperationStatus.INTERRUPTED,
622
- }
623
- and queue.empty()
624
- ):
625
- if current.status == OperationStatus.FAILED:
626
- data = json.dumps(current.error or {}, ensure_ascii=False)
627
- yield f"event: run.failed\ndata: {data}\n\n"
628
- break
1124
+ @app.get("/api/v1/builds/{build_id}/conversation-surface")
1125
+ async def get_conversation_surface(
1126
+ build_id: str,
1127
+ session_id: str = Query(alias="sessionId", min_length=1, max_length=256),
1128
+ ):
1129
+ return studio.conversation_surface(build_id, session_id=session_id)
629
1130
 
630
- return StreamingResponse(
631
- render(),
632
- media_type="text/event-stream",
633
- headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
1131
+ @app.get("/api/v1/agents/{agent_id}/conversation-surface")
1132
+ async def get_agent_conversation_surface(
1133
+ agent_id: str,
1134
+ session_id: str = Query(alias="sessionId", min_length=1, max_length=256),
1135
+ ):
1136
+ """Resolve the immutable Build and its composer contract atomically.
1137
+
1138
+ The browser selects an Agent, not a mutable Draft or a Build id. This
1139
+ route gives it the same current-Build decision used by chat and local
1140
+ Scheduler authoring, so controls cannot be rendered from a stale or
1141
+ unrelated Build.
1142
+ """
1143
+
1144
+ await runtime_model_catalog()
1145
+ build = await studio.ensure_current_build(agent_id)
1146
+ return {
1147
+ "buildId": build.id,
1148
+ "surface": studio.conversation_surface(
1149
+ build.id,
1150
+ session_id=session_id,
1151
+ ),
1152
+ }
1153
+
1154
+ @app.post("/api/v1/builds/{build_id}/conversation:stream")
1155
+ async def stream_conversation_turn(
1156
+ build_id: str,
1157
+ payload: ConversationTurnRequest,
1158
+ idempotency_key: str | None = Header(default=None, alias="Idempotency-Key"),
1159
+ ):
1160
+ key = _require_idempotency_key(idempotency_key)
1161
+ conversation_input = payload.input
1162
+ if conversation_input.idempotency_key != key:
1163
+ raise StudioError(
1164
+ "CONVERSATION_IDEMPOTENCY_MISMATCH",
1165
+ "ConversationInput 的幂等键必须与请求头一致",
1166
+ status_code=422,
1167
+ )
1168
+ surface = studio.conversation_surface(
1169
+ build_id,
1170
+ session_id=conversation_input.session_id,
1171
+ )
1172
+ try:
1173
+ validate_conversation_input(surface, conversation_input)
1174
+ except ValueError as exc:
1175
+ raise StudioError(
1176
+ "CONVERSATION_INPUT_UNSUPPORTED",
1177
+ "当前 Agent 不支持此会话输入",
1178
+ status_code=422,
1179
+ details={"reason": str(exc), "surfaceId": surface.surface_id},
1180
+ ) from exc
1181
+ text_parts = [
1182
+ part.text for part in conversation_input.parts if isinstance(part, ConversationTextPart)
1183
+ ]
1184
+ runtime_parts: list[dict[str, str]] = [
1185
+ {"type": "text", "text": value} for value in text_parts
1186
+ ]
1187
+ attachment_names: list[str] = []
1188
+ for part in conversation_input.parts:
1189
+ if not isinstance(part, ConversationAttachmentPart):
1190
+ continue
1191
+ stored = studio.conversation_attachments.resolve(part.attachment_ref)
1192
+ if part.media_type.lower() != stored.media_type.lower():
1193
+ raise StudioError(
1194
+ "CONVERSATION_ATTACHMENT_METADATA_MISMATCH",
1195
+ "会话附件类型与已上传内容不一致",
1196
+ status_code=422,
1197
+ details={"attachmentRef": part.attachment_ref},
1198
+ )
1199
+ encoded = base64.b64encode(stored.path.read_bytes()).decode("ascii")
1200
+ data_url = f"data:{stored.media_type};base64,{encoded}"
1201
+ attachment_names.append(part.name or stored.name)
1202
+ if stored.media_type.startswith("image/"):
1203
+ runtime_parts.append({"type": "image", "url": data_url})
1204
+ else:
1205
+ runtime_parts.append(
1206
+ {
1207
+ "type": "input_file",
1208
+ "filename": part.name or stored.name,
1209
+ "file_data": data_url,
1210
+ }
1211
+ )
1212
+ display_input = "\n".join(text_parts).strip()
1213
+ if not display_input:
1214
+ display_input = "请处理本轮附件:" + "、".join(attachment_names)
1215
+ return _stream_studio_run(
1216
+ build_id,
1217
+ user_input=display_input,
1218
+ session_id=conversation_input.session_id,
1219
+ model=conversation_input.model_ref,
1220
+ sandbox=payload.sandbox,
1221
+ reasoning_effort=conversation_input.reasoning,
1222
+ approval_mode=conversation_input.approval_mode,
1223
+ collaboration_mode=conversation_input.collaboration_mode,
1224
+ goal_objective=conversation_input.goal_objective,
1225
+ runtime_input=runtime_parts if attachment_names else None,
1226
+ idempotency_key=key,
634
1227
  )
635
1228
 
636
1229
  @app.post("/api/v1/agents", status_code=201)
@@ -644,6 +1237,15 @@ def create_studio_app(
644
1237
  runtime=payload.runtime,
645
1238
  )
646
1239
 
1240
+ @app.post("/api/v1/conversation-attachments", status_code=201)
1241
+ async def upload_conversation_attachment(file: UploadFile = File(...)):
1242
+ content = await file.read(studio.conversation_attachments.MAX_BYTES + 1)
1243
+ return studio.conversation_attachments.store(
1244
+ content,
1245
+ filename=file.filename or "attachment",
1246
+ media_type=file.content_type or "application/octet-stream",
1247
+ )
1248
+
647
1249
  @app.post("/api/v1/assets/agent-avatars", status_code=201)
648
1250
  async def upload_agent_avatar(request: Request):
649
1251
  declared_size = request.headers.get("Content-Length")
@@ -777,7 +1379,9 @@ def create_studio_app(
777
1379
 
778
1380
  @app.get("/api/v1/agents/{agent_id}/models")
779
1381
  async def get_agent_models(agent_id: str):
780
- return shared_web.list_models(shared_web.resolve_agent_id(agent_id))
1382
+ model_agent_id = shared_web.resolve_agent_id(agent_id)
1383
+ await runtime_model_catalog()
1384
+ return shared_web.list_models(model_agent_id)
781
1385
 
782
1386
  @app.put("/api/v1/agents/{agent_id}")
783
1387
  async def update_agent(
@@ -878,6 +1482,7 @@ def create_studio_app(
878
1482
  payload: BuildRequest,
879
1483
  idempotency_key: str | None = Header(default=None, alias="Idempotency-Key"),
880
1484
  ):
1485
+ await runtime_model_catalog()
881
1486
  return studio.submit_studio_build(
882
1487
  agent_id,
883
1488
  revision=payload.revision,
@@ -955,6 +1560,8 @@ def create_studio_app(
955
1560
  interaction_id,
956
1561
  name=payload.name,
957
1562
  data=payload.data,
1563
+ expected_revision=payload.expected_revision,
1564
+ idempotency_key=payload.idempotency_key,
958
1565
  )
959
1566
 
960
1567
  @app.get("/api/v1/runs/{run_id}/context")
@@ -1236,7 +1843,7 @@ def create_studio_app(
1236
1843
  async def list_deployments():
1237
1844
  """Read local deployment receipts without implicit cloud refreshes."""
1238
1845
 
1239
- return {"items": studio.cloud.list()}
1846
+ return {"items": studio.cloud.list(), "currentIdentity": studio.cloud.cached_identity()}
1240
1847
 
1241
1848
  @app.get("/api/v1/cloud-agents")
1242
1849
  async def list_account_cloud_agents(
@@ -1312,9 +1919,7 @@ def create_studio_app(
1312
1919
  ):
1313
1920
  """List Server-owned sessions for this local deployment receipt only."""
1314
1921
 
1315
- return await studio.cloud.list_cloud_chat_sessions(
1316
- deployment_id, page=page, size=size
1317
- )
1922
+ return await studio.cloud.list_cloud_chat_sessions(deployment_id, page=page, size=size)
1318
1923
 
1319
1924
  @app.get("/api/v1/deployments/{deployment_id}/cloud-chat/models")
1320
1925
  async def list_cloud_chat_models(deployment_id: str):
@@ -1331,9 +1936,7 @@ def create_studio_app(
1331
1936
 
1332
1937
  return await studio.cloud.create_cloud_chat_session(deployment_id)
1333
1938
 
1334
- @app.get(
1335
- "/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/messages"
1336
- )
1939
+ @app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/messages")
1337
1940
  async def list_cloud_chat_messages(
1338
1941
  deployment_id: str,
1339
1942
  session_id: str,
@@ -1347,25 +1950,23 @@ def create_studio_app(
1347
1950
  limit=limit,
1348
1951
  )
1349
1952
 
1350
- @app.get(
1351
- "/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events"
1352
- )
1953
+ @app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events")
1353
1954
  async def list_cloud_chat_events(
1354
1955
  deployment_id: str,
1355
1956
  session_id: str,
1356
1957
  after_seq_id: int | None = Query(default=None, alias="afterSeqId", ge=0),
1958
+ offset: int | None = Query(default=None, ge=0),
1357
1959
  limit: int = Query(default=200, ge=1, le=1000),
1358
1960
  ):
1359
1961
  return await studio.cloud.list_cloud_chat_events(
1360
1962
  deployment_id,
1361
1963
  session_id=session_id,
1362
1964
  after_seq_id=after_seq_id,
1965
+ offset=offset,
1363
1966
  limit=limit,
1364
1967
  )
1365
1968
 
1366
- @app.get(
1367
- "/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events/stream"
1368
- )
1969
+ @app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events/stream")
1369
1970
  async def stream_cloud_chat_events(
1370
1971
  request: Request,
1371
1972
  deployment_id: str,
@@ -1399,9 +2000,7 @@ def create_studio_app(
1399
2000
  if not isinstance(event, dict):
1400
2001
  continue
1401
2002
  event_payload = (
1402
- event.get("payload")
1403
- if isinstance(event.get("payload"), dict)
1404
- else event
2003
+ event.get("payload") if isinstance(event.get("payload"), dict) else event
1405
2004
  )
1406
2005
  seq = int(
1407
2006
  event_payload.get("seq")
@@ -1427,25 +2026,44 @@ def create_studio_app(
1427
2026
  if isinstance(event_payload.get("content"), dict)
1428
2027
  else {}
1429
2028
  )
1430
- status = str(
1431
- event_payload.get("status") or content.get("status") or ""
1432
- ).lower()
2029
+ status = str(event_payload.get("status") or content.get("status") or "").lower()
1433
2030
  event_is_terminal = event_type in {
1434
- "run.completed", "run.complete", "run.succeeded",
1435
- "run.failed", "run.cancelled", "run.expired", "run.error",
2031
+ "run.completed",
2032
+ "run.complete",
2033
+ "run.succeeded",
2034
+ "run.failed",
2035
+ "run.cancelled",
2036
+ "run.expired",
2037
+ "run.error",
1436
2038
  } or (
1437
2039
  event_type in {"run_status", "run.status"}
1438
- and status in {
1439
- "completed", "complete", "succeeded", "success",
1440
- "failed", "cancelled", "canceled", "expired", "error", "aborted",
2040
+ and status
2041
+ in {
2042
+ "completed",
2043
+ "complete",
2044
+ "succeeded",
2045
+ "success",
2046
+ "failed",
2047
+ "cancelled",
2048
+ "canceled",
2049
+ "expired",
2050
+ "error",
2051
+ "aborted",
1441
2052
  }
1442
2053
  )
1443
2054
  terminal = terminal or event_is_terminal
1444
2055
  emitted = True
2056
+ projected_event = dict(event)
2057
+ conversation_item = _cloud_event_conversation_item(
2058
+ event,
2059
+ session_id=session_id,
2060
+ )
2061
+ if conversation_item is not None:
2062
+ projected_event["conversationItem"] = conversation_item
1445
2063
  yield (
1446
2064
  (f"id: {seq}\n" if seq else "")
1447
2065
  + "event: session.event\n"
1448
- + f"data: {json.dumps(event, ensure_ascii=False)}\n\n"
2066
+ + f"data: {json.dumps(projected_event, ensure_ascii=False)}\n\n"
1449
2067
  )
1450
2068
  if terminal or payload.get("session_deleted"):
1451
2069
  break
@@ -1465,9 +2083,7 @@ def create_studio_app(
1465
2083
  status_code=204,
1466
2084
  )
1467
2085
  async def delete_cloud_chat_session(deployment_id: str, session_id: str):
1468
- await studio.cloud.delete_cloud_chat_session(
1469
- deployment_id, session_id=session_id
1470
- )
2086
+ await studio.cloud.delete_cloud_chat_session(deployment_id, session_id=session_id)
1471
2087
  return Response(status_code=204)
1472
2088
 
1473
2089
  @app.post(
@@ -1594,5 +2210,13 @@ def create_studio_app(
1594
2210
  runtime_model_catalog=runtime_model_catalog,
1595
2211
  )
1596
2212
  register_memory_routes(app, studio)
2213
+ register_resource_connection_routes(app, studio)
2214
+ register_plugin_routes(app, studio)
2215
+
2216
+ from ksadk.studio.dsh_application import register_dsh_application
2217
+
2218
+ register_dsh_application(
2219
+ app, studio, session_secret=session_secret, security_enabled=security_enabled
2220
+ )
1597
2221
 
1598
2222
  return app