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
@@ -9,8 +9,22 @@ from datetime import datetime, timezone
9
9
  from typing import Any
10
10
  from uuid import uuid4
11
11
 
12
- from ksadk.studio.contracts import BuildStatus, OperationStatus, RunRecord, RunStatus
12
+ from ksadk.conversations.contracts import (
13
+ APPROVAL_MODE_EXTENSION,
14
+ COLLABORATION_MODE_EXTENSION,
15
+ GOAL_OBJECTIVE_EXTENSION,
16
+ ConversationAttachmentPart,
17
+ ConversationInput,
18
+ ConversationTextPart,
19
+ validate_conversation_input,
20
+ )
21
+ from ksadk.conversations.message_projection import project_session_messages
22
+ from ksadk.events.canonical import parse_runtime_event
23
+ from ksadk.events.canonical_store import session_event_to_runtime_event
24
+ from ksadk.sessions.base import Session
25
+ from ksadk.studio.contracts import OperationStatus, RunRecord, RunStatus
13
26
  from ksadk.studio.errors import StudioError, not_found
27
+ from ksadk.studio.run_service import project_runtime_event
14
28
  from ksadk.studio.service import StudioService
15
29
  from ksadk.tools.gateway import tool_approval_capability
16
30
 
@@ -80,10 +94,12 @@ class StudioSharedWebBridge:
80
94
  "CheckpointResumePreview": False,
81
95
  },
82
96
  "ApprovalPolicy": tool_approval_capability(),
97
+ "InteractionV1": True,
83
98
  "WorkspaceFiles": {"Enabled": False},
84
99
  "NativeDashboard": {"Enabled": False},
85
100
  "NativeTerminal": {"Enabled": False},
86
101
  "Thinking": False,
102
+ "ContextCompaction": self.studio.is_codex_agent(agent_id),
87
103
  },
88
104
  }
89
105
 
@@ -101,14 +117,14 @@ class StudioSharedWebBridge:
101
117
 
102
118
  return self._select_model(agent_id, str(requested or ""))
103
119
 
104
- def list_sessions(
120
+ async def list_sessions(
105
121
  self,
106
122
  agent_id: str,
107
123
  *,
108
124
  page: int = 1,
109
125
  page_size: int = 30,
110
126
  ) -> dict[str, Any]:
111
- sessions = self._sessions(agent_id)
127
+ sessions = await self._sessions(agent_id)
112
128
  safe_page = max(1, page)
113
129
  safe_size = min(100, max(1, page_size))
114
130
  start = (safe_page - 1) * safe_size
@@ -119,29 +135,79 @@ class StudioSharedWebBridge:
119
135
  "PageSize": safe_size,
120
136
  }
121
137
 
122
- def create_session(self, agent_id: str) -> dict[str, Any]:
138
+ async def create_session(self, agent_id: str) -> dict[str, Any]:
123
139
  self._draft(agent_id)
124
140
  session_id = f"ses_{uuid4().hex}"
125
- now = datetime.now(timezone.utc).isoformat()
126
- return {
127
- "Session": {
128
- "SessionId": session_id,
129
- "AgentId": agent_id,
130
- "UserId": "local-user",
131
- "Title": "新会话",
132
- "CreatedAt": now,
133
- "UpdatedAt": now,
134
- }
135
- }
141
+ session = await self.studio.session_service.create_session(
142
+ agent_id,
143
+ "local-user",
144
+ session_id,
145
+ )
146
+ return {"Session": self._session_metadata_record(session)}
136
147
 
137
- def get_session(self, session_id: str) -> dict[str, Any]:
148
+ async def get_session(self, session_id: str) -> dict[str, Any]:
138
149
  runs = self.studio.event_store.list_runs(session_id=session_id)
150
+ if runs:
151
+ return {"Session": self._session_record(runs)}
152
+ session = await self.studio.session_service.get_session_metadata(session_id)
153
+ if session is None:
154
+ raise not_found("session", session_id)
155
+ return {"Session": self._session_metadata_record(session)}
156
+
157
+ async def compact_session(self, agent_id: str, session_id: str) -> dict[str, Any]:
158
+ from ksadk.codex.runtime import CodexRuntimeAdapter
159
+
160
+ runs = self.studio.event_store.list_runs(session_id=session_id, agent_id=agent_id)
139
161
  if not runs:
140
162
  raise not_found("session", session_id)
