agentengine-sdk-python 0.8.4__py3-none-any.whl → 0.8.5__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 (673) hide show
  1. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +6 -3
  2. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/RECORD +591 -365
  3. ksadk/_build_provenance.json +1 -1
  4. ksadk/_process.py +83 -0
  5. ksadk/_str_enum.py +17 -0
  6. ksadk/a2ui/core.py +3 -3
  7. ksadk/api/client.py +6 -0
  8. ksadk/builders/code_builder.py +38 -12
  9. ksadk/builders/framework_requirements.py +20 -2
  10. ksadk/cli/__init__.py +36 -0
  11. ksadk/cli/cmd_config.py +4 -4
  12. ksadk/cli/cmd_create.py +12 -12
  13. ksadk/cli/cmd_hermes.py +24 -2
  14. ksadk/cli/cmd_invoke.py +28 -5
  15. ksadk/cli/cmd_openclaw.py +26 -1
  16. ksadk/cli/cmd_plugin.py +70 -12
  17. ksadk/cli/cmd_studio.py +64 -16
  18. ksadk/cli/openclaw_env.py +1 -1
  19. ksadk/cli/resource_common.py +26 -0
  20. ksadk/codex/client.py +3 -2
  21. ksadk/configs/__init__.py +1 -1
  22. ksadk/configs/env_registry.py +125 -31
  23. ksadk/configs/env_registry_studio.py +86 -0
  24. ksadk/configs/global_config.py +1 -1
  25. ksadk/configs/settings.py +3 -3
  26. ksadk/connector/__init__.py +17 -0
  27. ksadk/connector/channel.py +477 -0
  28. ksadk/context_engine/capabilities.py +52 -4
  29. ksadk/conversations/attachment_storage.py +10 -3
  30. ksadk/conversations/attachments.py +16 -5
  31. ksadk/conversations/message_projection.py +23 -32
  32. ksadk/conversations/normalize.py +28 -10
  33. ksadk/conversations/runtime_baseline.py +37 -0
  34. ksadk/conversations/runtime_invocation.py +17 -4
  35. ksadk/conversations/runtime_observability.py +39 -10
  36. ksadk/conversations/runtime_payloads.py +8 -0
  37. ksadk/conversations/runtime_persistence.py +105 -9
  38. ksadk/conversations/runtime_preparation.py +13 -7
  39. ksadk/conversations/runtime_stream_events.py +29 -35
  40. ksadk/conversations/runtime_streaming.py +8 -0
  41. ksadk/events/adapters/_codex_items.py +16 -8
  42. ksadk/events/adapters/_langgraph_support.py +34 -0
  43. ksadk/events/session_event.py +2 -2
  44. ksadk/harness/__init__.py +14 -0
  45. ksadk/harness/app.py +11 -0
  46. ksadk/harness/artifact_store.py +213 -0
  47. ksadk/harness/capabilities.py +115 -0
  48. ksadk/harness/capability_runtime.py +237 -0
  49. ksadk/harness/closure_contract.py +92 -0
  50. ksadk/harness/compaction_record.py +122 -0
  51. ksadk/harness/compiler.py +284 -0
  52. ksadk/harness/conformance/__init__.py +33 -0
  53. ksadk/harness/conformance/contract.py +506 -0
  54. ksadk/harness/conformance/fixtures.py +102 -0
  55. ksadk/harness/context_engine.py +403 -0
  56. ksadk/harness/context_maintenance.py +259 -0
  57. ksadk/harness/context_manifest.py +188 -0
  58. ksadk/harness/context_tuning.py +168 -0
  59. ksadk/harness/draft_runtime.py +322 -0
  60. ksadk/harness/engine/__init__.py +40 -0
  61. ksadk/harness/engine/base.py +122 -0
  62. ksadk/harness/engine/budgets.py +108 -0
  63. ksadk/harness/engine/capability_declarations.py +59 -0
  64. ksadk/harness/engine/completion_guard.py +42 -0
  65. ksadk/harness/engine/context_pipeline.py +579 -0
  66. ksadk/harness/engine/graph_builder.py +859 -0
  67. ksadk/harness/engine/langgraph.py +931 -0
  68. ksadk/harness/engine/mcp_disclosure.py +750 -0
  69. ksadk/harness/engine/policy_runtime.py +70 -0
  70. ksadk/harness/engine/postgres_checkpointer.py +63 -0
  71. ksadk/harness/engine/run_control_bridge.py +80 -0
  72. ksadk/harness/engine/run_types.py +88 -0
  73. ksadk/harness/engine/skill_disclosure.py +189 -0
  74. ksadk/harness/engine/spans.py +41 -0
  75. ksadk/harness/engine/subagents.py +343 -0
  76. ksadk/harness/engine/thread_ids.py +112 -0
  77. ksadk/harness/engine/tool_dispatch.py +144 -0
  78. ksadk/harness/event_tree.py +212 -0
  79. ksadk/harness/events.py +461 -0
  80. ksadk/harness/execution_policy.py +94 -0
  81. ksadk/harness/insights.py +210 -0
  82. ksadk/harness/lifecycle.py +578 -0
  83. ksadk/harness/lifecycle_conformance.py +233 -0
  84. ksadk/harness/lifecycle_local_plane.py +104 -0
  85. ksadk/harness/loop/__init__.py +44 -0
  86. ksadk/harness/loop/reason.py +454 -0
  87. ksadk/harness/loop/tools.py +762 -0
  88. ksadk/harness/managed_runtime.py +884 -0
  89. ksadk/harness/mcp_matrix.py +474 -0
  90. ksadk/harness/mcp_runtime.py +471 -0
  91. ksadk/harness/memory_consolidation.py +157 -0
  92. ksadk/harness/memory_loop.py +156 -0
  93. ksadk/harness/memory_runtime.py +541 -0
  94. ksadk/harness/metrics.py +90 -0
  95. ksadk/harness/model_capability.py +253 -0
  96. ksadk/harness/model_provider.py +220 -0
  97. ksadk/harness/observability/__init__.py +29 -0
  98. ksadk/harness/observability/inspection.py +528 -0
  99. ksadk/harness/observability/metrics.py +167 -0
  100. ksadk/harness/observability/otel_exporter.py +218 -0
  101. ksadk/harness/prompt_cache.py +70 -0
  102. ksadk/harness/public_activity.py +154 -0
  103. ksadk/harness/readiness.py +249 -0
  104. ksadk/harness/reasoner.py +466 -13
  105. ksadk/harness/release_readiness.py +140 -0
  106. ksadk/harness/resource_ref.py +69 -0
  107. ksadk/harness/run_control.py +668 -0
  108. ksadk/harness/runtime.py +146 -111
  109. ksadk/harness/runtime_capabilities.py +158 -0
  110. ksadk/harness/runtime_server.py +514 -0
  111. ksadk/harness/sandbox_adapters.py +739 -0
  112. ksadk/harness/sandbox_backend.py +530 -0
  113. ksadk/harness/sandbox_conformance.py +288 -0
  114. ksadk/harness/sandbox_lease.py +77 -0
  115. ksadk/harness/sandbox_lease_conformance.py +259 -0
  116. ksadk/harness/sandbox_matrix.py +170 -0
  117. ksadk/harness/sandbox_reconciliation.py +140 -0
  118. ksadk/harness/sandbox_recovery.py +586 -0
  119. ksadk/harness/sandbox_recovery_conformance.py +246 -0
  120. ksadk/harness/session_store.py +243 -0
  121. ksadk/harness/skill_composition.py +212 -0
  122. ksadk/harness/skill_feedback.py +123 -0
  123. ksadk/harness/skill_matrix.py +233 -0
  124. ksadk/harness/skill_runtime.py +259 -0
  125. ksadk/harness/spec.py +332 -0
  126. ksadk/harness/state.py +153 -0
  127. ksadk/harness/strategies.py +149 -0
  128. ksadk/harness/subagent.py +253 -0
  129. ksadk/harness/tool_policy.py +131 -0
  130. ksadk/harness/tool_receipts.py +96 -0
  131. ksadk/harness/tool_reliability.py +81 -0
  132. ksadk/harness/user_errors.py +69 -0
  133. ksadk/harness/working_context.py +81 -0
  134. ksadk/harness/working_context_patch.py +99 -0
  135. ksadk/identity/resolver.py +18 -0
  136. ksadk/interaction/__init__.py +1 -1
  137. ksadk/interaction/ledger.py +1 -1
  138. ksadk/interaction/provider.py +1 -1
  139. ksadk/interaction/providers/__init__.py +3 -1
  140. ksadk/interaction/providers/adk.py +1 -1
  141. ksadk/interaction/providers/codex.py +1 -1
  142. ksadk/interaction/providers/harness.py +50 -0
  143. ksadk/interaction/providers/langgraph.py +1 -1
  144. ksadk/kernel/__init__.py +10 -0
  145. ksadk/kernel/approval_presentation.py +91 -0
  146. ksadk/kernel/authorization.py +1 -1
  147. ksadk/kernel/bootstrap.py +86 -102
  148. ksadk/kernel/contract_fingerprints.py +1 -1
  149. ksadk/kernel/contracts.py +5 -0
  150. ksadk/kernel/control.py +32 -1
  151. ksadk/kernel/execution_grants.py +221 -0
  152. ksadk/kernel/execution_grants_memory.py +133 -0
  153. ksadk/kernel/execution_grants_postgres.py +217 -0
  154. ksadk/kernel/execution_grants_sqlite.py +209 -0
  155. ksadk/kernel/ingress.py +27 -27
  156. ksadk/kernel/mapping.py +1 -1
  157. ksadk/kernel/memory_store.py +24 -11
  158. ksadk/kernel/postgres_store.py +63 -33
  159. ksadk/kernel/recovery.py +78 -14
  160. ksadk/kernel/sql/001_agent_kernel.sql +23 -0
  161. ksadk/kernel/sqlite_store.py +304 -25
  162. ksadk/kernel/state.py +2 -3
  163. ksadk/kernel/store.py +69 -2
  164. ksadk/kernel/worker.py +79 -41
  165. ksadk/kernel/worker_history.py +72 -0
  166. ksadk/kernel/worker_identity.py +47 -0
  167. ksadk/memory/coordinator.py +22 -6
  168. ksadk/memory/extraction.py +40 -1
  169. ksadk/memory/models.py +77 -1
  170. ksadk/memory/provider_resolver.py +5 -0
  171. ksadk/memory/providers/local_postgres.py +200 -0
  172. ksadk/memory/providers/local_sqlite.py +42 -3
  173. ksadk/memory/retrieval.py +189 -0
  174. ksadk/memory/store_adapter.py +150 -0
  175. ksadk/model_policy.py +2 -2
  176. ksadk/model_proxy/detect.py +254 -0
  177. ksadk/model_proxy/server.py +4 -2
  178. ksadk/model_proxy/transform.py +40 -2
  179. ksadk/plugins/__init__.py +1 -1
  180. ksadk/plugins/bridges/dsh.py +11 -0
  181. ksadk/plugins/builtins.py +40 -2
  182. ksadk/plugins/companion_artifacts.py +83 -0
  183. ksadk/plugins/companions.py +368 -0
  184. ksadk/plugins/contracts.py +1 -1
  185. ksadk/plugins/dsh_channels.py +156 -0
  186. ksadk/plugins/dsh_home.py +140 -0
  187. ksadk/plugins/dsh_teams.py +105 -0
  188. ksadk/plugins/dsh_toolchain.py +101 -19
  189. ksadk/plugins/execution_host.py +99 -0
  190. ksadk/plugins/providers/bundles/dsh-channels-client/client.js +19 -0
  191. ksadk/plugins/providers/bundles/dsh-channels-client/cordis.patch.yml +3 -0
  192. ksadk/plugins/providers/bundles/dsh-channels-client/index.mjs +7 -0
  193. ksadk/plugins/providers/bundles/dsh-channels-client/package.json +12 -0
  194. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +1 -1
  195. ksadk/plugins/providers/bundles/dsh-memory/package.json +1 -1
  196. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +1 -1
  197. ksadk/plugins/providers/bundles/dsh-teams-client/client.js +29 -0
  198. ksadk/plugins/providers/bundles/dsh-teams-client/cordis.patch.yml +3 -0
  199. ksadk/plugins/providers/bundles/dsh-teams-client/index.mjs +11 -0
  200. ksadk/plugins/providers/bundles/dsh-teams-client/package.json +35 -0
  201. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/cordis.patch.yml +3 -0
  202. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/index.mjs +13 -0
  203. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/package.json +27 -0
  204. ksadk/plugins/providers/bundles/dsh-teams-profile/cordis.patch.yml +3 -0
  205. ksadk/plugins/providers/bundles/dsh-teams-profile/index.mjs +12 -0
  206. ksadk/plugins/providers/bundles/dsh-teams-profile/package.json +26 -0
  207. ksadk/plugins/providers/bundles/dsh-teams-router/cordis.patch.yml +3 -0
  208. ksadk/plugins/providers/bundles/dsh-teams-router/index.mjs +16 -0
  209. ksadk/plugins/providers/bundles/dsh-teams-router/package.json +27 -0
  210. ksadk/plugins/providers/bundles/dsh-teams-tasks/cordis.patch.yml +3 -0
  211. ksadk/plugins/providers/bundles/dsh-teams-tasks/index.mjs +16 -0
  212. ksadk/plugins/providers/bundles/dsh-teams-tasks/package.json +27 -0
  213. ksadk/plugins/providers/bundles/dsh-teams-tools/cordis.patch.yml +3 -0
  214. ksadk/plugins/providers/bundles/dsh-teams-tools/index.mjs +25 -0
  215. ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +29 -0
  216. ksadk/plugins/providers/bundles/dsh-teams-tools/tools.json +235 -0
  217. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +1 -1
  218. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +51 -1
  219. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +2 -2
  220. ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/client.mjs +133 -0
  221. ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/index.mjs +14 -0
  222. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +27 -4
  223. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +9 -5
  224. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
  225. ksadk/plugins/providers/codex.py +10 -2
  226. ksadk/plugins/providers/dsh_capabilities.py +61 -0
  227. ksadk/plugins/providers/harness.py +181 -33
  228. ksadk/plugins/providers/harness_delegation.py +593 -0
  229. ksadk/plugins/providers/harness_managed.py +456 -0
  230. ksadk/plugins/providers/harness_tools.py +326 -0
  231. ksadk/plugins/providers/shipped_dsh.py +4 -1
  232. ksadk/plugins/subagent_providers/codex.py +28 -6
  233. ksadk/plugins/teams/__init__.py +5 -0
  234. ksadk/plugins/teams/api.py +405 -0
  235. ksadk/plugins/teams/application.py +680 -0
  236. ksadk/plugins/teams/artifacts.py +60 -0
  237. ksadk/plugins/teams/context.py +96 -0
  238. ksadk/plugins/teams/contracts.py +136 -0
  239. ksadk/plugins/teams/domain.py +1427 -0
  240. ksadk/plugins/teams/domain_values.py +24 -0
  241. ksadk/plugins/teams/errors.py +13 -0
  242. ksadk/plugins/teams/migration.py +311 -0
  243. ksadk/plugins/teams/migration_cli.py +322 -0
  244. ksadk/plugins/teams/postgres_store.py +138 -0
  245. ksadk/plugins/teams/runtime.py +777 -0
  246. ksadk/plugins/teams/source_projection.py +84 -0
  247. ksadk/plugins/teams/store.py +311 -0
  248. ksadk/plugins/teams/task_decisions.py +423 -0
  249. ksadk/plugins/teams/transport.py +91 -0
  250. ksadk/plugins/teams/workspaces.py +255 -0
  251. ksadk/runners/_langgraph_runner_streams.py +121 -45
  252. ksadk/runners/_langgraph_state_reader.py +106 -0
  253. ksadk/runners/_session_identity.py +285 -0
  254. ksadk/runners/adk_runner.py +25 -60
  255. ksadk/runners/langgraph_runner.py +128 -111
  256. ksadk/runners/patch_langchain.py +47 -0
  257. ksadk/runners/usage_accumulator.py +11 -3
  258. ksadk/runtime/_runner_adapter/stream_mapping.py +52 -2
  259. ksadk/runtime/conversation_execution.py +25 -1
  260. ksadk/runtime/executor.py +9 -1
  261. ksadk/runtime/factory.py +36 -1
  262. ksadk/runtime/preprocessing.py +11 -3
  263. ksadk/runtime/runner_adapter.py +38 -9
  264. ksadk/runtime/skill_eval_result.py +36 -0
  265. ksadk/runtime/timing.py +46 -0
  266. ksadk/runtime/usage.py +49 -18
  267. ksadk/runtime_context.py +103 -1
  268. ksadk/sandbox/backends/e2b.py +245 -23
  269. ksadk/sandbox/backends/local_process.py +63 -39
  270. ksadk/sandbox/base.py +62 -1
  271. ksadk/sandbox/diagnostics.py +82 -0
  272. ksadk/sandbox/local_controls.py +746 -0
  273. ksadk/sandbox/local_launcher.py +90 -0
  274. ksadk/scheduler/dispatcher.py +1 -1
  275. ksadk/server/invocation_identity.py +118 -0
  276. ksadk/server/routes/common.py +32 -3
  277. ksadk/server/routes/control.py +64 -9
  278. ksadk/server/routes/dependencies.py +2 -1
  279. ksadk/server/routes/kernel_ingress.py +9 -1
  280. ksadk/server/routes/misc.py +233 -25
  281. ksadk/server/routes/models.py +3 -3
  282. ksadk/server/routes/openai_compat.py +76 -13
  283. ksadk/server/routes/run.py +106 -35
  284. ksadk/server/routes/sessions.py +244 -68
  285. ksadk/server/routes/workspace.py +130 -21
  286. ksadk/server/static/assets/{ArtifactsPanel-CGbWlMNh.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
  287. ksadk/server/static/assets/{CodeBlock-b4C7upmO.js → CodeBlock-DHuAWfr5.js} +10 -7
  288. ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
  289. ksadk/server/static/assets/{MermaidBlock-BEBN4Ksz.js → MermaidBlock-DeBkbJvI.js} +9 -9
  290. ksadk/server/static/assets/{NativeTerminalPanel-zvL-WpAn.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
  291. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-BYafW7Za.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
  292. ksadk/server/static/assets/{arc-bTohInsS.js → arc-C35w-pn1.js} +1 -1
  293. ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
  294. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-Ch5Lbzsi.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
  295. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-kqF4MDOG.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
  296. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-8uSRIODv.js → c4Diagram-UCG6FXSJ-BCtGGkhN.js} +1 -1
  297. ksadk/server/static/assets/channel-_KDifNys.js +1 -0
  298. ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +1 -0
  299. ksadk/server/static/assets/{chunk-5VM5RSS4-DkhehZDr.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
  300. ksadk/server/static/assets/{chunk-F27PBJKO-BdXhtPe9.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
  301. ksadk/server/static/assets/{chunk-G27WJ6UU-DPTpvpwi.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
  302. ksadk/server/static/assets/{chunk-JWPE2WC7-Pqoh38el.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
  303. ksadk/server/static/assets/{chunk-LCL6LL3I-DeU00qC-.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
  304. ksadk/server/static/assets/{chunk-POPQ4Y6H-CzxScFkr.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
  305. ksadk/server/static/assets/{chunk-RHFEMEQ7-DpqMx-ux.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
  306. ksadk/server/static/assets/{chunk-SVP7TREG-C6t0SypQ.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
  307. ksadk/server/static/assets/{chunk-XXDRQBXY-DVaeafZk.js → chunk-XXDRQBXY-Bx1jS-X-.js} +1 -1
  308. ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +1 -0
  309. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +1 -0
  310. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-Bf9D3tzJ.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
  311. ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
  312. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-B9cY3iTz.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
  313. ksadk/server/static/assets/{dagre-3AP2YEHR-CSwlx3CB.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
  314. ksadk/server/static/assets/{dagre-UBpgon5q.js → dagre-B7nCawed.js} +1 -1
  315. ksadk/server/static/assets/{diagram-S7CK7UJ4-C9akhN9a.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
  316. ksadk/server/static/assets/{diagram-UQ7AKVKN-CgedhTPI.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
  317. ksadk/server/static/assets/{diagram-VSXAHHWV-Cjucz5BY.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
  318. ksadk/server/static/assets/{diagram-VX7I27RA-Dd4Vleyn.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
  319. ksadk/server/static/assets/{diagram-Z3DM3KII-CZ2jGtYW.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
  320. ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
  321. ksadk/server/static/assets/{dist-DiixqL0J.js → dist-1nXCdsej.js} +1 -1
  322. ksadk/server/static/assets/{dist-BIr4DSRq.js → dist-2vL2sAdF.js} +1 -1
  323. ksadk/server/static/assets/{dist-D_ctSS2i.js → dist-B3bA05-e.js} +1 -1
  324. ksadk/server/static/assets/{dist-ClYUxfeK.js → dist-BLpRy_Yx.js} +1 -1
  325. ksadk/server/static/assets/{dist-QfkEHOlb.js → dist-BO_UwatH.js} +1 -1
  326. ksadk/server/static/assets/{dist-B3FR1SKK.js → dist-BdNFAney.js} +1 -1
  327. ksadk/server/static/assets/{dist-BnaTiyzN.js → dist-C0J5_3qM.js} +1 -1
  328. ksadk/server/static/assets/{dist-Bj730Ib4.js → dist-CGt_UGeO.js} +1 -1
  329. ksadk/server/static/assets/{dist-CFzsn6BG.js → dist-CIRMvUM4.js} +1 -1
  330. ksadk/server/static/assets/{dist-BgV_owcB.js → dist-CIpWk_5f.js} +1 -1
  331. ksadk/server/static/assets/{dist-C5_ZAZsG.js → dist-CPyieXEf.js} +1 -1
  332. ksadk/server/static/assets/{dist-btbmmX5O.js → dist-D-92S-Fd.js} +1 -1
  333. ksadk/server/static/assets/{dist-fBO2v5Kt.js → dist-DNKuMzWc.js} +1 -1
  334. ksadk/server/static/assets/{dist-ufY3F5p6.js → dist-DWfdmz9s.js} +2 -2
  335. ksadk/server/static/assets/{dist-DVCOWtha.js → dist-DppE_r-D.js} +1 -1
  336. ksadk/server/static/assets/{dist-C1NMAY5a.js → dist-DyG6Ya-z.js} +1 -1
  337. ksadk/server/static/assets/{dist-CB9iJrvg.js → dist-M-SrdhhZ.js} +1 -1
  338. ksadk/server/static/assets/{dist-DvFK7p5S.js → dist-mqD5TZup.js} +1 -1
  339. ksadk/server/static/assets/{dist-Cf125P_m.js → dist-n3n6t_FO.js} +1 -1
  340. ksadk/server/static/assets/{dist-DFD6Qa6T.js → dist-qe8xjesy.js} +1 -1
  341. ksadk/server/static/assets/{dist-DoVSwoDb.js → dist-t6MzE0jU.js} +1 -1
  342. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Ci8NqqZu.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
  343. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CCIOhLZG.js → erDiagram-SSCWMZ5O-Dpz9_0zn.js} +1 -1
  344. ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +1 -0
  345. ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +1 -0
  346. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
  347. ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
  348. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js → gitGraphDiagram-WWUBYQGX-DcxzRwYC.js} +1 -1
  349. ksadk/server/static/assets/index-BMd2mucF.css +2 -0
  350. ksadk/server/static/assets/index-D5qyyhTH.js +244 -0
  351. ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +1 -0
  352. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CO0rRTRA.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
  353. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CHiaedSS.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
  354. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-CHcCIB09.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
  355. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CJ_ebBZf.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
  356. ksadk/server/static/assets/{katex-B4weu383.js → katex-mtjOi4KM.js} +1 -1
  357. ksadk/server/static/assets/{linear-V-MgYHW1.js → linear-BETqsxE_.js} +1 -1
  358. ksadk/server/static/assets/{mermaid-parser.core-CBijEX_c.js → mermaid-parser.core-DPWrvs90.js} +2 -2
  359. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-Bc-pQvpp.js → mindmap-definition-FBJOCRG2-CJG2mfBP.js} +1 -1
  360. ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +1 -0
  361. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-D7genGLl.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
  362. ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
  363. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-Bxj32zwD.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
  364. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BURv2mGh.js → quadrantDiagram-AXDQQJYC-4d78KiEY.js} +1 -1
  365. ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +1 -0
  366. ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +1 -0
  367. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +1 -0
  368. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +1 -0
  369. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +1 -0
  370. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-CCsh3avW.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
  371. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-_FRRBKEd.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
  372. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-C-gr2o9M.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
  373. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-D97NmfKg.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
  374. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DjrPC5FX.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
  375. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DzMNg1hh.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
  376. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
  377. ksadk/server/static/assets/{swimlanes-XN3QIQJK-Cssf_CsU.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
  378. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
  379. ksadk/server/static/assets/{timeline-definition-24CTP7MA-BWTHzyS1.js → timeline-definition-24CTP7MA-CMD3x_U_.js} +1 -1
  380. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +1 -0
  381. ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +1 -0
  382. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-BSKgJsmR.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
  383. ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
  384. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-eflHNoaZ.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
  385. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-eYqrQ-v4.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
  386. ksadk/server/static/index.html +2 -2
  387. ksadk/server/terminal_sessions.py +34 -2
  388. ksadk/sessions/invocation_identity.py +235 -0
  389. ksadk/skills/__init__.py +26 -0
  390. ksadk/skills/events.py +464 -0
  391. ksadk/skills/manifest_cache.py +263 -0
  392. ksadk/skills/mcp_server/__init__.py +0 -0
  393. ksadk/skills/mcp_server/_registry.py +33 -0
  394. ksadk/skills/mcp_server/_routing.py +26 -0
  395. ksadk/skills/mcp_server/_workspace_files.py +160 -0
  396. ksadk/skills/mcp_server/register.py +415 -0
  397. ksadk/skills/mcp_server/server.py +218 -0
  398. ksadk/skills/models.py +11 -0
  399. ksadk/skills/observability.py +132 -0
  400. ksadk/skills/package_store.py +75 -2
  401. ksadk/skills/runtime/agent.py +38 -5
  402. ksadk/skills/runtime/artifacts.py +87 -0
  403. ksadk/skills/runtime/backends/e2b.py +393 -52
  404. ksadk/skills/runtime/backends/local.py +621 -119
  405. ksadk/skills/runtime/base.py +78 -7
  406. ksadk/skills/runtime/executor.py +266 -1
  407. ksadk/skills/runtime/loader.py +108 -3
  408. ksadk/skills/runtime/request.py +18 -0
  409. ksadk/skills/tool_defs.py +108 -3
  410. ksadk/studio/api.py +592 -57
  411. ksadk/studio/api_contracts.py +8 -2
  412. ksadk/studio/api_plugin_routes.py +39 -12
  413. ksadk/studio/api_resource_connections.py +79 -41
  414. ksadk/studio/authoring.py +12 -6
  415. ksadk/studio/authoring_coordinator.py +4 -2
  416. ksadk/studio/builder.py +12 -0
  417. ksadk/studio/capabilities.py +23 -6
  418. ksadk/studio/channel_connections.py +333 -0
  419. ksadk/studio/cloud.py +30 -10
  420. ksadk/studio/cloud_shared_web.py +75 -2
  421. ksadk/studio/codex_agent_service.py +2 -2
  422. ksadk/studio/codex_builder.py +1 -1
  423. ksadk/studio/codex_run.py +6 -1
  424. ksadk/studio/compiler.py +10 -0
  425. ksadk/studio/configuration.py +182 -0
  426. ksadk/studio/contracts.py +33 -5
  427. ksadk/studio/dsh_application.py +135 -25
  428. ksadk/studio/dsh_capability_service.py +287 -20
  429. ksadk/studio/dsh_lifecycle.py +58 -0
  430. ksadk/studio/dsh_provider_registration.py +55 -16
  431. ksadk/studio/entry.py +53 -0
  432. ksadk/studio/event_store.py +36 -5
  433. ksadk/studio/execution_host.py +525 -0
  434. ksadk/studio/framework_run.py +32 -10
  435. ksadk/studio/hosted_kernel.py +1 -1
  436. ksadk/studio/kernel_registry.py +418 -0
  437. ksadk/studio/kernel_sqlite_migration.py +181 -0
  438. ksadk/studio/model_client.py +1178 -64
  439. ksadk/studio/model_profile_service.py +26 -11
  440. ksadk/studio/native_documents.py +172 -0
  441. ksadk/studio/plugin_composition.py +13 -2
  442. ksadk/studio/plugin_kernel_adapter.py +15 -0
  443. ksadk/studio/plugin_lifecycle.py +80 -0
  444. ksadk/studio/plugin_runtime.py +230 -17
  445. ksadk/studio/provider_recovery.py +59 -0
  446. ksadk/studio/recovery_page.py +70 -0
  447. ksadk/studio/resource_authority.py +59 -32
  448. ksadk/studio/resource_catalog.py +6 -0
  449. ksadk/studio/run_activity.py +895 -0
  450. ksadk/studio/run_documents.py +127 -0
  451. ksadk/studio/run_service.py +329 -33
  452. ksadk/studio/runtime_catalog.py +53 -10
  453. ksadk/studio/runtime_source.py +1 -1
  454. ksadk/studio/scheduler_runtime.py +32 -289
  455. ksadk/studio/service.py +398 -103
  456. ksadk/studio/shared_web.py +149 -36
  457. ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +8 -0
  458. ksadk/studio/static/assets/CodeBlock-DMIf4h33-UIqo-BPW.js +44 -0
  459. ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -0
  460. ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-OhNwH4K9.js +8 -0
  461. ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
  462. ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-g0I-I4dD.js +59 -0
  463. ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
  464. ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +3 -0
  465. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
  466. ksadk/studio/static/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
  467. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
  468. ksadk/studio/static/assets/{blockDiagram-I7D4REHJ-CFmPl1de.js → blockDiagram-I7D4REHJ-CLB4L11u.js} +6 -6
  469. ksadk/studio/static/assets/{c4Diagram-7LVT6UL2-BRrGu8qt.js → c4Diagram-7LVT6UL2-BOma_Z_F.js} +7 -7
  470. ksadk/studio/static/assets/channel-r8itPEik.js +1 -0
  471. ksadk/studio/static/assets/chunk-2E4U76K2-BFf_huql.js +2 -0
  472. ksadk/studio/static/assets/chunk-2ZTRR5NV-C2qZJila.js +2 -0
  473. ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
  474. ksadk/studio/static/assets/{chunk-4HAMMTFA-D220vUtq.js → chunk-4HAMMTFA-DVtDP4rm.js} +7 -7
  475. ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
  476. ksadk/studio/static/assets/chunk-6AZGARVD-BB6FqMl-.js +1 -0
  477. ksadk/studio/static/assets/chunk-6EIED4P4-DdUJkP0f.js +1 -0
  478. ksadk/studio/static/assets/chunk-6K3QC6MW-CqVsVn-y.js +1 -0
  479. ksadk/studio/static/assets/chunk-6TQVIW2G-DKlLbNIP.js +1 -0
  480. ksadk/studio/static/assets/chunk-747NJXEK-BFkZPlab.js +2 -0
  481. ksadk/studio/static/assets/chunk-75Z2AOVW-BZNhM4vB.js +2 -0
  482. ksadk/studio/static/assets/chunk-CLGD4ZFX-D-GTtyKs.js +1 -0
  483. ksadk/studio/static/assets/{chunk-DU6HZSFF-C4DtVpCu.js → chunk-DU6HZSFF-CpEZCUgg.js} +1 -1
  484. ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
  485. ksadk/studio/static/assets/{chunk-GMAD6QVW-DiQA-u2N.js → chunk-GMAD6QVW-DE_8H717.js} +6 -6
  486. ksadk/studio/static/assets/chunk-GVQU2GXP-BfEB0lNv.js +1 -0
  487. ksadk/studio/static/assets/chunk-I5DQTOEV-Hm2LfiYI.js +1 -0
  488. ksadk/studio/static/assets/chunk-ICYGCRZG-749o-pGJ.js +1 -0
  489. ksadk/studio/static/assets/chunk-IH6LHLGP-CC6I9F3i.js +1 -0
  490. ksadk/studio/static/assets/{chunk-IMKFNOWR-BSlbjT_b.js → chunk-IMKFNOWR-D38axYOR.js} +5 -5
  491. ksadk/studio/static/assets/chunk-KI3K4JFJ-Rma-0k_M.js +1 -0
  492. ksadk/studio/static/assets/chunk-L3NEJ4N5-Dq5xn7aL.js +1 -0
  493. ksadk/studio/static/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
  494. ksadk/studio/static/assets/{chunk-OSK3NFVY-M2m6G3j4.js → chunk-OSK3NFVY-DiCQjx9b.js} +5 -5
  495. ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
  496. ksadk/studio/static/assets/{chunk-P2QGCYS3-DezaQxiK.js → chunk-P2QGCYS3-VdhKmfYq.js} +1 -1
  497. ksadk/studio/static/assets/chunk-POPQ4Y6H-C1_rzO5M.js +1 -0
  498. ksadk/studio/static/assets/chunk-PWAF6VOD-B45HvflI.js +1 -0
  499. ksadk/studio/static/assets/{chunk-SHT3W25Y-DAyIVp5H.js → chunk-SHT3W25Y-DsCFnRVE.js} +9 -9
  500. ksadk/studio/static/assets/{chunk-SVP7TREG-DulomOrS.js → chunk-SVP7TREG-DljApgRX.js} +1 -1
  501. ksadk/studio/static/assets/{chunk-TICWLB2K-bHJYoflj.js → chunk-TICWLB2K-DWqRtyqa.js} +6 -6
  502. ksadk/studio/static/assets/chunk-TLUHSLCS-DUeGgnD5.js +2 -0
  503. ksadk/studio/static/assets/chunk-UY3FDG6J-CnmaAkG5.js +1 -0
  504. ksadk/studio/static/assets/chunk-XHIXRSVI-BFQ6B8BE.js +1 -0
  505. ksadk/studio/static/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  506. ksadk/studio/static/assets/classDiagram-ZZMXUADV-DjeMNJmu.js +1 -0
  507. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-DjeMNJmu.js +1 -0
  508. ksadk/studio/static/assets/clsx-DB0hHKMi.js +1 -0
  509. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-om8AY0Mc.js +1 -0
  510. ksadk/studio/static/assets/createLucideIcon-DR0LGTP5.js +1 -0
  511. ksadk/studio/static/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
  512. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-6BrmK52S.js +62 -0
  513. ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
  514. ksadk/studio/static/assets/{diagram-S7CK7UJ4-0BZ98mya.js → diagram-S7CK7UJ4-C6aH78c4.js} +3 -3
  515. ksadk/studio/static/assets/diagram-UQ7AKVKN-DY_tQ6C_.js +41 -0
  516. ksadk/studio/static/assets/diagram-VSXAHHWV-DX9p5cQT.js +3 -0
  517. ksadk/studio/static/assets/diagram-VX7I27RA-DB2WSH8X.js +24 -0
  518. ksadk/studio/static/assets/diagram-Z3DM3KII-Ce1BJwHE.js +24 -0
  519. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
  520. ksadk/studio/static/assets/{erDiagram-RLTQ6QDP-DLGry2Ap.js → erDiagram-RLTQ6QDP-CGthTMmJ.js} +6 -6
  521. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
  522. ksadk/studio/static/assets/flowDiagram-HODETNUW-CZ1tEenp.js +1 -0
  523. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BfoAZW9X.js +292 -0
  524. ksadk/studio/static/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
  525. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-S985OIJF.js +106 -0
  526. ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
  527. ksadk/studio/static/assets/index-CfEnms6Y.css +2 -0
  528. ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
  529. ksadk/studio/static/assets/index.dom-BQenBtFm.js +1 -0
  530. ksadk/studio/static/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
  531. ksadk/studio/static/assets/infoDiagram-27XIBGKW-CO3W8tFn.js +2 -0
  532. ksadk/studio/static/assets/{ishikawaDiagram-5VMMS53U-CljI2wyf.js → ishikawaDiagram-5VMMS53U-BUGEl8cO.js} +2 -2
  533. ksadk/studio/static/assets/{journeyDiagram-3NMN7TZE-D50Fo2sL.js → journeyDiagram-3NMN7TZE-Ch2ZYxvr.js} +6 -6
  534. ksadk/studio/static/assets/{kanban-definition-UXKFOSKX-DimfOTam.js → kanban-definition-UXKFOSKX-Da-Fp4vC.js} +3 -3
  535. ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
  536. ksadk/studio/static/assets/{line-CX5BOOUP.js → line-BDaeq300.js} +1 -1
  537. ksadk/studio/static/assets/linear-DmucvK78.js +1 -0
  538. ksadk/studio/static/assets/mermaid-parser.core-Cj5mYdBi.js +4 -0
  539. ksadk/studio/static/assets/{mindmap-definition-YA3MSWOX-Bizzqy5R.js → mindmap-definition-YA3MSWOX-CvlsVQ38.js} +1 -1
  540. ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
  541. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-BuHuNgT5.js +1 -0
  542. ksadk/studio/static/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
  543. ksadk/studio/static/assets/{pieDiagram-E7YTZNPT-B9mrFSDF.js → pieDiagram-E7YTZNPT-DlrWiSOv.js} +1 -1
  544. ksadk/studio/static/assets/preload-helper-CO68xz6u.js +1 -0
  545. ksadk/studio/static/assets/presentation-yYw7xK60-BmcZriri.js +1 -0
  546. ksadk/studio/static/assets/{quadrantDiagram-AXDQQJYC-NzUfCbMR.js → quadrantDiagram-AXDQQJYC-BA3hpUZM.js} +6 -6
  547. ksadk/studio/static/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
  548. ksadk/studio/static/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
  549. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
  550. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
  551. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
  552. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-BxpAazym.js +1 -0
  553. ksadk/studio/static/assets/{requirementDiagram-BXWQKSXE-BF3d103U.js → requirementDiagram-BXWQKSXE-E-Ge0FcV.js} +1 -1
  554. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
  555. ksadk/studio/static/assets/{sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js → sequenceDiagram-WJ2MYXX4-CcElXGg4.js} +9 -9
  556. ksadk/studio/static/assets/src-B6xuSHsQ.js +1 -0
  557. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DdXZOFqY.js +1 -0
  558. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-CJbOM-QK.js +1 -0
  559. ksadk/studio/static/assets/swimlanes-42K2YHIH-NtgEEHLY.js +1 -0
  560. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-D-AVlW8B.js +8 -0
  561. ksadk/studio/static/assets/{timeline-definition-24CTP7MA-DxmSSjRB.js → timeline-definition-24CTP7MA-CIuYhNy3.js} +7 -7
  562. ksadk/studio/static/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
  563. ksadk/studio/static/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
  564. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-7HbApbrv.js +34 -0
  565. ksadk/studio/static/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
  566. ksadk/studio/static/assets/{wardleyDiagram-VM6X3IG4-Ba1AOWoe.js → wardleyDiagram-VM6X3IG4-CMJiaedy.js} +1 -1
  567. ksadk/studio/static/assets/{xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js → xychartDiagram-S5SC5T6Z-BdgtMvW2.js} +6 -6
  568. ksadk/studio/static/index.html +8 -2
  569. ksadk/studio/teams_catalog.py +133 -0
  570. ksadk/studio/teams_installation.py +214 -0
  571. ksadk/studio/teams_node.py +545 -0
  572. ksadk/studio/teams_node_runner.py +69 -0
  573. ksadk/studio/teams_remote.py +274 -0
  574. ksadk/studio/templates.py +40 -19
  575. ksadk/studio/validator.py +13 -0
  576. ksadk/studio/workspace.py +19 -4
  577. ksadk/studio/workspace_plugins.py +136 -0
  578. ksadk/studio/workspace_registry.py +286 -0
  579. ksadk/toolsets/__init__.py +11 -0
  580. ksadk/toolsets/skills.py +446 -378
  581. ksadk/toolsets/workspace.py +3 -3
  582. ksadk/toolsets/workspace_identity.py +15 -0
  583. ksadk/version.py +1 -1
  584. ksadk_runtime_common/memory_backend/providers/lancedb.py +56 -2
  585. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -148
  586. ksadk_runtime_common/workspace_files/router.py +26 -13
  587. ksadk/server/static/assets/MathMessageMarkdown-DbdW5A4_.js +0 -8
  588. ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +0 -1
  589. ksadk/server/static/assets/channel-CF5Up3hQ.js +0 -1
  590. ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +0 -1
  591. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +0 -1
  592. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +0 -1
  593. ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +0 -1
  594. ksadk/server/static/assets/dist-B2_CVgKv.js +0 -1
  595. ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +0 -1
  596. ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +0 -1
  597. ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +0 -1
  598. ksadk/server/static/assets/index-DcTML1Up.css +0 -2
  599. ksadk/server/static/assets/index-Dh2XHqPK.js +0 -244
  600. ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +0 -1
  601. ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +0 -1
  602. ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +0 -1
  603. ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +0 -1
  604. ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +0 -1
  605. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +0 -1
  606. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +0 -1
  607. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +0 -1
  608. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +0 -1
  609. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +0 -8
  610. ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +0 -1
  611. ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +0 -1
  612. ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +0 -1
  613. ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +0 -41
  614. ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +0 -8
  615. ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +0 -44
  616. ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +0 -3
  617. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +0 -1
  618. ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +0 -1
  619. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +0 -36
  620. ksadk/studio/static/assets/channel-BqO-gtEw.js +0 -1
  621. ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +0 -2
  622. ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +0 -1
  623. ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +0 -1
  624. ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +0 -1
  625. ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +0 -1
  626. ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +0 -1
  627. ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +0 -1
  628. ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +0 -1
  629. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +0 -1
  630. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +0 -1
  631. ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +0 -1
  632. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +0 -62
  633. ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +0 -4
  634. ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +0 -41
  635. ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +0 -3
  636. ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +0 -24
  637. ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +0 -24
  638. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +0 -1
  639. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +0 -1
  640. ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +0 -1
  641. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +0 -292
  642. ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +0 -1
  643. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +0 -106
  644. ksadk/studio/static/assets/index-CeHL9ARV.css +0 -2
  645. ksadk/studio/static/assets/index-D9QEcVpL.js +0 -320
  646. ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +0 -1
  647. ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +0 -2
  648. ksadk/studio/static/assets/linear-BCxN9JLv.js +0 -1
  649. ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +0 -7
  650. ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +0 -1
  651. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +0 -1
  652. ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +0 -1
  653. ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +0 -1
  654. ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +0 -1
  655. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +0 -1
  656. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +0 -1
  657. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +0 -1
  658. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +0 -1
  659. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +0 -40
  660. ksadk/studio/static/assets/src-SFn9St9H.js +0 -1
  661. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +0 -1
  662. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +0 -1
  663. ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +0 -1
  664. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +0 -8
  665. ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +0 -1
  666. ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +0 -1
  667. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +0 -34
  668. ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +0 -1
  669. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
  670. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
  671. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
  672. {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
  673. /ksadk/studio/static/assets/{MathMessageMarkdown-CBcDrAw--BEOyPC3w.css → MathMessageMarkdown-BesSeCYl-BEOyPC3w.css} +0 -0
ksadk/studio/service.py CHANGED
@@ -7,6 +7,7 @@ import hashlib
7
7
  import json
8
8
  import logging
9
9
  import os
10
+ import time
10
11
  import zipfile
11
12
  from collections.abc import AsyncIterator, Awaitable, Mapping, Sequence
12
13
  from contextlib import asynccontextmanager
@@ -88,6 +89,7 @@ from ksadk.studio.codex_plugin_store import CodexPluginSnapshotStore
88
89
  from ksadk.studio.codex_provider_build import CodexProviderBuildManager
89
90
  from ksadk.studio.codex_run import CodexRunSpecResolver
90
91
  from ksadk.studio.compiler import AgentCompiler
92
+ from ksadk.studio.configuration import SETTINGS_ENV, WorkspaceConfiguration
91
93
  from ksadk.studio.contracts import (
92
94
  AgentAppearance,
93
95
  AgentBindings,
@@ -102,6 +104,7 @@ from ksadk.studio.contracts import (
102
104
  DiagnosticSeverity,
103
105
  Operation,
104
106
  OperationKind,
107
+ OperationStatus,
105
108
  RunEvent,
106
109
  RunStatus,
107
110
  RuntimeRef,
@@ -123,7 +126,7 @@ from ksadk.studio.model_profile_service import test_model_profile_connection
123
126
  from ksadk.studio.operations import OperationManager
124
127
  from ksadk.studio.plugin_composition import StudioPluginCompositionCompiler
125
128
  from ksadk.studio.plugin_runtime import StudioPluginRuntime
126
- from ksadk.studio.repository import AgentDraftRepository, BuildRepository, load_yaml_file
129
+ from ksadk.studio.repository import AgentDraftRepository, BuildRepository
127
130
  from ksadk.studio.resource_authority import (
128
131
  ResourceAuthorityPolicy,
129
132
  SignedKnowledgeResourceAuthority,
@@ -149,9 +152,11 @@ from ksadk.studio.templates import (
149
152
  compose_research_agent,
150
153
  default_agent_spec,
151
154
  list_agent_templates,
155
+ with_harness_provider_permissions,
152
156
  )
153
157
  from ksadk.studio.validator import AgentValidator
154
158
  from ksadk.studio.workspace import Workspace
159
+ from ksadk.studio.workspace_registry import WorkspaceRegistry
155
160
 
156
161
  _T = TypeVar("_T")
157
162
 
@@ -186,6 +191,7 @@ class StudioService:
186
191
  dsh_provider_registration_manager: StudioDshProviderRegistrationManager | None = None,
187
192
  dsh_capability_service: StudioDshCapabilityService | None = None,
188
193
  resource_authority_policy: ResourceAuthorityPolicy | None = None,
194
+ configuration_overrides: dict[str, str] | None = None,
189
195
  ) -> None:
190
196
  provider_manifests = dict(plugin_provider_manifests or {})
191
197
  provider_factories = dict(plugin_provider_factories or {})
@@ -195,6 +201,8 @@ class StudioService:
195
201
  )
196
202
  self.workspace = Workspace(root)
197
203
  self.workspace.initialize()
204
+ self.workspace_registry = WorkspaceRegistry()
205
+ self.workspace_record = self.workspace_registry.open(self.workspace.root)
198
206
  self._startup_provider_manifests = provider_manifests
199
207
  self._startup_provider_factories = provider_factories
200
208
  self._active_provider_manifests = dict(provider_manifests)
@@ -208,9 +216,11 @@ class StudioService:
208
216
  dsh_capability_service
209
217
  or StudioDshCapabilityService.discover_or_create_workspace_default(self.workspace.root)
210
218
  )
211
- if dsh_capability_service is not None or os.environ.get(
212
- "KSADK_DSH_HOME", ""
213
- ).strip() or os.environ.get("KSADK_DSH_PROFILE", "").strip():
219
+ if (
220
+ dsh_capability_service is not None
221
+ or os.environ.get("KSADK_DSH_HOME", "").strip()
222
+ or os.environ.get("KSADK_DSH_PROFILE", "").strip()
223
+ ):
214
224
  self._resource_dsh_provider_registration_manager = None
215
225
  self.resource_dsh_capabilities = self.dsh_capabilities
216
226
  else:
@@ -220,13 +230,18 @@ class StudioService:
220
230
  )
221
231
  )
222
232
  self.resource_dsh_capabilities = (
223
- StudioDshCapabilityService.create_workspace_resource_default(
224
- self.workspace.root
225
- )
233
+ StudioDshCapabilityService.create_workspace_resource_default(self.workspace.root)
226
234
  )
227
235
  self._start_lock = asyncio.Lock()
236
+ self._profile_maintenance = False
228
237
  self._started = False
238
+ self._dsh_startup_task: asyncio.Task[None] | None = None
239
+ self._dsh_ready = False
229
240
  self._closed = False
241
+ self.configuration = WorkspaceConfiguration(
242
+ self.workspace, overrides=configuration_overrides
243
+ )
244
+ self._resource_authority_policy_override = resource_authority_policy
230
245
  self._apply_persisted_settings()
231
246
  self.avatar_assets = AgentAvatarAssetStore(self.workspace)
232
247
  self.conversation_attachments = ConversationAttachmentStore(self.workspace)
@@ -236,18 +251,16 @@ class StudioService:
236
251
  self.credentials = (
237
252
  credential_resolver
238
253
  or getattr(model_client, "credential_resolver", None)
239
- or CredentialResolver(self.workspace)
254
+ or CredentialResolver(self.workspace, configuration=self.configuration)
240
255
  )
241
256
  self.resource_connections = ResourceConnectionRepository(self.workspace, self.credentials)
242
257
  effective_resource_policy = (
243
258
  resource_authority_policy
244
259
  if resource_authority_policy is not None
245
- else resource_authority_policy_from_environment()
260
+ else resource_authority_policy_from_environment(self.configuration.environment())
246
261
  )
247
262
  self.resource_authority = (
248
- SignedKnowledgeResourceAuthority(
249
- self.resource_connections, effective_resource_policy
250
- )
263
+ SignedKnowledgeResourceAuthority(self.resource_connections, effective_resource_policy)
251
264
  if effective_resource_policy is not None
252
265
  else None
253
266
  )
@@ -341,16 +354,32 @@ class StudioService:
341
354
  resolve_adapter_provider=self._scheduler_adapter_provider,
342
355
  session_service=self.session_service,
343
356
  runtime_executor=self.runtime_executor,
357
+ state_dir=self.workspace.resolve(".agentkit/plugin-runtime/state"),
344
358
  )
345
359
  self.scheduler = StudioSchedulerService(
346
360
  self.workspace,
347
361
  runtime_registry=self.scheduler_runtimes,
348
362
  )
363
+ from ksadk.studio.execution_host import StudioExecutionHost
364
+ from ksadk.studio.teams_installation import create_teams_installation
365
+ from ksadk.studio.workspace_plugins import WorkspacePluginRegistry
366
+
367
+ self.workspace_plugins = WorkspacePluginRegistry()
368
+ self.execution_host = StudioExecutionHost(
369
+ self.scheduler_runtimes,
370
+ state_path=self.workspace.resolve(".agentkit/plugin-runtime/execution-host.sqlite"),
371
+ )
372
+ self.plugin_runs.execution_policy_resolver = self.execution_host
373
+ self.teams_installation = create_teams_installation(self)
374
+ from ksadk.studio.channel_connections import StudioChannelConnections
375
+
376
+ self.channel_connections = StudioChannelConnections(self)
349
377
  from ksadk.studio.scheduler_assistant import StudioScheduleAssistant
350
378
 
351
379
  self.run_service.schedule_assistant = StudioScheduleAssistant(self)
352
380
  self.mcp_runtime = MCPRuntimeAdapter(self.workspace, credentials=self.credentials)
353
381
  self._cloud_gateway_override = cloud_gateway
382
+ self._profile_maintenance = False
354
383
  self.cloud = CloudDeploymentService(
355
384
  self.workspace,
356
385
  gateway=cloud_gateway or self._configured_cloud_gateway(),
@@ -360,13 +389,37 @@ class StudioService:
360
389
  self.evaluation_storage = EvaluationStorage(self.workspace.resolve(".agentkit/evaluations"))
361
390
  self.authoring = StudioAuthoringCoordinator(self)
362
391
  self.codex_agents = CodexAgentService(self)
363
-
364
- async def start(self) -> None:
365
- """Bind ready managed DSH registrations before build or execution."""
366
-
392
+ self._current_codex_builds: dict[str, CodexBuildRecord] = {}
393
+ # agent_detail 进程内 TTL 缓存:bootstrap/list_models/list_sessions 等
394
+ # 转发接口在会话切换时反复调用 agent_detail,每次都重做 builds 全扫 +
395
+ # validator.validate(100-300ms)。5s TTL 把切换/刷新的重复读折叠掉;
396
+ # create/update/delete agent 时主动失效。
397
+ self._agent_detail_cache: dict[str, tuple[float, dict[str, Any]]] = {}
398
+ self._agent_detail_ttl = 5.0
399
+
400
+ async def start(self, *, wait_for_dsh: bool = True) -> None:
401
+ """Start local state and optionally wait for the managed DSH profile."""
402
+ # Desktop workspace switching must not queue behind an in-flight DSH
403
+ # discovery task. The service is already usable while that optional
404
+ # task finishes in the background; callers that explicitly request
405
+ # readiness still await the task below.
406
+ if self._started and not wait_for_dsh:
407
+ return
408
+ async with self._start_lock:
409
+ self._ensure_open()
410
+ if not self._started:
411
+ await self.scheduler_runtimes.start()
412
+ self._started = True
413
+ self._dsh_startup_task = asyncio.create_task(self._initialize_dsh())
414
+ self.channel_connections.start_background()
415
+ task = self._dsh_startup_task
416
+ if wait_for_dsh and task is not None:
417
+ await asyncio.shield(task)
418
+
419
+ async def _initialize_dsh(self) -> None:
367
420
  async with self._start_lock:
368
421
  self._ensure_open()
369
- if self._started:
422
+ if self._dsh_ready:
370
423
  return
371
424
  await self._bootstrap_official_dsh_defaults()
372
425
  manifests, factories, manager_refs = await self._provider_snapshot(refresh=False)
@@ -376,21 +429,32 @@ class StudioService:
376
429
  manager = self._dsh_provider_registration_manager
377
430
  if manager is not None and manager_refs is not None:
378
431
  manager.mark_bound(manager_refs)
379
- self._started = True
432
+ self._dsh_ready = True
380
433
 
381
434
  async def refresh_dsh_provider_registrations(self) -> None:
382
435
  """Rebind the exact current DSH Profile and release stale activations."""
383
436
 
384
437
  async with self._start_lock:
385
438
  self._ensure_open()
386
- safe_to_resume = False
439
+ await self.execution_host.set_admission_open(False)
440
+ await self.scheduler_runtimes.set_admission_open(False)
441
+ self._profile_maintenance = True
442
+ safe_to_resume = True
387
443
  try:
444
+ await self._require_profile_idle()
445
+ safe_to_resume = False
388
446
  await self.plugin_runs.suspend_admission()
389
447
  await self.reset_dsh_capability_state()
390
448
  await self._bind_dsh_provider_registrations_locked(refresh=True)
391
449
  await self._refresh_dsh_catalog_resource(required=False)
392
450
  safe_to_resume = True
393
451
  finally:
452
+ # 维护窗标志是纯同步状态,无条件复位:任何异常/取消路径都不得
453
+ # 把整个会话面永久留在 503。admission 的恢复语义不变(恢复失败
454
+ # 仍按契约保持关闭,由测试 test_failed_profile_rebind_* 保障)。
455
+ self._profile_maintenance = False
456
+ await self.execution_host.set_admission_open(safe_to_resume)
457
+ await self.scheduler_runtimes.set_admission_open(safe_to_resume)
394
458
  if safe_to_resume:
395
459
  await self.plugin_runs.resume_admission()
396
460
 
@@ -402,12 +466,21 @@ class StudioService:
402
466
 
403
467
  async with self._start_lock:
404
468
  self._ensure_open()
405
- safe_to_resume = False
469
+ await self.execution_host.set_admission_open(False)
470
+ await self.scheduler_runtimes.set_admission_open(False)
471
+ self._profile_maintenance = True
472
+ safe_to_resume = True
406
473
  try:
474
+ await self._require_profile_idle()
475
+ safe_to_resume = False
407
476
  await self.plugin_runs.suspend_admission()
408
477
  await self.reset_dsh_capability_state()
409
478
  try:
410
479
  result = await operation()
480
+ except asyncio.CancelledError:
481
+ # 取消中的任务做不了 recovery;维护窗标志在 finally 无条件
482
+ # 复位,避免一次取消把会话面永久 503。
483
+ raise
411
484
  except BaseException as mutation_error:
412
485
  if (
413
486
  isinstance(mutation_error, StudioError)
@@ -429,9 +502,45 @@ class StudioService:
429
502
  safe_to_resume = True
430
503
  return result
431
504
  finally:
505
+ # 维护窗标志是纯同步状态,无条件复位:任何异常/取消路径都不得
506
+ # 把整个会话面永久留在 503。admission 的恢复语义不变(恢复失败
507
+ # 仍按契约保持关闭,由测试 test_failed_profile_rebind_* 保障)。
508
+ self._profile_maintenance = False
509
+ await self.execution_host.set_admission_open(safe_to_resume)
510
+ await self.scheduler_runtimes.set_admission_open(safe_to_resume)
432
511
  if safe_to_resume:
433
512
  await self.plugin_runs.resume_admission()
434
513
 
514
+ async def _require_profile_idle(self) -> None:
515
+ pending = await self.scheduler_runtimes.unsettled_sessions()
516
+ active_operations = [
517
+ operation for operation in self.operations.list()
518
+ if operation.status in {OperationStatus.QUEUED, OperationStatus.RUNNING}
519
+ ]
520
+ if pending or active_operations:
521
+ raise StudioError("DSH_PROFILE_IN_USE",
522
+ "仍有执行或审批正在进行,请结束执行后再变更插件 Profile", status_code=409)
523
+
524
+ def _require_direct_session(self, session_id: str | None) -> None:
525
+ if self._profile_maintenance:
526
+ raise StudioError("DSH_PROFILE_MAINTENANCE", "插件宿主正在维护", status_code=503)
527
+ if session_id:
528
+ from ksadk.studio.execution_host import ExecutionHostError
529
+
530
+ try:
531
+ self.execution_host.require_unreserved_session(session_id)
532
+ except ExecutionHostError as error:
533
+ raise StudioError(error.code, str(error), status_code=error.status) from error
534
+
535
+ def _require_direct_run(self, run_id: str) -> None:
536
+ from ksadk.studio.execution_host import ExecutionHostError
537
+
538
+ self._require_direct_session(None)
539
+ try:
540
+ self.execution_host.require_unreserved_run(run_id)
541
+ except ExecutionHostError as error:
542
+ raise StudioError(error.code, str(error), status_code=error.status) from error
543
+
435
544
  async def _bind_dsh_provider_registrations_locked(self, *, refresh: bool) -> None:
436
545
  if self._dsh_provider_registration_manager is None:
437
546
  self._dsh_provider_registration_manager = (
@@ -448,6 +557,7 @@ class StudioService:
448
557
  if manager is not None and manager_refs is not None:
449
558
  manager.mark_bound(manager_refs)
450
559
  self._started = True
560
+ self._dsh_ready = True
451
561
 
452
562
  async def reset_dsh_capability_state(self) -> None:
453
563
  """Drop the current DSH capability/Core generation."""
@@ -531,6 +641,17 @@ class StudioService:
531
641
  logging.getLogger(__name__).info(
532
642
  "official Codex DSH provider bootstrap: %s", result
533
643
  )
644
+ try:
645
+ harness_result = await manager.bootstrap_official_harness_provider()
646
+ except Exception as error:
647
+ logging.getLogger(__name__).warning(
648
+ "official Harness DSH provider bootstrap skipped: %s", error
649
+ )
650
+ else:
651
+ if harness_result in {"installed", "already_enabled"}:
652
+ logging.getLogger(__name__).info(
653
+ "official Harness DSH provider bootstrap: %s", harness_result
654
+ )
534
655
  try:
535
656
  resource_result = await manager.bootstrap_official_resource_plugins()
536
657
  except Exception as error: # optional DSH must fail closed to legacy paths
@@ -768,6 +889,7 @@ class StudioService:
768
889
  sending provider-specific fields to every Runtime.
769
890
  """
770
891
 
892
+ self._require_direct_session(session_id)
771
893
  spec = self.resolve_run_spec(build_id)
772
894
  runtime_type = spec.launch_context.runtime_type.strip().lower()
773
895
  runtime_mode: Literal["native", "translated"] = (
@@ -784,7 +906,7 @@ class StudioService:
784
906
  ConversationCapability(name="attachment.image", mode="native"),
785
907
  # Bounded UTF-8/code attachments are made model-visible as
786
908
  # deterministic text parts by the Responses compatibility
787
- # adapter. Binary files remain unavailable in Phase 2.
909
+ # adapter. Binary files remain unavailable in Release.
788
910
  ConversationCapability(name="attachment.file", mode="translated"),
789
911
  ConversationCapability(name="reasoning.effort", mode="native"),
790
912
  ConversationCapability(name="goal", mode="native"),
@@ -826,14 +948,24 @@ class StudioService:
826
948
  await self.start()
827
949
  if self.is_codex_agent(agent_id):
828
950
  self.codex_agent_detail(agent_id)
951
+ manifest_snapshot = self.codex_manifests.load(agent_id)
952
+ cached = self._current_codex_builds.get(agent_id)
953
+ if cached is not None and cached.manifest_sha256 == manifest_snapshot.manifest_sha256:
954
+ try:
955
+ return self.codex_builds.get(cached.id)
956
+ except StudioError:
957
+ self._current_codex_builds.pop(agent_id, None)
829
958
  builds = [
830
959
  record
831
960
  for record in self.codex_builds.list()
832
961
  if record.agent_name == agent_id and self.codex_builder.is_current(record)
833
962
  ]
834
963
  if builds:
964
+ self._current_codex_builds[agent_id] = builds[0]
835
965
  return builds[0]
836
- return await asyncio.to_thread(self.codex_builder.build, agent_id)
966
+ built = await asyncio.to_thread(self.codex_builder.build, agent_id)
967
+ self._current_codex_builds[agent_id] = built
968
+ return built
837
969
  draft = self.drafts.get(agent_id)
838
970
  composition_required = self.plugin_compositions.required_for(draft)
839
971
  resources_required = resource_build_required(draft)
@@ -853,6 +985,8 @@ class StudioService:
853
985
  "当前 Agent 需要插件组合,但无法生成 Composition",
854
986
  status_code=409,
855
987
  )
988
+ if not self._build_has_composition(record, composition=composition):
989
+ continue
856
990
  self.plugin_compositions.bind_build(
857
991
  composition,
858
992
  agent_id=draft.metadata.id,
@@ -917,7 +1051,7 @@ class StudioService:
917
1051
  )
918
1052
  return record
919
1053
 
920
- def _build_has_composition(self, record: Any) -> bool:
1054
+ def _build_has_composition(self, record: Any, *, composition: Any = None) -> bool:
921
1055
  """Reject stale pre-Phase-2 builds for a composed runtime.
922
1056
 
923
1057
  This check is intentionally scoped to Harness/plugin runtimes. Legacy
@@ -936,6 +1070,13 @@ class StudioService:
936
1070
  and manifest.get("compositionProfileDigest")
937
1071
  and "composition-profile.json" in names
938
1072
  and "plugin-lock.json" in names
1073
+ and (
1074
+ composition is None
1075
+ or (
1076
+ manifest.get("compositionProfileDigest") == composition.profile_digest
1077
+ and manifest.get("pluginLockDigest") == composition.plugin_lock_digest
1078
+ )
1079
+ )
939
1080
  )
940
1081
  except (KeyError, OSError, UnicodeError, ValueError, zipfile.BadZipFile):
941
1082
  return False
@@ -1140,12 +1281,15 @@ class StudioService:
1140
1281
  name: str | None = None,
1141
1282
  labels: dict[str, str] | None = None,
1142
1283
  ) -> AgentDraft:
1143
- return self.codex_agents.create(
1284
+ created = self.codex_agents.create(
1144
1285
  agent_id=agent_id,
1145
1286
  spec=spec,
1146
1287
  name=name,
1147
1288
  labels=labels,
1148
1289
  )
1290
+ self._current_codex_builds.pop(agent_id, None)
1291
+ self.invalidate_agent_detail(agent_id)
1292
+ return created
1149
1293
 
1150
1294
  def update_codex_agent(
1151
1295
  self,
@@ -1155,15 +1299,20 @@ class StudioService:
1155
1299
  expected_revision: int,
1156
1300
  name: str | None = None,
1157
1301
  ) -> AgentDraft:
1158
- return self.codex_agents.update(
1302
+ updated = self.codex_agents.update(
1159
1303
  agent_id,
1160
1304
  spec,
1161
1305
  expected_revision=expected_revision,
1162
1306
  name=name,
1163
1307
  )
1308
+ self._current_codex_builds.pop(agent_id, None)
1309
+ self.invalidate_agent_detail(agent_id)
1310
+ return updated
1164
1311
 
1165
1312
  def delete_codex_agent(self, agent_id: str, *, purge: bool = False) -> None:
1166
1313
  self.codex_agents.delete(agent_id, purge=purge)
1314
+ self._current_codex_builds.pop(agent_id, None)
1315
+ self.invalidate_agent_detail(agent_id)
1167
1316
 
1168
1317
  def codex_agent_detail(self, agent_id: str | None = None) -> dict:
1169
1318
  return self.codex_agents.detail(agent_id)
@@ -1199,6 +1348,7 @@ class StudioService:
1199
1348
  idempotency_key: str,
1200
1349
  on_event: Callable[[RunEvent], None] | None = None,
1201
1350
  ) -> Operation:
1351
+ self._require_direct_session(session_id)
1202
1352
  return self.codex_agents.submit_run(
1203
1353
  build_id,
1204
1354
  user_input,
@@ -1217,17 +1367,23 @@ class StudioService:
1217
1367
  async def delete_session(self, session_id: str) -> None:
1218
1368
  from ksadk.studio.errors import not_found
1219
1369
 
1370
+ self._require_direct_session(session_id)
1220
1371
  runs = self.event_store.list_runs(session_id=session_id)
1221
1372
  session = await self.session_service.get_session_metadata(session_id)
1222
1373
  if not runs and session is None:
1223
1374
  raise not_found("session", session_id)
1224
- if any(run.status == RunStatus.RUNNING for run in runs):
1225
- raise StudioError(
1226
- "SESSION_RUN_ACTIVE",
1227
- "会话仍在运行,请先停止运行后再删除",
1228
- status_code=409,
1229
- details={"sessionId": session_id},
1230
- )
1375
+ # 磁盘停在 RUNNING 的 run 只有仍在本进程内执行时才阻止删除;
1376
+ # 崩溃/重启遗留的僵尸 RUNNING 一律回收为 canceled 后放行删除。
1377
+ for run in runs:
1378
+ if run.status == RunStatus.RUNNING:
1379
+ if self.run_service.is_run_executing(run.id):
1380
+ raise StudioError(
1381
+ "SESSION_RUN_ACTIVE",
1382
+ "会话仍在运行,请先停止运行后再删除",
1383
+ status_code=409,
1384
+ details={"sessionId": session_id},
1385
+ )
1386
+ await self.run_service.reap_stale_running_run(run.id)
1231
1387
  await self.plugin_runs.close_session(session_id)
1232
1388
  await self.session_service.delete_session(session_id)
1233
1389
  self.event_store.delete_session(session_id)
@@ -1238,6 +1394,8 @@ class StudioService:
1238
1394
  async with self._start_lock:
1239
1395
  if self._closed:
1240
1396
  return
1397
+ if self._dsh_startup_task is not None and not self._dsh_startup_task.done():
1398
+ self._dsh_startup_task.cancel()
1241
1399
  self._closed = True
1242
1400
  cleanup = asyncio.create_task(self._close_owned_plugin_services())
1243
1401
  interrupted = False
@@ -1251,8 +1409,20 @@ class StudioService:
1251
1409
  raise asyncio.CancelledError
1252
1410
 
1253
1411
  async def _close_owned_plugin_services(self) -> None:
1412
+ from ksadk.studio.provider_recovery import detach_recovered_runs
1413
+
1414
+ await detach_recovered_runs(self.run_service)
1254
1415
  first_error: BaseException | None = None
1255
- owned = [self.plugin_runs.aclose, self.dsh_capabilities.aclose]
1416
+ owned = [
1417
+ self.channel_connections.close,
1418
+ self.workspace_plugins.close, self.plugin_runs.aclose, self.dsh_capabilities.aclose,
1419
+ self.scheduler_runtimes.close, self.execution_host.close,
1420
+ ]
1421
+ # The model client owns a keep-alive connection pool shared by all
1422
+ # turns. Close it with the Studio service so shutdown remains clean.
1423
+ close_model_client = getattr(self.model_client, "aclose", None)
1424
+ if close_model_client is not None:
1425
+ owned.append(close_model_client)
1256
1426
  if self.resource_dsh_capabilities is not self.dsh_capabilities:
1257
1427
  owned.append(self.resource_dsh_capabilities.aclose)
1258
1428
  if self._dsh_provider_registration_manager is not None:
@@ -1277,6 +1447,7 @@ class StudioService:
1277
1447
  )
1278
1448
 
1279
1449
  async def _require_runtime_session(self, session_id: str) -> None:
1450
+ self._require_direct_session(session_id)
1280
1451
  if await self.session_service.get_session_metadata(session_id) is None:
1281
1452
  raise StudioError(
1282
1453
  "SESSION_NOT_FOUND",
@@ -1799,17 +1970,29 @@ class StudioService:
1799
1970
  return values[:limit]
1800
1971
 
1801
1972
  def agent_detail(self, agent_id: str) -> dict:
1973
+ cached = self._agent_detail_cache.get(agent_id)
1974
+ if cached and cached[0] > time.monotonic():
1975
+ return cached[1]
1802
1976
  if self.is_codex_agent(agent_id):
1803
1977
  detail = self.codex_agent_detail(agent_id)
1804
1978
  detail["soulProjection"] = self._soul_projection(detail["draft"])
1805
- return detail
1806
- draft = self.drafts.get(agent_id)
1807
- return {
1808
- "draft": draft,
1809
- "builds": self.builds.list_for_agent(agent_id)[:10],
1810
- "validation": self.validator.validate(draft),
1811
- "soulProjection": self._soul_projection(draft),
1812
- }
1979
+ else:
1980
+ draft = self.drafts.get(agent_id)
1981
+ detail = {
1982
+ "draft": draft,
1983
+ "builds": self.builds.list_for_agent(agent_id)[:10],
1984
+ "validation": self.validator.validate(draft),
1985
+ "soulProjection": self._soul_projection(draft),
1986
+ }
1987
+ self._agent_detail_cache[agent_id] = (time.monotonic() + self._agent_detail_ttl, detail)
1988
+ return detail
1989
+
1990
+ def invalidate_agent_detail(self, agent_id: str | None = None) -> None:
1991
+ """Invalidate cached agent_detail after create/update/delete/build."""
1992
+ if agent_id is None:
1993
+ self._agent_detail_cache.clear()
1994
+ else:
1995
+ self._agent_detail_cache.pop(agent_id, None)
1813
1996
 
1814
1997
  @staticmethod
1815
1998
  def _soul_projection(draft: AgentDraft) -> dict[str, object]:
@@ -1850,6 +2033,8 @@ class StudioService:
1850
2033
  )
1851
2034
  selected = runtime or resolved_spec.runtime
1852
2035
  resolved_spec.runtime = selected
2036
+ if selected is not None and selected.type == "harness" and spec is None:
2037
+ resolved_spec = with_harness_provider_permissions(resolved_spec)
1853
2038
  if selected is not None and selected.type == "codex":
1854
2039
  return cast(
1855
2040
  AgentDraft,
@@ -1860,7 +2045,7 @@ class StudioService:
1860
2045
  labels=labels,
1861
2046
  ),
1862
2047
  )
1863
- return cast(
2048
+ created = cast(
1864
2049
  AgentDraft,
1865
2050
  self.create_agent(
1866
2051
  agent_id=agent_id,
@@ -1871,6 +2056,8 @@ class StudioService:
1871
2056
  labels=labels,
1872
2057
  ),
1873
2058
  )
2059
+ self.invalidate_agent_detail(agent_id)
2060
+ return created
1874
2061
 
1875
2062
  def update_studio_agent(
1876
2063
  self,
@@ -1942,17 +2129,21 @@ class StudioService:
1942
2129
  appearance,
1943
2130
  expected_revision=expected_revision,
1944
2131
  )
1945
- return self.drafts.update_appearance(
2132
+ updated = self.drafts.update_appearance(
1946
2133
  agent_id,
1947
2134
  appearance,
1948
2135
  expected_revision=expected_revision,
1949
2136
  )
2137
+ self.invalidate_agent_detail(agent_id)
2138
+ return updated
1950
2139
 
1951
2140
  def delete_studio_agent(self, agent_id: str, *, purge: bool = False) -> None:
1952
2141
  if self.is_codex_agent(agent_id):
1953
2142
  self.delete_codex_agent(agent_id, purge=purge)
2143
+ self.invalidate_agent_detail(agent_id)
1954
2144
  return
1955
2145
  delete_framework_agent(self, agent_id, purge=purge)
2146
+ self.invalidate_agent_detail(agent_id)
1956
2147
 
1957
2148
  def validate_studio_agent(
1958
2149
  self,
@@ -1979,11 +2170,13 @@ class StudioService:
1979
2170
  # Check workspace ownership, but never project the mutable draft as runtime state.
1980
2171
  await asyncio.to_thread(self.agent_detail, agent_id)
1981
2172
  status = await self.dsh_capabilities.resource_runtime_status(
1982
- agent_id=agent_id, activation_id=activation_id,
2173
+ agent_id=agent_id,
2174
+ activation_id=activation_id,
1983
2175
  )
1984
2176
  if status is None:
1985
2177
  raise StudioError(
1986
- "RESOURCE_ACTIVATION_NOT_FOUND", "未找到此 Agent 的资源运行实例",
2178
+ "RESOURCE_ACTIVATION_NOT_FOUND",
2179
+ "未找到此 Agent 的资源运行实例",
1987
2180
  status_code=404,
1988
2181
  )
1989
2182
  return status
@@ -1995,10 +2188,14 @@ class StudioService:
1995
2188
  draft = self.agent_detail(agent_id)["draft"]
1996
2189
  if draft.metadata.revision != expected_revision:
1997
2190
  raise StudioError(
1998
- "AGENT_REVISION_CONFLICT", "资源校验版本与当前 Agent 不一致", status_code=409,
2191
+ "AGENT_REVISION_CONFLICT",
2192
+ "资源校验版本与当前 Agent 不一致",
2193
+ status_code=409,
1999
2194
  )
2000
2195
  diagnostics = resource_binding_diagnostics(
2001
- draft.spec.bindings.plugins, draft.spec.memory, self.resource_connections,
2196
+ draft.spec.bindings.plugins,
2197
+ draft.spec.memory,
2198
+ self.resource_connections,
2002
2199
  )
2003
2200
  configs = [
2004
2201
  (index, config)
@@ -2029,8 +2226,7 @@ class StudioService:
2029
2226
  severity=DiagnosticSeverity.ERROR,
2030
2227
  code=error.code,
2031
2228
  message=error.message,
2032
- field=error.field
2033
- or f"spec.bindings.plugins[{index}].config.binding",
2229
+ field=error.field or f"spec.bindings.plugins[{index}].config.binding",
2034
2230
  )
2035
2231
  )
2036
2232
  current = self.agent_detail(agent_id)["draft"]
@@ -2114,6 +2310,7 @@ class StudioService:
2114
2310
  runtime_input: Any = None,
2115
2311
  on_event: Callable[[RunEvent], None] | None = None,
2116
2312
  ) -> Operation:
2313
+ self._require_direct_session(session_id)
2117
2314
  try:
2118
2315
  self.codex_builds.get(build_id)
2119
2316
  except Exception as exc:
@@ -2230,12 +2427,14 @@ class StudioService:
2230
2427
  preview,
2231
2428
  catalog=self.catalog,
2232
2429
  )
2233
- return self.drafts.update(
2430
+ updated = self.drafts.update(
2234
2431
  agent_id,
2235
2432
  spec,
2236
2433
  expected_revision=expected_revision,
2237
2434
  name=name,
2238
2435
  )
2436
+ self.invalidate_agent_detail(agent_id)
2437
+ return updated
2239
2438
 
2240
2439
  def update_agent_bindings(
2241
2440
  self,
@@ -2424,6 +2623,7 @@ class StudioService:
2424
2623
  idempotency_key: str,
2425
2624
  on_event: Callable[[RunEvent], None] | None = None,
2426
2625
  ) -> Operation:
2626
+ self._require_direct_session(session_id)
2427
2627
  async def runner(_operation_id: str):
2428
2628
  return await self.run_build(
2429
2629
  build_id,
@@ -2464,6 +2664,7 @@ class StudioService:
2464
2664
  """Execute any immutable Studio Build through the canonical executor."""
2465
2665
 
2466
2666
  await self.start()
2667
+ self._require_direct_session(session_id)
2467
2668
  spec = self.resolve_run_spec(
2468
2669
  build_id,
2469
2670
  model=model,
@@ -3081,41 +3282,68 @@ class StudioService:
3081
3282
  "cloudCredential": opaque(f"{region}\0{access_key}"),
3082
3283
  }
3083
3284
 
3285
+ @staticmethod
3286
+ def frontend_assets() -> dict[str, Any]:
3287
+ import re
3288
+
3289
+ entry = Path(__file__).with_name("static") / "index.html"
3290
+ if not entry.is_file():
3291
+ return {"entryAssets": []}
3292
+ assets = re.findall(
3293
+ r'(?:src|href)="(/static/assets/[^"<>]+\.(?:js|css))"',
3294
+ entry.read_text(encoding="utf-8"),
3295
+ )
3296
+ return {"entryAssets": [Path(asset).name for asset in assets]}
3297
+
3084
3298
  def get_settings(self) -> dict[str, Any]:
3085
- path = self.workspace.resolve(".agentkit/settings.yaml")
3086
- data: dict[str, Any] = {}
3087
- if path.is_file():
3088
- try:
3089
- data = load_yaml_file(path) or {}
3090
- except Exception:
3091
- data = {}
3299
+ data = self.configuration.settings()
3300
+ environment = self.configuration.environment()
3092
3301
  defaults = {
3093
- "sandbox": os.environ.get("KSADK_CODEX_SANDBOX", "workspace-write-auto"),
3302
+ "sandbox": environment.get("KSADK_CODEX_SANDBOX", "workspace-write-auto"),
3094
3303
  "buildAfterCreate": True,
3095
3304
  "codexProxy": current_proxy_mode(),
3096
- "cloudRegion": os.environ.get(
3097
- "AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "cn-beijing-6")
3305
+ "cloudRegion": environment.get(
3306
+ "AGENTENGINE_REGION", environment.get("KSYUN_REGION", "cn-beijing-6")
3098
3307
  ),
3099
- "cloudBucket": os.environ.get("KS3_BUCKET", ""),
3100
- "cloudAccountId": (os.environ.get("KSYUN_ACCOUNT_ID", "").strip()),
3308
+ "cloudServerUrl": environment.get("AGENTENGINE_SERVER_URL", ""),
3309
+ "cloudBucket": environment.get("KS3_BUCKET", ""),
3310
+ "cloudAccountId": (environment.get("KSYUN_ACCOUNT_ID", "").strip()),
3101
3311
  # AK/SK 不回显(避免本地 UI 回传 secret);只暴露配置状态。
3102
3312
  # 已配置 = 启动环境或已持久化 settings 里 AK+SK 齐全。
3103
3313
  "cloudAccountConfigured": bool(
3104
- (os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
3314
+ (
3315
+ environment.get("KSYUN_ACCESS_KEY") or environment.get("KS3_ACCESS_KEY", "")
3316
+ ).strip()
3105
3317
  and (
3106
- os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
3318
+ environment.get("KSYUN_SECRET_KEY") or environment.get("KS3_SECRET_KEY", "")
3107
3319
  ).strip()
3108
3320
  ),
3109
3321
  "cloudSignedAccountConfigured": bool(
3110
- (os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
3322
+ (
3323
+ environment.get("KSYUN_ACCESS_KEY") or environment.get("KS3_ACCESS_KEY", "")
3324
+ ).strip()
3111
3325
  and (
3112
- os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
3326
+ environment.get("KSYUN_SECRET_KEY") or environment.get("KS3_SECRET_KEY", "")
3113
3327
  ).strip()
3114
3328
  ),
3115
- "traceContent": os.environ.get("KSADK_STUDIO_TRACE_CONTENT", "1") != "0",
3329
+ "traceContent": environment.get("KSADK_STUDIO_TRACE_CONTENT", "1") != "0",
3116
3330
  }
3117
3331
  defaults.update({k: v for k, v in data.items() if k in defaults and v is not None})
3118
- defaults["codexProxy"] = normalize_proxy_mode(defaults.get("codexProxy"))
3332
+ for key, name in SETTINGS_ENV.items():
3333
+ if key in defaults:
3334
+ value, _source = self.configuration.resolve(name)
3335
+ if value is not None:
3336
+ defaults[key] = value
3337
+ defaults["configurationSources"] = {
3338
+ key: self.configuration.resolve(name)[1] for key, name in SETTINGS_ENV.items()
3339
+ }
3340
+ defaults["platformResourceMissingFields"] = [
3341
+ key
3342
+ for key in ("cloudAccessKey", "cloudSecretKey", "cloudServerUrl")
3343
+ if not self.configuration.resolve(SETTINGS_ENV[key])[0]
3344
+ ]
3345
+ defaults["platformResourcesConfigured"] = self.resource_authority is not None
3346
+ defaults["codexProxy"] = normalize_proxy_mode(environment.get("KSADK_CODEX_USE_PROXY"))
3119
3347
  return defaults
3120
3348
 
3121
3349
  def update_settings(self, payload: dict[str, Any]) -> dict[str, Any]:
@@ -3125,6 +3353,7 @@ class StudioService:
3125
3353
  "codexProxy",
3126
3354
  "cloudRegion",
3127
3355
  "cloudBucket",
3356
+ "cloudServerUrl",
3128
3357
  "traceContent",
3129
3358
  # 云账号:AK/SK 留空 = 不修改(保留已存值);AccountID 可单独更新。
3130
3359
  "cloudAccessKey",
@@ -3153,35 +3382,102 @@ class StudioService:
3153
3382
  raise StudioError("SETTINGS_INVALID", "sandbox 取值非法", status_code=422)
3154
3383
  if "codexProxy" in data and data["codexProxy"] not in {"auto", "forced", "direct"}:
3155
3384
  raise StudioError("SETTINGS_INVALID", "codexProxy 取值非法", status_code=422)
3156
- path = self.workspace.resolve(".agentkit/settings.yaml")
3157
- self.workspace.atomic_write_yaml(path, data)
3158
- # env 桥接用落盘后的全量数据:局部更新(只改 AccountID)时,
3159
- # 已持久化的 AK/SK 也要继续桥接,否则签名凭证丢失。
3385
+ for key in (
3386
+ "cloudAccessKey",
3387
+ "cloudSecretKey",
3388
+ "cloudAccountId",
3389
+ "cloudRegion",
3390
+ "cloudBucket",
3391
+ "cloudServerUrl",
3392
+ ):
3393
+ if key in data:
3394
+ if (
3395
+ not isinstance(data[key], str)
3396
+ or len(data[key]) > 2048
3397
+ or any(ord(c) < 32 for c in data[key])
3398
+ ):
3399
+ raise StudioError(
3400
+ "SETTINGS_INVALID", "配置值格式无效", status_code=422, field=key
3401
+ )
3402
+ data[key] = data[key].strip()
3403
+ if data.get("cloudServerUrl"):
3404
+ from ksadk.studio.resource_authority import _canonical_endpoint
3405
+
3406
+ try:
3407
+ data["cloudServerUrl"] = _canonical_endpoint(
3408
+ data["cloudServerUrl"],
3409
+ allow_loopback_http=False,
3410
+ allow_ksyun_internal_http=True,
3411
+ )
3412
+ except ValueError as error:
3413
+ raise StudioError(
3414
+ "SETTINGS_INVALID",
3415
+ "控制面地址必须是有效的 HTTPS 服务地址",
3416
+ status_code=422,
3417
+ field="cloudServerUrl",
3418
+ ) from error
3419
+ if (
3420
+ "cloudAccessKey" in data
3421
+ and data["cloudAccessKey"] != self.configuration.resolve("KSYUN_ACCESS_KEY")[0]
3422
+ ):
3423
+ if not data.get("cloudSecretKey"):
3424
+ raise StudioError(
3425
+ "SETTINGS_INVALID",
3426
+ "切换 Access Key 时请同时填写对应的 Secret Key",
3427
+ status_code=422,
3428
+ field="cloudSecretKey",
3429
+ )
3430
+ data.setdefault("cloudAccountId", "")
3431
+ candidate_environment = self.configuration.environment()
3432
+ for key, name in SETTINGS_ENV.items():
3433
+ if key in data and name not in self.configuration.overrides:
3434
+ candidate_environment[name] = str(data[key])
3160
3435
  try:
3161
- persisted = load_yaml_file(path) or {}
3162
- except Exception:
3163
- persisted = data
3164
- self._apply_settings_to_env(persisted if isinstance(persisted, dict) else data)
3436
+ candidate_policy = (
3437
+ self._resource_authority_policy_override
3438
+ or resource_authority_policy_from_environment(candidate_environment)
3439
+ )
3440
+ except ValueError as error:
3441
+ raise StudioError(
3442
+ "SETTINGS_INVALID", "云端连接配置无效,请检查控制面地址和区域", status_code=422
3443
+ ) from error
3444
+ self.plugin_runs.check_configuration_mutable()
3445
+ self.configuration.update_settings(data)
3446
+ self._apply_persisted_settings()
3447
+ self.resource_authority = (
3448
+ SignedKnowledgeResourceAuthority(self.resource_connections, candidate_policy)
3449
+ if candidate_policy is not None
3450
+ else None
3451
+ )
3452
+ self.plugin_runs.replace_resource_authority(self.resource_authority)
3165
3453
  if self._cloud_gateway_override is None:
3166
3454
  self.cloud.gateway = self._configured_cloud_gateway()
3167
3455
  return self.get_settings()
3168
3456
 
3169
- def _apply_persisted_settings(self) -> None:
3170
- """启动时把 settings.yaml 回填到进程环境。
3457
+ async def apply_settings(self, payload: dict[str, Any]) -> dict[str, Any]:
3458
+ """Drain old credentials/leases before making a new account visible."""
3459
+ async with self._start_lock:
3460
+ if self.run_service.has_active_runs():
3461
+ raise StudioError(
3462
+ "SETTINGS_RUNTIME_BUSY", "请等待当前运行结束后再保存设置", status_code=409
3463
+ )
3464
+ try:
3465
+ await self.plugin_runs.suspend_admission()
3466
+ return self.update_settings(payload)
3467
+ finally:
3468
+ await self.plugin_runs.resume_admission()
3171
3469
 
3172
- update_settings 只在 PUT 时桥接 env;重启后 env 丢失,运行解析
3173
- (如 _resolve_sandbox 读 KSADK_CODEX_SANDBOX)会回落默认,表现为
3174
- 「设置页显示 workspace-write-auto,实际运行 read-only」。
3175
- """
3176
- path = self.workspace.resolve(".agentkit/settings.yaml")
3177
- if not path.is_file():
3178
- return
3179
- try:
3180
- data = load_yaml_file(path) or {}
3181
- except Exception:
3182
- return
3183
- if isinstance(data, dict):
3184
- self._apply_settings_to_env(data)
3470
+ def _apply_persisted_settings(self) -> None:
3471
+ data = self.configuration.settings()
3472
+ environment = self.configuration.environment()
3473
+ self._apply_settings_to_env(data)
3474
+ for name in (
3475
+ *SETTINGS_ENV.values(),
3476
+ *self.configuration.dotenv,
3477
+ *self.configuration.overrides,
3478
+ ):
3479
+ if name in environment:
3480
+ os.environ[name] = environment[name]
3185
3481
 
3186
3482
  @staticmethod
3187
3483
  def _apply_settings_to_env(data: dict[str, Any]) -> None:
@@ -3208,34 +3504,33 @@ class StudioService:
3208
3504
  if data.get("cloudAccountId"):
3209
3505
  os.environ["KSYUN_ACCOUNT_ID"] = str(data["cloudAccountId"])
3210
3506
 
3211
- @staticmethod
3212
- def _configured_cloud_gateway() -> CloudDeploymentGateway:
3507
+ def _configured_cloud_gateway(self) -> CloudDeploymentGateway:
3213
3508
  """Compose the existing signed Code deployment path from process-only credentials."""
3214
3509
 
3510
+ environment = self.configuration.environment()
3215
3511
  access_key = (
3216
- os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")
3512
+ environment.get("KSYUN_ACCESS_KEY") or environment.get("KS3_ACCESS_KEY", "")
3217
3513
  ).strip()
3218
3514
  secret_key = (
3219
- os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
3515
+ environment.get("KSYUN_SECRET_KEY") or environment.get("KS3_SECRET_KEY", "")
3220
3516
  ).strip()
3221
- configured_region = os.environ.get(
3222
- "AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "")
3517
+ configured_region = environment.get(
3518
+ "AGENTENGINE_REGION", environment.get("KSYUN_REGION", "")
3223
3519
  ).strip()
3224
- environment_region = os.environ.get("KSYUN_REGION", "").strip()
3520
+ environment_region = environment.get("KSYUN_REGION", "").strip()
3225
3521
  logical_region = (
3226
- "pre-online"
3227
- if environment_region.lower() == "pre-online"
3228
- else configured_region
3522
+ "pre-online" if environment_region.lower() == "pre-online" else configured_region
3229
3523
  )
3230
3524
  if not all((access_key, secret_key, logical_region)):
3231
3525
  return UnavailableCloudGateway()
3232
3526
  control_client = AgentEngineClient(
3527
+ base_url=environment.get("AGENTENGINE_SERVER_URL") or None,
3233
3528
  region=logical_region,
3234
3529
  access_key=access_key,
3235
3530
  secret_key=secret_key,
3236
3531
  )
3237
3532
  is_preonline = logical_region.lower() == "pre-online"
3238
- stream_base_url = os.environ.get("AGENTENGINE_STREAM_SERVER_URL", "").strip()
3533
+ stream_base_url = environment.get("AGENTENGINE_STREAM_SERVER_URL", "").strip()
3239
3534
  if not stream_base_url and is_preonline:
3240
3535
  # The pre-online KOP response path currently buffers SSE until
3241
3536
  # EOF, and KOP may not yet publish newly deployed native Action
@@ -3257,7 +3552,7 @@ class StudioService:
3257
3552
  client=control_client,
3258
3553
  stream_client=stream_client,
3259
3554
  managed_runtime_client=stream_client if is_preonline else None,
3260
- bucket=os.environ.get("KS3_BUCKET", "").strip() or None,
3555
+ bucket=environment.get("KS3_BUCKET", "").strip() or None,
3261
3556
  ks3_credentials={
3262
3557
  "access_key": access_key,
3263
3558
  "secret_key": secret_key,