141
- return {"Session": self._session_record(runs)}
163
+ latest = runs[-1]
164
+ if latest.runtime_type != "codex":
165
+ raise StudioError("COMPACTION_UNSUPPORTED", "此运行时尚未提供手动压缩", status_code=409)
166
+ key = (agent_id, session_id)
167
+ service = self.studio.run_service
168
+ if key in service._active_sessions or any(self._active_status(run.status) for run in runs):
169
+ raise StudioError(
170
+ "SESSION_RUN_ACTIVE", "请等待当前运行完成后压缩上下文", status_code=409
171
+ )
172
+ thread_id = str((latest.runtime_handle.get("native_ref") or {}).get("thread_id") or "")
173
+ if not thread_id:
174
+ raise StudioError(
175
+ "CONTEXT_UNAVAILABLE", "此会话尚无可压缩的原生上下文", status_code=409
176
+ )
177
+ service._active_sessions.add(key)
178
+ adapter = None
179
+ try:
180
+ spec = self.studio.resolve_run_spec(latest.build_id, model=latest.model or None)
181
+ adapter = self.studio.runtime_executor.create_adapter(spec.launch_context)
182
+ if not isinstance(adapter, CodexRuntimeAdapter):
183
+ raise StudioError(
184
+ "COMPACTION_UNSUPPORTED", "此运行时尚未提供手动压缩", status_code=409
185
+ )
186
+ usage = await adapter.compact_session(thread_id, dict(spec.request_config))
187
+ last = usage.get("last") or {}
188
+ context_usage = {
189
+ "used_tokens": last.get("totalTokens"),
190
+ "source": "runtime",
191
+ "model": latest.model,
192
+ }
193
+ self.studio.event_store.append(
194
+ latest.id,
195
+ "context.compaction.completed",
196
+ {
197
+ "trigger": "manual",
198
+ "contextUsage": context_usage,
199
+ },
200
+ )
201
+ return {"Status": "completed", "ContextUsage": context_usage}
202
+ finally:
203
+ try:
204
+ if adapter is not None:
205
+ await adapter.close_all()
206
+ finally:
207
+ service._active_sessions.discard(key)
142
208
 
143
- def delete_session(self, session_id: str) -> dict[str, Any]:
144
- self.studio.event_store.delete_session(session_id)
209
+ async def delete_session(self, session_id: str) -> dict[str, Any]:
210
+ await self.studio.delete_session(session_id)
145
211
  return {}
146
212
 
147
213
  async def list_messages(
@@ -172,7 +238,14 @@ class StudioSharedWebBridge:
172
238
  {
173
239
  "MessageId": f"{run.id}:assistant",
174
240
  "Role": "assistant",
175
- "Content": {"text": self._run_output(run)},
241
+ "Content": {
242
+ # Run status is metadata, not an assistant reply. An
243
+ # empty pending reply lets canonical reasoning/tools
244
+ # restore without a synthetic status text shadowing them.
245
+ "text": (
246
+ run.output if self._active_status(run.status) else self._run_output(run)
247
+ )
248
+ },
176
249
  "Timestamp": self._timestamp(run.completed_at or run.started_at),
177
250
  "SeqId": sequence,
178
251
  "InvocationId": run.id,
@@ -180,6 +253,16 @@ class StudioSharedWebBridge:
180
253
  }
181
254
  )
182
255
 
256
+ extra_events = await self._untracked_runtime_events(session_id, runs)
257
+ if extra_events:
258
+ messages.extend(project_session_messages(extra_events))
259
+ messages.sort(key=lambda item: self._timestamp_value(item["Timestamp"]))
260
+ for sequence, message in enumerate(messages, 1):
261
+ message["SeqId"] = sequence
262
+ if isinstance(message["Timestamp"], (int, float)):
263
+ message["Timestamp"] = self._timestamp(message["Timestamp"])
264
+ message.pop("StartSeqId", None)
265
+
183
266
  latest_seq_id = sequence
184
267
  if after_seq_id is not None:
185
268
  messages = [item for item in messages if item["SeqId"] > after_seq_id]
@@ -205,12 +288,31 @@ class StudioSharedWebBridge:
205
288
  events.append(
206
289
  {
207
290
  "SeqId": sequence,
208
- "EventType": event.type,
291
+ "EventType": self._shared_event_type(event.type, event.data),
209
292
  "InvocationId": run.id,
210
- "Content": event.data,
293
+ "Content": self._shared_event_content(event.data, run.id),
211
294
  "Timestamp": self._timestamp(event.created_at),
212
295
  }
213
296
  )
297
+ extra_events = await self._untracked_runtime_events(session_id, runs)
298
+ for event in extra_events:
299
+ native = event["Content"]["runtime_event"]
300
+ event_type, content = project_runtime_event(
301
+ parse_runtime_event(native), session_id=session_id
302
+ )
303
+ events.append(
304
+ {
305
+ "SeqId": 0,
306
+ "EventType": self._shared_event_type(event_type, content),
307
+ "InvocationId": event["InvocationId"],
308
+ "Content": content,
309
+ "Timestamp": self._timestamp(event["Timestamp"]),
310
+ }
311
+ )
312
+ if extra_events:
313
+ events.sort(key=lambda item: self._timestamp_value(item["Timestamp"]))
314
+ for sequence, event in enumerate(events, 1):
315
+ event["SeqId"] = sequence
214
316
  return {
215
317
  "Events": events,
216
318
  "Total": len(events),
@@ -218,6 +320,147 @@ class StudioSharedWebBridge:
218
320
  "Limit": len(events),
219
321
  }
220
322
 
323
+ async def _untracked_runtime_events(
324
+ self, session_id: str, runs: list[RunRecord]
325
+ ) -> list[dict[str, Any]]:
326
+ """Read Kernel-owned runs absent from Studio's foreground run index.
327
+
328
+ Scheduled runs already have a durable canonical transcript. Project
329
+ that log through the shared message contract, including in sessions
330
+ that also contain foreground turns, without manufacturing RunRecords.
331
+ """
332
+ tracked = {run.id for run in runs}
333
+ for run in runs:
334
+ tracked.add(str(run.runtime_handle.get("run_id") or ""))
335
+ for event in await self.studio.run_service.events(run.id):
336
+ native = event.data.get("runtimeEvent")
337
+ if isinstance(native, dict):
338
+ tracked.add(str(native.get("run_id") or ""))
339
+ result = []
340
+ for row in await self.studio.session_service.get_events(session_id):
341
+ native = session_event_to_runtime_event(row)
342
+ if native is None or native.run_id in tracked:
343
+ continue
344
+ result.append(
345
+ {
346
+ "EventId": native.event_id,
347
+ "SessionId": session_id,
348
+ "SeqId": row.seq_id,
349
+ "EventType": native.event_type,
350
+ "InvocationId": native.run_id,
351
+ "Timestamp": row.timestamp,
352
+ "Content": {"runtime_event": native.model_dump(mode="json")},
353
+ "Metadata": {"ksadk_canonical_runtime_event": True},
354
+ }
355
+ )
356
+ return result
357
+
358
+ @staticmethod
359
+ def _timestamp_value(value: str | float) -> float:
360
+ if isinstance(value, (float, int)):
361
+ return value
362
+ return datetime.fromisoformat(value.replace("Z", "+00:00")).timestamp() if value else 0
363
+
364
+ @staticmethod
365
+ def _shared_event_type(event_type: str, data: dict[str, Any]) -> str:
366
+ native = data.get("runtimeEvent")
367
+ if (
368
+ event_type == "run.interrupted"
369
+ and isinstance(native, dict)
370
+ and native.get("interaction_id")
371
+ ):
372
+ # A resumable interaction is waiting, not a terminal interruption.
373
+ return "run.waiting"
374
+ return event_type
375
+
376
+ @staticmethod
377
+ def _shared_event_content(data: dict[str, Any], run_id: str) -> dict[str, Any]:
378
+ """Use the public Studio run identity in shared-Web history projections.
379
+
380
+ The persisted canonical event retains the adapter's native run ID.
381
+ ListSessionMessages uses the Studio ID, so its event projection must
382
+ use the same ID or hydration retains both copies of the answer.
383
+ """
384
+ native = data.get("runtimeEvent")
385
+ if not isinstance(native, dict):
386
+ return data
387
+ return {**data, "runtimeEvent": {**native, "run_id": run_id}}
388
+
389
+ async def subscription_run_id(self, session_id: str, invocation_id: str) -> str:
390
+ run_id = self._run_ids_by_invocation.get(invocation_id, invocation_id)
391
+ try:
392
+ run = self.studio.event_store.get(run_id)
393
+ except StudioError as error:
394
+ if error.code != "RUN_NOT_FOUND":
395
+ raise
396
+ else:
397
+ if run.session_id != session_id:
398
+ raise not_found("run", invocation_id)
399
+ return run_id
400
+ for row in await self.studio.session_service.get_events(session_id):
401
+ native = session_event_to_runtime_event(row)
402
+ if native is not None and native.run_id == run_id:
403
+ return run_id
404
+ raise not_found("run", invocation_id)
405
+
406
+ async def subscribe_run_events(
407
+ self,
408
+ session_id: str,
409
+ invocation_id: str,
410
+ *,
411
+ after_seq_id: int = 0,
412
+ ) -> AsyncIterator[str]:
413
+ run_id = await self.subscription_run_id(session_id, invocation_id)
414
+ runs = self.studio.event_store.list_runs(session_id=session_id)
415
+ if await self._untracked_runtime_events(session_id, runs):
416
+ cursor = after_seq_id
417
+ while True:
418
+ history = await self.list_session_events(session_id)
419
+ run_events = [
420
+ event for event in history["Events"] if event["InvocationId"] == run_id
421
+ ]
422
+ for event in run_events:
423
+ if event["SeqId"] > cursor:
424
+ yield self._sse("message", {**event, "SessionId": session_id})
425
+ cursor = event["SeqId"]
426
+ if any(
427
+ event["EventType"]
428
+ in {"run.completed", "run.failed", "run.cancelled", "run.interrupted"}
429
+ for event in run_events
430
+ ):
431
+ yield "event: done\ndata: [DONE]\n\n"
432
+ return
433
+ yield ": ping\n\n"
434
+ await asyncio.sleep(0.25)
435
+ # Match ListSessionEvents' session cursor without rereading every old
436
+ # run on every live poll. Only the subscribed run can still grow.
437
+ offset = 0
438
+ for record in self.studio.event_store.list_runs(session_id=session_id):
439
+ if record.id == run_id:
440
+ break
441
+ offset += len(self.studio.event_store.events(record.id))
442
+ cursor = max(0, after_seq_id - offset)
443
+ while True:
444
+ for event in await self.studio.run_service.events(run_id, after=cursor):
445
+ cursor = max(cursor, event.id)
446
+ yield self._sse(
447
+ "message",
448
+ {
449
+ "SeqId": offset + event.id,
450
+ "SessionId": session_id,
451
+ "InvocationId": invocation_id,
452
+ "EventType": self._shared_event_type(event.type, event.data),
453
+ "Content": self._shared_event_content(event.data, run_id),
454
+ "Timestamp": self._timestamp(event.created_at),
455
+ },
456
+ )
457
+ record = self.studio.event_store.get(run_id)
458
+ if not self._active_status(record.status):
459
+ yield "event: done\ndata: [DONE]\n\n"
460
+ return
461
+ yield ": ping\n\n"
462
+ await asyncio.sleep(0.25)
463
+
221
464
  def cancel_run(self, invocation_id: str) -> dict[str, Any]:
222
465
  operation_id = self._operations_by_invocation.get(invocation_id)
223
466
  if operation_id:
@@ -240,19 +483,46 @@ class StudioSharedWebBridge:
240
483
  run_id = self._response_runs.get(response_id, response_id)
241
484
  return self.studio.event_store.get(run_id).session_id
242
485
 
243
- async def stream_run(self, payload: dict[str, Any]) -> AsyncIterator[str]:
486
+ async def stream_run(
487
+ self, payload: dict[str, Any], *, shared_ui: bool = False
488
+ ) -> AsyncIterator[str]:
244
489
  agent_id = self.resolve_agent_id(str(payload.get("AgentId") or "") or None)
245
490
  session_id = str(payload.get("SessionId") or f"ses_{uuid4().hex}")
246
491
  invocation_id = str(payload.get("InvocationId") or f"resp_{uuid4().hex}")
247
492
  prompt = self._input_text(payload)
248
493
  runtime_input = self._runtime_input(payload)
249
494
  model = self._select_model(agent_id, str(payload.get("Model") or ""))
250
- approval_mode = str(payload.get("ApprovalMode") or "")
251
- collaboration_mode = str(payload.get("CollaborationMode") or "")
252
- goal_objective = str(payload.get("GoalObjective") or "")
253
- reasoning_effort = str(payload.get("ReasoningEffort") or "")
495
+ model_explicit = bool(payload.get("ModelExplicit", str(payload.get("Model") or "")))
496
+ approval_mode, collaboration_mode, goal_objective, reasoning_effort = (
497
+ self._request_controls(payload)
498
+ )
499
+ try:
500
+ build = await self._ensure_build(agent_id)
501
+ self._validate_conversation_turn(
502
+ build_id=build.id,
503
+ session_id=session_id,
504
+ invocation_id=invocation_id,
505
+ prompt=prompt,
506
+ runtime_input=runtime_input,
507
+ model=model if model_explicit else "",
508
+ approval_mode=approval_mode,
509
+ collaboration_mode=collaboration_mode,
510
+ goal_objective=goal_objective,
511
+ reasoning_effort=reasoning_effort,
512
+ )
513
+ except StudioError as exc:
514
+ # StreamingResponse starts the HTTP response before advancing this
515
+ # generator. Preflight failures therefore belong in the stream;
516
+ # raising here would turn an actionable Studio error into Starlette's
517
+ # "response already started" RuntimeError.
518
+ yield self._failed_sse(invocation_id, exc.message)
519
+ return
520
+ except Exception:
521
+ yield self._failed_sse(invocation_id, "本地 Agent 运行失败")
522
+ return
254
523
  execution = asyncio.create_task(
255
524
  self._execute_run(
525
+ build=build,
256
526
  agent_id=agent_id,
257
527
  session_id=session_id,
258
528
  invocation_id=invocation_id,
@@ -304,6 +574,15 @@ class StudioSharedWebBridge:
304
574
  if event_name == "response.output_text.delta":
305
575
  emitted_text += str(event_payload.get("delta") or "")
306
576
  yield self._sse(event_name, event_payload)
577
+ if (
578
+ shared_ui
579
+ and event_name == "a2ui.interaction"
580
+ and event_payload.get("kind") in {"form", "structured_input"}
581
+ ):
582
+ # The shared UI restores the durable Interaction/v1
583
+ # request, then subscribes to this same live run.
584
+ # Leave the execution attached while input is pending.
585
+ return
307
586
  else:
308
587
  idle_polls += 1
309
588
  if idle_polls >= 20:
@@ -355,17 +634,33 @@ class StudioSharedWebBridge:
355
634
  session_id = str(payload.get("SessionId") or f"ses_{uuid4().hex}")
356
635
  invocation_id = str(payload.get("InvocationId") or f"resp_{uuid4().hex}")
357
636
  model = self._select_model(agent_id, str(payload.get("Model") or ""))
358
- approval_mode = str(payload.get("ApprovalMode") or "")
359
- collaboration_mode = str(payload.get("CollaborationMode") or "")
360
- goal_objective = str(payload.get("GoalObjective") or "")
361
- reasoning_effort = str(payload.get("ReasoningEffort") or "")
637
+ model_explicit = bool(payload.get("ModelExplicit", str(payload.get("Model") or "")))
638
+ approval_mode, collaboration_mode, goal_objective, reasoning_effort = (
639
+ self._request_controls(payload)
640
+ )
641
+ build = await self._ensure_build(agent_id)
642
+ prompt = self._input_text(payload)
643
+ runtime_input = self._runtime_input(payload)
644
+ self._validate_conversation_turn(
645
+ build_id=build.id,
646
+ session_id=session_id,
647
+ invocation_id=invocation_id,
648
+ prompt=prompt,
649
+ runtime_input=runtime_input,
650
+ model=model if model_explicit else "",
651
+ approval_mode=approval_mode,
652
+ collaboration_mode=collaboration_mode,
653
+ goal_objective=goal_objective,
654
+ reasoning_effort=reasoning_effort,
655
+ )
362
656
  try:
363
657
  run = await self._execute_run(
658
+ build=build,
364
659
  agent_id=agent_id,
365
660
  session_id=session_id,
366
661
  invocation_id=invocation_id,
367
- prompt=self._input_text(payload),
368
- runtime_input=self._runtime_input(payload),
662
+ prompt=prompt,
663
+ runtime_input=runtime_input,
369
664
  model=model,
370
665
  approval_mode=approval_mode,
371
666
  collaboration_mode=collaboration_mode,
@@ -383,6 +678,7 @@ class StudioSharedWebBridge:
383
678
  async def _execute_run(
384
679
  self,
385
680
  *,
681
+ build: Any = None,
386
682
  agent_id: str,
387
683
  session_id: str,
388
684
  invocation_id: str,
@@ -394,7 +690,15 @@ class StudioSharedWebBridge:
394
690
  goal_objective: str = "",
395
691
  reasoning_effort: str = "",
396
692
  ) -> RunRecord:
397
- build = await self._ensure_build(agent_id)
693
+ if build is None:
694
+ build = await self._ensure_build(agent_id)
695
+ bound_agent = str(getattr(build, "agent_name", None) or getattr(build, "agent_id", ""))
696
+ if bound_agent != agent_id:
697
+ raise StudioError(
698
+ "CONVERSATION_BUILD_MISMATCH",
699
+ "会话 Build 不属于当前 Agent",
700
+ status_code=409,
701
+ )
398
702
 
399
703
  def observe(event: Any) -> None:
400
704
  if event.type == "run.created":
@@ -522,6 +826,23 @@ class StudioSharedWebBridge:
522
826
  )
523
827
  )
524
828
  continue
829
+ if event.type == "approval.resolved":
830
+ projected.append(
831
+ (
832
+ "response.ksadk.approval_resolved",
833
+ {
834
+ "type": "response.ksadk.approval_resolved",
835
+ "approvalRequestId": event.data.get("approvalId")
836
+ or event.data.get("interactionId"),
837
+ "decision": event.data.get("decision")
838
+ or event.data.get("name")
839
+ or "approved",
840
+ "revision": event.data.get("revision") or 2,
841
+ "runId": run.id,
842
+ },
843
+ )
844
+ )
845
+ continue
525
846
  item_event = self._response_item_event(event.type, event.data, starts)
526
847
  if item_event is not None:
527
848
  projected.append(item_event)
@@ -550,7 +871,9 @@ class StudioSharedWebBridge:
550
871
  "status": (
551
872
  "failed"
552
873
  if event_type.endswith("failed") or data.get("exitCode") not in {None, 0}
553
- else "completed" if done else "in_progress"
874
+ else "completed"
875
+ if done
876
+ else "in_progress"
554
877
  ),
555
878
  "action": {
556
879
  "commands": [command],
@@ -571,17 +894,24 @@ class StudioSharedWebBridge:
571
894
  "status": (
572
895
  "failed"
573
896
  if event_type.endswith("failed")
574
- else "completed" if done else "in_progress"
897
+ else "completed"
898
+ if done
899
+ else "in_progress"
575
900
  ),
576
901
  "output": data.get("output") or data.get("result") or "",
577
902
  }
578
903
  elif event_type == "approval.requested":
904
+ approval_id = str(data.get("approvalId") or data.get("interactionId") or call_id or "")
905
+ detail = data.get("detail")
906
+ arguments = detail if isinstance(detail, dict) else {"detail": detail}
579
907
  item = {
580
- "id": call_id or f"approval_{uuid4().hex}",
908
+ "id": approval_id or f"approval_{uuid4().hex}",
581
909
  "call_id": call_id,
582
- "type": "approval_request",
910
+ "type": "mcp_approval_request",
911
+ "name": str(data.get("kind") or started.get("tool") or "人工确认"),
912
+ "arguments": json.dumps(arguments, ensure_ascii=False),
913
+ "run_id": str(data.get("runId") or ""),
583
914
  "status": "in_progress",
584
- "action": data,
585
915
  }
586
916
  else:
587
917
  return None
@@ -659,39 +989,138 @@ class StudioSharedWebBridge:
659
989
  }
660
990
 
661
991
  async def _ensure_build(self, agent_id: str):
662
- if self.studio.is_codex_agent(agent_id):
663
- self.studio.codex_agent_detail(agent_id)
664
- builds = [
665
- record
666
- for record in self.studio.codex_builds.list()
667
- if record.agent_name == agent_id and self.studio.codex_builder.is_current(record)
668
- ]
669
- if builds:
670
- return builds[0]
671
- return await asyncio.to_thread(self.studio.codex_builder.build, agent_id)
672
- for record in self.studio.builds.list_for_agent(agent_id):
673
- if record.status == BuildStatus.SUCCEEDED:
674
- return record
675
- draft = self.studio.drafts.get(agent_id)
676
- if draft.spec.model is None and not draft.spec.bindings.model_profile_id:
992
+ return await self.studio.ensure_current_build(agent_id)
993
+
994
+ def _validate_conversation_turn(
995
+ self,
996
+ *,
997
+ build_id: str,
998
+ session_id: str,
999
+ invocation_id: str,
1000
+ prompt: str,
1001
+ runtime_input: Any,
1002
+ model: str,
1003
+ approval_mode: str,
1004
+ collaboration_mode: str,
1005
+ goal_objective: str,
1006
+ reasoning_effort: str,
1007
+ ) -> None:
1008
+ """Revalidate compatibility requests against the active Surface.
1009
+
1010
+ `/v1/responses` and the legacy RunAgent action remain supported wire
1011
+ shapes, but neither may smuggle provider-only input past the shared
1012
+ ConversationInput contract.
1013
+ """
1014
+
1015
+ surface = self.studio.conversation_surface(build_id, session_id=session_id)
1016
+ parts: list[ConversationTextPart | ConversationAttachmentPart] = [
1017
+ ConversationTextPart(text=prompt)
1018
+ ]
1019
+ for index, item in enumerate(runtime_input if isinstance(runtime_input, list) else []):
1020
+ if not isinstance(item, dict):
1021
+ continue
1022
+ kind = str(item.get("type") or "")
1023
+ if kind in {"image", "input_image"}:
1024
+ media_type = self._data_url_media_type(
1025
+ str(item.get("url") or item.get("image_url") or ""),
1026
+ fallback="image/*",
1027
+ )
1028
+ parts.append(
1029
+ ConversationAttachmentPart(
1030
+ attachment_ref=f"attachment://inline/{invocation_id}/{index}",
1031
+ media_type=media_type,
1032
+ name=str(item.get("filename") or "image"),
1033
+ )
1034
+ )
1035
+ elif kind == "input_file":
1036
+ parts.append(
1037
+ ConversationAttachmentPart(
1038
+ attachment_ref=f"attachment://inline/{invocation_id}/{index}",
1039
+ media_type=self._data_url_media_type(
1040
+ str(item.get("file_data") or item.get("file_url") or ""),
1041
+ fallback="application/octet-stream",
1042
+ ),
1043
+ name=str(item.get("filename") or "attachment"),
1044
+ )
1045
+ )
1046
+ conversation_input = ConversationInput(
1047
+ input_id=invocation_id,
1048
+ session_id=session_id,
1049
+ idempotency_key=f"responses:{invocation_id}",
1050
+ parts=tuple(parts),
1051
+ model_ref=model or None,
1052
+ reasoning=reasoning_effort or None,
1053
+ extensions={
1054
+ key: value
1055
+ for key, value in (
1056
+ (APPROVAL_MODE_EXTENSION, approval_mode or None),
1057
+ (COLLABORATION_MODE_EXTENSION, collaboration_mode or None),
1058
+ (GOAL_OBJECTIVE_EXTENSION, goal_objective or None),
1059
+ )
1060
+ if value is not None
1061
+ },
1062
+ )
1063
+ try:
1064
+ validate_conversation_input(surface, conversation_input)
1065
+ except ValueError as exc:
677
1066
  raise StudioError(
678
- "AGENT_MODEL_REQUIRED",
679
- "当前 Agent 未绑定 Model Profile,请先在 Agent 配置中选择模型;"
680
- "API Key 只提供访问凭证,不会自动绑定模型。",
1067
+ "CONVERSATION_INPUT_UNSUPPORTED",
1068
+ "当前 Agent 不支持此会话输入",
681
1069
  status_code=422,
682
- field="spec.bindings.modelProfileId",
683
- )
684
- return await asyncio.to_thread(self.studio.builder.build, draft)
1070
+ details={"reason": str(exc), "surfaceId": surface.surface_id},
1071
+ ) from exc
1072
+
1073
+ @staticmethod
1074
+ def _data_url_media_type(value: str, *, fallback: str) -> str:
1075
+ if value.startswith("data:"):
1076
+ media_type = value[5:].split(";", 1)[0].strip().lower()
1077
+ if media_type:
1078
+ return media_type
1079
+ return fallback
685
1080
 
686
- def _sessions(self, agent_id: str) -> list[dict[str, Any]]:
1081
+ async def _sessions(self, agent_id: str) -> list[dict[str, Any]]:
1082
+ persisted = await self.studio.session_service.list_session_metadata(
1083
+ agent_id=agent_id,
1084
+ )
1085
+ records = {
1086
+ session.id: self._session_metadata_record(session)
1087
+ for session in persisted
1088
+ if session.user_id in {"local-user", "local-studio"}
1089
+ }
687
1090
  grouped: dict[str, list[RunRecord]] = {}
688
1091
  for run in self.studio.event_store.list_runs():
689
1092
  if run.agent_id != agent_id:
690
1093
  continue
691
1094
  grouped.setdefault(run.session_id, []).append(run)
692
- records = [self._session_record(runs) for runs in grouped.values()]
693
- records.sort(key=lambda item: item["UpdatedAt"], reverse=True)
694
- return records
1095
+ for session_id, runs in grouped.items():
1096
+ records[session_id] = self._session_record(runs)
1097
+ ordered = list(records.values())
1098
+ ordered.sort(key=lambda item: item["UpdatedAt"], reverse=True)
1099
+ return ordered
1100
+
1101
+ def _session_metadata_record(self, session: Session) -> dict[str, Any]:
1102
+ title = session.title
1103
+ if not title and session.first_prompt:
1104
+ title = self._short_title(session.first_prompt)
1105
+ return {
1106
+ "SessionId": session.id,
1107
+ "AgentId": session.agent_id,
1108
+ "UserId": session.user_id or "local-user",
1109
+ "Title": title or "新会话",
1110
+ "FirstPrompt": session.first_prompt,
1111
+ "LastPrompt": session.last_prompt,
1112
+ "CreatedAt": self._timestamp(session.created_at),
1113
+ "UpdatedAt": self._timestamp(session.updated_at),
1114
+ "ActiveRunStatus": "",
1115
+ "ActiveInvocationId": "",
1116
+ "TokenUsage": {
1117
+ "input_tokens": 0,
1118
+ "output_tokens": 0,
1119
+ "total_tokens": 0,
1120
+ "turns": 0,
1121
+ "last_response_id": "",
1122
+ },
1123
+ }
695
1124
 
696
1125
  def _session_record(self, runs: list[RunRecord]) -> dict[str, Any]:
697
1126
  ordered = sorted(
@@ -702,6 +1131,7 @@ class StudioSharedWebBridge:
702
1131
  )
703
1132
  first = ordered[0]
704
1133
  latest = ordered[-1]
1134
+ active = next((run for run in reversed(ordered) if self._active_status(run.status)), None)
705
1135
  usage = {
706
1136
  "input_tokens": sum(run.usage.input_tokens for run in ordered),
707
1137
  "output_tokens": sum(run.usage.output_tokens for run in ordered),
@@ -718,11 +1148,26 @@ class StudioSharedWebBridge:
718
1148
  "LastPrompt": latest.input,
719
1149
  "CreatedAt": self._timestamp(first.started_at),
720
1150
  "UpdatedAt": self._timestamp(latest.completed_at or latest.started_at),
721
- "ActiveRunStatus": self._active_status(latest.status),
722
- "ActiveInvocationId": latest.id if latest.status == RunStatus.RUNNING else "",
1151
+ "ActiveRunStatus": self._active_status(active.status) if active else "",
1152
+ "ActiveInvocationId": active.id if active else "",
723
1153
  "TokenUsage": usage,
1154
+ "ContextUsage": self._context_usage(latest),
724
1155
  }
725
1156
 
1157
+ def _context_usage(self, latest: RunRecord) -> dict[str, Any] | None:
1158
+ if latest.runtime_type != "codex":
1159
+ return None
1160
+ for event in reversed(self.studio.event_store.events(latest.id)):
1161
+ if event.type == "context.compaction.completed":
1162
+ return event.data.get("contextUsage")
1163
+ if latest.runtime_type == "codex" and latest.usage.input_tokens > 0:
1164
+ return {
1165
+ "used_tokens": latest.usage.input_tokens,
1166
+ "source": "last_request",
1167
+ "model": latest.model,
1168
+ }
1169
+ return None
1170
+
726
1171
  def _model_descriptor(
727
1172
  self, agent_id: str, models: list[dict[str, Any]] | None = None
728
1173
  ) -> dict[str, Any]:
@@ -799,7 +1244,7 @@ class StudioSharedWebBridge:
799
1244
  "id": model_name,
800
1245
  "display_name": model_name,
801
1246
  "source": "agentkit-studio",
802
- "context_window_tokens": draft.spec.context.max_input_tokens,
1247
+ "input_budget_tokens": draft.spec.context.max_input_tokens,
803
1248
  "max_output_tokens": 2048,
804
1249
  "capabilities": {
805
1250
  "function_calling": True,
@@ -824,8 +1269,8 @@ class StudioSharedWebBridge:
824
1269
  "id": model_id,
825
1270
  "display_name": resolved_display_name,
826
1271
  "source": "agentkit-studio",
827
- "context_window_tokens": metadata.get("context_window_tokens")
828
- or draft.spec.context.max_input_tokens,
1272
+ "context_window_tokens": metadata.get("context_window_tokens"),
1273
+ "input_budget_tokens": draft.spec.context.max_input_tokens,
829
1274
  "max_output_tokens": max_output_tokens,
830
1275
  "capabilities": {
831
1276
  **dict(metadata.get("capabilities") or {}),
@@ -843,7 +1288,7 @@ class StudioSharedWebBridge:
843
1288
  "id": model_id,
844
1289
  "display_name": model_id if model_id != "unconfigured-model" else "未配置模型",
845
1290
  "source": "agentkit-studio",
846
- "context_window_tokens": draft.spec.context.max_input_tokens,
1291
+ "input_budget_tokens": draft.spec.context.max_input_tokens,
847
1292
  "max_output_tokens": 2048,
848
1293
  "capabilities": {
849
1294
  "function_calling": True,
@@ -869,7 +1314,7 @@ class StudioSharedWebBridge:
869
1314
  return self.studio.agent_detail(agent_id)["draft"]
870
1315
 
871
1316
  async def _run_activities(self, run: RunRecord) -> list[dict[str, Any]]:
872
- activities: list[dict[str, Any]] = []
1317
+ activities: dict[str, dict[str, Any]] = {}
873
1318
  for event in await self.studio.run_service.events(run.id):
874
1319
  operations = (
875
1320
  event.data.get("a2uiOperations")
@@ -881,16 +1326,78 @@ class StudioSharedWebBridge:
881
1326
  surface_id = str(
882
1327
  event.data.get("surfaceId") or event.data.get("surface_id") or f"{run.id}-surface"
883
1328
  )
884
- activities.append(
885
- {
886
- "SeqId": event.id,
887
- "Type": event.type,
888
- "MessageId": f"{run.id}:assistant",
889
- "SurfaceId": surface_id,
890
- "Content": {"a2ui_operations": operations},
891
- }
1329
+ previous = activities.get(surface_id)
1330
+ # Snapshot updates may repeat createSurface; only the latest full
1331
+ # snapshot should become a history row. Delta-only batches append.
1332
+ reset = any(isinstance(op, dict) and "createSurface" in op for op in operations)
1333
+ previous_operations = (
1334
+ previous["Content"]["a2ui_operations"] if previous and not reset else []
892
1335
  )
893
- return activities
1336
+ activities[surface_id] = {
1337
+ "SeqId": event.id,
1338
+ "Type": event.type,
1339
+ "MessageId": f"{run.id}:assistant",
1340
+ "SurfaceId": surface_id,
1341
+ "Content": {"a2ui_operations": [*previous_operations, *operations]},
1342
+ }
1343
+ return list(activities.values())
1344
+
1345
+ @staticmethod
1346
+ def _request_controls(payload: dict[str, Any]) -> tuple[str, str, str, str]:
1347
+ """Read turn controls from both legacy and shared-Web request shapes."""
1348
+
1349
+ metadata = payload.get("Metadata") or payload.get("metadata")
1350
+ metadata = metadata if isinstance(metadata, dict) else {}
1351
+ agentengine = metadata.get("agentengine")
1352
+ agentengine = agentengine if isinstance(agentengine, dict) else {}
1353
+ model_options = payload.get("ModelOptions") or payload.get("model_options")
1354
+ model_options = model_options if isinstance(model_options, dict) else {}
1355
+
1356
+ approval_mode = (
1357
+ str(
1358
+ payload.get("ApprovalMode")
1359
+ or payload.get("approval_mode")
1360
+ or metadata.get("approval_mode")
1361
+ or metadata.get("approvalMode")
1362
+ or agentengine.get("tool_approval_mode")
1363
+ or agentengine.get("approval_mode")
1364
+ or ""
1365
+ )
1366
+ .strip()
1367
+ .lower()
1368
+ )
1369
+ collaboration_mode = (
1370
+ str(
1371
+ payload.get("CollaborationMode")
1372
+ or payload.get("collaboration_mode")
1373
+ or metadata.get("collaboration_mode")
1374
+ or metadata.get("collaborationMode")
1375
+ or agentengine.get("collaboration_mode")
1376
+ or ""
1377
+ )
1378
+ .strip()
1379
+ .lower()
1380
+ )
1381
+ goal_objective = str(
1382
+ payload.get("GoalObjective")
1383
+ or payload.get("goal_objective")
1384
+ or metadata.get("goal_objective")
1385
+ or metadata.get("goalObjective")
1386
+ or agentengine.get("goal_objective")
1387
+ or ""
1388
+ ).strip()
1389
+ reasoning_effort = (
1390
+ str(
1391
+ payload.get("ReasoningEffort")
1392
+ or payload.get("reasoning_effort")
1393
+ or model_options.get("reasoning_effort")
1394
+ or model_options.get("reasoningEffort")
1395
+ or ""
1396
+ )
1397
+ .strip()
1398
+ .lower()
1399
+ )
1400
+ return approval_mode, collaboration_mode, goal_objective, reasoning_effort
894
1401
 
895
1402
  @staticmethod
896
1403
  def _input_text(payload: dict[str, Any]) -> str:
@@ -939,7 +1446,7 @@ class StudioSharedWebBridge:
939
1446
  if not isinstance(content, list):
940
1447
  continue
941
1448
  items: list[dict[str, str]] = []
942
- has_image = False
1449
+ has_attachment = False
943
1450
  for part in content:
944
1451
  if not isinstance(part, dict):
945
1452
  continue
@@ -954,14 +1461,25 @@ class StudioSharedWebBridge:
954
1461
  )
955
1462
  if url:
956
1463
  items.append({"type": "image", "url": url})
957
- has_image = True
958
- if items and has_image:
1464
+ has_attachment = True
1465
+ elif kind == "input_file":
1466
+ data = str(part.get("file_data") or part.get("file_url") or "")
1467
+ if data:
1468
+ items.append(
1469
+ {
1470
+ "type": "input_file",
1471
+ "file_data": data,
1472
+ "filename": str(part.get("filename") or "attachment"),
1473
+ }
1474
+ )
1475
+ has_attachment = True
1476
+ if items and has_attachment:
959
1477
  return items
960
1478
  return []
961
1479
 
962
1480
  @staticmethod
963
1481
  def _active_status(status: RunStatus) -> str:
964
- return "running" if status == RunStatus.RUNNING else ""
1482
+ return "running" if status in {RunStatus.RUNNING, RunStatus.WAITING_INPUT} else ""
965
1483
 
966
1484
  @staticmethod
967
1485
  def _run_output(run: RunRecord) -> str:
@@ -969,7 +1487,8 @@ class StudioSharedWebBridge:
969
1487
  return run.output
970
1488
  if run.error:
971
1489
  return str(run.error.get("message") or "Agent 运行失败")
972
- return f"运行状态:{run.status.value}"
1490
+ status = run.status.value if isinstance(run.status, RunStatus) else str(run.status)
1491
+ return f"运行状态:{status}"
973
1492
 
974
1493
  @staticmethod
975
1494
  def _short_title(value: str, limit: int = 36) -> str:
@@ -977,8 +1496,12 @@ class StudioSharedWebBridge:
977
1496
  return text if len(text) <= limit else f"{text[:limit]}..."
978
1497
 
979
1498
  @staticmethod
980
- def _timestamp(value: datetime | None) -> str:
981
- return (value or datetime.now(timezone.utc)).isoformat()
1499
+ def _timestamp(value: datetime | float | int | None) -> str:
1500
+ if isinstance(value, datetime):
1501
+ return value.isoformat()
1502
+ if isinstance(value, (float, int)):
1503
+ return datetime.fromtimestamp(value, tz=timezone.utc).isoformat()
1504
+ return datetime.now(timezone.utc).isoformat()
982
1505
 
983
1506
  @staticmethod
984
1507
  def _sse(event: str, payload: dict[str, Any]) -> str: