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
@@ -0,0 +1,931 @@
1
+ """ManagedLangGraphEngine —— 默认执行引擎(plan §7 / Kernel)。
2
+
3
+ 实现 §7.1 默认 Agent Loop 的 Kernel 子集:prepare_context -> reason ->
4
+ tool_calls -> final,reason 自环。LangGraph 类型不越出本模块
5
+ (tests/architecture/test_harness_contract.py 守卫)。
6
+
7
+ Kernel 能力范围(诚实声明):
8
+ - Cancel:支持(终止语义,不伪装 Pause);
9
+ - Interrupt/Resume:支持(approval 通道,resume 携带 payload 重放);
10
+ - Checkpoint:LangGraph Checkpointer 注入(内存/SQLite),thread_id 走
11
+ 租户复合编码(plan §6.2.2);
12
+ - Context 压缩:Release 交付,本引擎留 policy 读取口。
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import asyncio
18
+ import time
19
+ import uuid
20
+ from typing import Any, AsyncIterator, Callable
21
+
22
+ from langgraph.checkpoint.base import BaseCheckpointSaver
23
+ from langgraph.errors import GraphInterrupt
24
+ from langgraph.types import Command
25
+
26
+ from ksadk.harness.engine import budgets
27
+ from ksadk.harness.engine.base import (
28
+ CompiledHarness,
29
+ EngineCapability,
30
+ EngineCapabilityMatrix,
31
+ ExecutionEngineError,
32
+ )
33
+ from ksadk.harness.engine.context_pipeline import EngineContextPipeline
34
+ from ksadk.harness.engine.mcp_disclosure import (
35
+ McpDisclosureBridge,
36
+ McpDisclosureCursors,
37
+ )
38
+ from ksadk.harness.engine.policy_runtime import configure_run, revalidate_policy
39
+ from ksadk.harness.engine.run_types import _EngineRun, _GraphState
40
+ from ksadk.harness.engine.skill_disclosure import SkillDisclosureBridge
41
+ from ksadk.harness.engine.thread_ids import encode_thread_id
42
+ from ksadk.harness.events import EventType, RuntimeEvent
43
+ from ksadk.harness.execution_policy import execution_policy_scope
44
+ from ksadk.harness.mcp_runtime import McpCapabilityRuntime
45
+ from ksadk.harness.prompt_cache import PromptCacheTracker
46
+ from ksadk.harness.reasoner import HarnessReasoner, LiteLLMHarnessReasoner
47
+ from ksadk.harness.run_control import (
48
+ RunController,
49
+ RunControlStop,
50
+ run_control_spec_from_config,
51
+ )
52
+ from ksadk.harness.skill_runtime import SkillRuntime
53
+ from ksadk.harness.spec import HarnessSpec
54
+ from ksadk.harness.state import HarnessState, Message, MessageRole, RunStatus
55
+ from ksadk.harness.strategies import ExecutionStrategyRegistry
56
+ from ksadk.runtime import (
57
+ CancelResult,
58
+ PauseResult,
59
+ ResumePayload,
60
+ ResumeTarget,
61
+ RunHandle,
62
+ StartRequest,
63
+ )
64
+
65
+ _MAX_REASONING_TURNS = 8
66
+
67
+
68
+ class ManagedLangGraphEngine:
69
+ """默认执行引擎:Revision 编译产物在 LangGraph 上运行。"""
70
+
71
+ def __init__(
72
+ self,
73
+ *,
74
+ reasoner: HarnessReasoner | None = None,
75
+ checkpointer: BaseCheckpointSaver | None = None,
76
+ tenant_id: str = "default",
77
+ tools: dict[str, Any] | None = None,
78
+ approval_required: set[str] | None = None,
79
+ context_engine: Any | None = None,
80
+ strategy_registry: ExecutionStrategyRegistry | None = None,
81
+ capability_runtime: Any | None = None,
82
+ sub_agents: dict[str, Any] | None = None,
83
+ memory_runtime: Any | None = None,
84
+ skill_runtime: SkillRuntime | None = None,
85
+ mcp_runtime: McpCapabilityRuntime | None = None,
86
+ artifact_store: Any | None = None,
87
+ mcp_offload_policy: Any | None = None,
88
+ delegation_runtime: Any | None = None,
89
+ event_sink: Callable[[str, str, RuntimeEvent], None] | None = None,
90
+ max_reasoning_turns: int = _MAX_REASONING_TURNS,
91
+ ) -> None:
92
+ self._reasoner = reasoner or LiteLLMHarnessReasoner()
93
+ self._checkpointer = checkpointer
94
+ # 集成项 4:Strategy Registry 真正参与 compile()——拓扑来自注册表。
95
+ self._strategy_registry = strategy_registry or ExecutionStrategyRegistry()
96
+ self._tenant_id = tenant_id
97
+ self._tools = tools or {}
98
+ self._approval_required = approval_required or set()
99
+ self._context_engine = context_engine
100
+ # 收口 2:统一 CapabilityRuntime(Policy 决策 + Receipt 幂等)。
101
+ # 为 None 时 tool_calls 节点回退静态 approval_required 集合。
102
+ self._capability_runtime = capability_runtime
103
+ # 收口 6:子 Agent(名称 → SubAgentSpec);多 Agent 作为可选能力。
104
+ self._sub_agents = sub_agents or {}
105
+ if max_reasoning_turns < 1:
106
+ raise ValueError("max_reasoning_turns 必须为正整数")
107
+ self._max_reasoning_turns = max_reasoning_turns
108
+ # 长任务方案 §6.4:压缩前受控 Memory Flush 用的 Memory Runtime(可选)。
109
+ self._memory_runtime = memory_runtime
110
+ self._prompt_cache_tracker = PromptCacheTracker()
111
+ # SkillRuntime 只消费已绑定、已校验的 Skill 内容;L0 摘要常驻动态
112
+ # Context,L1/L2/L3 由默认 Agent Loop 的受限工具渐进披露。
113
+ self._skill_runtime = skill_runtime
114
+ self._skill_disclosure = SkillDisclosureBridge(skill_runtime)
115
+ # P0 MCP Deferred Tool Loading:McpCapabilityRuntime 复用健康缓存/
116
+ # 熔断/tools 缓存,披露层级(L0 目录/L1 列表/L2 Schema/L3 调用)
117
+ # 由 McpDisclosureBridge 接入默认 Loop。
118
+ self._mcp_runtime = mcp_runtime
119
+ # P1 大结果 Offload:L3 结果超阈值/命中敏感策略 → Artifact Store 外置。
120
+ self._mcp_disclosure = McpDisclosureBridge(
121
+ mcp_runtime,
122
+ artifact_store=artifact_store,
123
+ offload_policy=mcp_offload_policy,
124
+ )
125
+ # Provider-owned dynamic delegation. The engine only knows the stable
126
+ # tool/runtime seam; provider selection remains outside the LangGraph
127
+ # execution kernel.
128
+ self._delegation_runtime = delegation_runtime
129
+ # P3 补强:事件出口回调(session_id, run_id, event)——洞察登记处
130
+ # (ksadk.harness.insights)由此拿到完整事件流,供 Studio API 消费。
131
+ self._event_sink = event_sink
132
+ # Context 构建管线(规划/压缩/组装/Manifest 投影,见 context_pipeline)。
133
+ self._context_pipeline = (
134
+ EngineContextPipeline(
135
+ context_engine=self._context_engine,
136
+ reasoner=self._reasoner,
137
+ event_fn=self._event,
138
+ memory_runtime=self._memory_runtime,
139
+ prompt_cache_tracker=self._prompt_cache_tracker,
140
+ )
141
+ if self._context_engine is not None
142
+ else None
143
+ )
144
+ # 最近 compile 的 Spec(子 Agent 派生 child spec 用)。
145
+ self._current_spec: HarnessSpec | None = None
146
+ # 收口 6:子 Agent 事件缓冲(run_id → 待并入父流的子事件)。
147
+ # 子 Agent 在 tool_calls 节点内联执行,但事件必须等本节点自身的
148
+ # tool.call.begin/end 落定后统一重排并入,保证 seq 单调。
149
+ self._pending_child_events: dict[str, list[RuntimeEvent]] = {}
150
+ # 并行子 Agent 按 call_id 单独缓冲,节点结束时再按模型原始调用顺序
151
+ # 合并,避免墙钟完成顺序造成 Trace/重放结果不确定。
152
+ self._pending_subagent_events: dict[str, dict[str, list[RuntimeEvent]]] = {}
153
+ # parent_run_id -> call_id -> (child_engine, child_handle)。父取消必须先
154
+ # 显式传播到所有活动子 Run,不能只依赖 asyncio 任务树的隐式取消。
155
+ self._active_subagent_runs: dict[str, dict[str, tuple[Any, RunHandle]]] = {}
156
+ self._runs: dict[str, _EngineRun] = {}
157
+
158
+ # ------------------------------------------------------------- compile
159
+
160
+ async def compile(self, spec: HarnessSpec) -> CompiledHarness:
161
+ # 集成项 4:拓扑由 Strategy Registry 按 spec.execution_strategy 编译,
162
+ # 引擎不再硬编码 single_agent_plan。
163
+ plan = self._strategy_registry.compile(spec, strategy=spec.execution_strategy.kind.value)
164
+ if spec.execution_strategy.kind.value == self._strategy_registry.default():
165
+ ExecutionStrategyRegistry.assert_single_agent_purity(plan)
166
+ max_parallel = spec.execution_strategy.config.get("max_parallel_subagents", 4)
167
+ if isinstance(max_parallel, bool) or not isinstance(max_parallel, int):
168
+ raise ExecutionEngineError("max_parallel_subagents 必须是整数")
169
+ if not 1 <= max_parallel <= 32:
170
+ raise ExecutionEngineError("max_parallel_subagents 必须在 1..32 之间")
171
+ failure_mode = spec.execution_strategy.config.get("subagent_failure_mode", "partial")
172
+ if failure_mode not in {"partial", "fail_fast"}:
173
+ raise ExecutionEngineError("subagent_failure_mode 必须是 partial 或 fail_fast")
174
+ try:
175
+ run_control_spec_from_config(spec.execution_strategy.config)
176
+ except ValueError as exc:
177
+ raise ExecutionEngineError(f"run_control 配置无效: {exc}") from exc
178
+ declared_sub_agents = {binding.name for binding in spec.sub_agents}
179
+ self._skill_disclosure.validate_bindings(
180
+ spec,
181
+ tool_names=set(self._tools),
182
+ sub_agent_names=set(self._sub_agents) | declared_sub_agents,
183
+ )
184
+ self._mcp_disclosure.validate_bindings(
185
+ spec,
186
+ tool_names=set(self._tools),
187
+ sub_agent_names=set(self._sub_agents) | declared_sub_agents,
188
+ )
189
+ self._current_spec = spec
190
+ return CompiledHarness(
191
+ spec=spec,
192
+ plan=plan,
193
+ engine_kind="managed-langgraph",
194
+ )
195
+
196
+ # --------------------------------------------------------------- start
197
+
198
+ async def start(
199
+ self, request: StartRequest, compiled: CompiledHarness, *,
200
+ execution_policy=None, execution_policy_resolver=None, execution_policy_request=None,
201
+ ) -> RunHandle:
202
+ run_id = str(request.metadata.get("invocation_id") or f"mle_{uuid.uuid4().hex[:16]}")
203
+ if run_id in self._runs:
204
+ raise ValueError(f"duplicate engine run: {run_id}")
205
+ state = HarnessState(
206
+ tenant_id=self._tenant_id,
207
+ user_id=request.user_id,
208
+ agent_id=str(request.agent_id or compiled.spec.agent_revision_ref),
209
+ session_id=request.session_id,
210
+ run_id=run_id,
211
+ status=RunStatus.PENDING,
212
+ )
213
+ checkpoint_session_id = str(
214
+ request.metadata.get("checkpoint_session_id") or request.session_id
215
+ )
216
+ thread_id = encode_thread_id(
217
+ tenant_id=self._tenant_id,
218
+ user_id=request.user_id,
219
+ agent_id=state.agent_id,
220
+ session_id=checkpoint_session_id,
221
+ run_id=run_id,
222
+ )
223
+ handle = RunHandle(
224
+ run_id=run_id,
225
+ session_id=request.session_id,
226
+ runtime_type="managed-langgraph",
227
+ native_ref={
228
+ "thread_id": thread_id,
229
+ "user_id": request.user_id,
230
+ "agent_id": state.agent_id,
231
+ **({"execution_policy_ref": request.metadata["execution_policy_ref"]}
232
+ if "execution_policy_ref" in request.metadata else {}),
233
+ **({"parent_run_id": request.metadata["parent_run_id"]}
234
+ if "parent_run_id" in request.metadata else {}),
235
+ },
236
+ )
237
+ from ksadk.harness.subagent import SubAgentSpec
238
+
239
+ revision_sub_agents = {
240
+ binding.name: SubAgentSpec.from_binding(binding)
241
+ for binding in compiled.spec.sub_agents
242
+ }
243
+ # Revision 是事实源;宿主同名配置只作为未编译旧路径的兼容兜底。
244
+ effective_sub_agents = {**self._sub_agents, **revision_sub_agents}
245
+ self._runs[run_id] = _EngineRun(
246
+ handle=handle,
247
+ request=request,
248
+ compiled=compiled,
249
+ state=state,
250
+ thread_id=thread_id,
251
+ skill_catalog=self._skill_disclosure.catalog(
252
+ compiled.spec, query=str(request.input or "")
253
+ ),
254
+ mcp_catalog=self._mcp_disclosure.catalog(compiled.spec),
255
+ sub_agents=effective_sub_agents,
256
+ controller=self._new_run_controller(compiled),
257
+ )
258
+ configure_run(
259
+ self, self._runs[run_id], policy=execution_policy,
260
+ resolver=execution_policy_resolver, request=execution_policy_request,
261
+ )
262
+ return handle
263
+
264
+ # -------------------------------------------------------------- attach
265
+
266
+ def is_handle_attached(self, handle: RunHandle) -> bool:
267
+ """Return whether this engine process already owns the live Run state."""
268
+ return handle.run_id in self._runs
269
+
270
+ async def attach(
271
+ self, handle: RunHandle, compiled: CompiledHarness, *, allow_completed: bool = False,
272
+ execution_policy=None, execution_policy_resolver=None, execution_policy_request=None,
273
+ ) -> RunHandle:
274
+ """跨进程恢复(收口 3):从持久 Checkpoint 重建 _EngineRun。
275
+
276
+ 状态从 durable Checkpointer 的 graph snapshot 推断:存在未决 interrupt
277
+ → awaiting_approval;存在 pending 节点 → paused;无 Checkpoint → 诚实报错。
278
+ 事件队列从空开始(历史事件已由平台 EventStore 持久化)。
279
+ """
280
+ if handle.run_id in self._runs:
281
+ return handle
282
+ if self._checkpointer is None:
283
+ raise ExecutionEngineError(
284
+ "attach 需要 durable Checkpointer:跨进程恢复依赖持久 Checkpoint"
285
+ )
286
+ thread_id = str(handle.native_ref.get("thread_id") or "")
287
+ if not thread_id:
288
+ raise ExecutionEngineError(
289
+ f"attach 失败:handle.native_ref 缺少 thread_id(run {handle.run_id!r})"
290
+ )
291
+ # 持久 handle 可能不带 user_id(旧版本句柄):用占位值,事件锚点以
292
+ # Checkpoint 内的图状态为准,跨进程身份由 thread_id 保证。
293
+ user_id = str(handle.native_ref.get("user_id") or "unknown")
294
+ agent_id = str(handle.native_ref.get("agent_id") or compiled.spec.agent_revision_ref)
295
+ state = HarnessState(
296
+ tenant_id=self._tenant_id,
297
+ user_id=user_id,
298
+ agent_id=agent_id,
299
+ session_id=handle.session_id,
300
+ run_id=handle.run_id,
301
+ status=RunStatus.PAUSED,
302
+ )
303
+ run = _EngineRun(
304
+ handle=handle,
305
+ request=StartRequest(
306
+ agent_id=agent_id,
307
+ user_id=user_id,
308
+ session_id=handle.session_id,
309
+ input="",
310
+ runtime_type="managed-langgraph",
311
+ metadata={
312
+ "invocation_id": handle.run_id,
313
+ **{key: handle.native_ref[key] for key in
314
+ ("parent_run_id", "execution_policy_ref") if key in handle.native_ref},
315
+ },
316
+ ),
317
+ compiled=compiled,
318
+ state=state,
319
+ thread_id=thread_id,
320
+ skill_catalog=self._skill_disclosure.catalog(compiled.spec),
321
+ mcp_catalog=self._mcp_disclosure.catalog(compiled.spec),
322
+ controller=self._new_run_controller(compiled),
323
+ )
324
+ run.started_emitted = True # run.started 已在首个进程发出
325
+ run.done = False
326
+ configure_run(
327
+ self, run, policy=execution_policy,
328
+ resolver=execution_policy_resolver, request=execution_policy_request,
329
+ )
330
+ # 从 Checkpoint snapshot 推断挂起状态。
331
+ graph = self._build_graph(run)
332
+ snapshot = await graph.aget_state({"configurable": {"thread_id": thread_id}})
333
+ if snapshot is None or not snapshot.values or (not snapshot.next and not allow_completed):
334
+ raise ExecutionEngineError(f"attach 失败:thread {thread_id!r} 无未决 Checkpoint")
335
+ tasks = getattr(snapshot, "tasks", None) or ()
336
+ if isinstance(tasks, dict):
337
+ tasks = tuple(tasks.values())
338
+ has_interrupt = any(getattr(task, "interrupts", None) for task in tasks)
339
+ for task in tasks:
340
+ for pending in getattr(task, "interrupts", ()):
341
+ value = getattr(pending, "value", {})
342
+ if isinstance(value, dict) and value.get("call_id"):
343
+ run.pending_approval_call_id = str(value["call_id"])
344
+ run.pending_approval = dict(value)
345
+ break
346
+ if run.controller is not None:
347
+ values = getattr(snapshot, "values", None) or {}
348
+ control_snapshot = values.get("run_control") if isinstance(values, dict) else None
349
+ if control_snapshot:
350
+ run.controller.restore(control_snapshot)
351
+ run.state.status = RunStatus.AWAITING_APPROVAL if has_interrupt else RunStatus.PAUSED
352
+ values = snapshot.values
353
+ budgets.restore(run, values.get("budget") or {})
354
+ run.seq = int(values.get("event_seq") or 0)
355
+ run.state.messages = self._messages(values.get("messages", []))
356
+ if not snapshot.next:
357
+ terminal = values.get("execution_terminal") or "completed"
358
+ run.state.status = RunStatus(terminal)
359
+ run.done = True
360
+ self._runs[handle.run_id] = run
361
+ from ksadk.harness.engine.subagents import restore_pending_child
362
+
363
+ await restore_pending_child(self, run)
364
+ return handle
365
+
366
+ # -------------------------------------------------------------- stream
367
+
368
+ def stream(self, handle: RunHandle) -> AsyncIterator[RuntimeEvent]:
369
+ return self._stream(handle)
370
+
371
+ async def _stream(self, handle: RunHandle) -> AsyncIterator[RuntimeEvent]:
372
+ run = self._require_run(handle)
373
+ task_finished = run.task is None or run.task.done()
374
+ if run.state.status in (RunStatus.AWAITING_APPROVAL, RunStatus.PAUSED) and task_finished:
375
+ # 挂起中:只回放未消费事件,不重启图(恢复必须走 resume)。
376
+ while run.events:
377
+ yield run.events.pop(0)
378
+ return
379
+ if run.done and task_finished:
380
+ while run.events:
381
+ yield run.events.pop(0)
382
+ return
383
+ if run.task is None or task_finished:
384
+ run.task = asyncio.create_task(self._execute(run))
385
+ try:
386
+ while True:
387
+ while run.events:
388
+ event = run.events.pop(0)
389
+ self._emit_insight(run, event)
390
+ yield event
391
+ if run.task.done():
392
+ break
393
+ await asyncio.sleep(0)
394
+ remaining = await run.task
395
+ for event in remaining:
396
+ self._emit_insight(run, event)
397
+ yield event
398
+ except asyncio.CancelledError:
399
+ # A subscriber timeout must cancel and await the executing graph,
400
+ # not just mark its output stream finished while tools keep running.
401
+ await self.cancel(handle)
402
+ raise
403
+
404
+ def _emit_insight(self, run: _EngineRun, event: RuntimeEvent) -> None:
405
+ """事件出口统一回调(洞察登记处 / 审计侧消费;异常不阻断主流程)。"""
406
+ if self._event_sink is None:
407
+ return
408
+ try:
409
+ self._event_sink(run.state.session_id, run.handle.run_id, event)
410
+ except Exception: # noqa: BLE001 - 登记失败不阻断对话主流程
411
+ pass
412
+
413
+ def harness_capabilities(self):
414
+ """返回运行时真实治理声明;该声明也随每个 Run 的首批事件保存。"""
415
+ from ksadk.harness.runtime_capabilities import managed_langgraph_capabilities
416
+
417
+ return managed_langgraph_capabilities()
418
+
419
+ async def _execute(
420
+ self,
421
+ run: _EngineRun,
422
+ resume_command: Command | None = None,
423
+ *,
424
+ resume_from_checkpoint: bool = False,
425
+ ) -> list[RuntimeEvent]:
426
+ run.execution_started_at = time.monotonic()
427
+ spec = run.compiled.spec
428
+ run.state.status = RunStatus.RUNNING
429
+ if not run.started_emitted:
430
+ run.started_emitted = True
431
+ run.events.append(self._event(run, EventType.RUN_STARTED, {"status": "in_progress"}))
432
+ # 收口 5:事件树根——Agent 生命周期(主 Agent 与未来子 Agent 同构)。
433
+ run.events.append(
434
+ self._event(run, EventType.AGENT_STARTED, {"agent_id": run.state.agent_id})
435
+ )
436
+ from ksadk.harness.engine.capability_declarations import (
437
+ capability_declarations,
438
+ )
439
+
440
+ run.events.extend(capability_declarations(self, run))
441
+ try:
442
+ if run.cancel_requested:
443
+ raise asyncio.CancelledError
444
+ await revalidate_policy(self, run)
445
+ graph = self._build_graph(run)
446
+ instructions = spec.prompt.instructions or ""
447
+ config = {
448
+ "configurable": {"thread_id": run.thread_id},
449
+ # Sequential tool checkpoints are graph steps too. The model
450
+ # turn/tool budgets, not LangGraph's default 25, govern a Run.
451
+ "recursion_limit": max(64, self._max_reasoning_turns * 128),
452
+ }
453
+ invoke_input: _GraphState | Command | None
454
+ if resume_command is not None:
455
+ invoke_input = resume_command
456
+ elif resume_from_checkpoint:
457
+ # 通用 pause 恢复:None → LangGraph 从最近 Checkpoint 续跑。
458
+ invoke_input = None
459
+ else:
460
+ # 收口 1:ContextEngine 真正控制首次模型输入(规划 + 主动/紧急压缩
461
+ # + 组装);未注入时回退旧的 history 拼接路径。
462
+ planned = await self._prepare_context(run, instructions)
463
+ if planned is not None:
464
+ conversation = planned
465
+ else:
466
+ history = run.request.metadata.get("conversation_history") or []
467
+ conversation = [{"role": "system", "content": instructions}]
468
+ skill_catalog_message = self._skill_disclosure.catalog_message(
469
+ run.skill_catalog
470
+ )
471
+ if skill_catalog_message:
472
+ conversation.append(skill_catalog_message)
473
+ mcp_catalog_message = self._mcp_disclosure.catalog_message(
474
+ run.mcp_catalog
475
+ )
476
+ if mcp_catalog_message:
477
+ conversation.append(mcp_catalog_message)
478
+ if isinstance(history, list) and history:
479
+ # 宿主(如 Studio Playground)注入的会话历史已含当前输入。
480
+ conversation.extend(dict(m) for m in history if isinstance(m, dict))
481
+ else:
482
+ conversation.append(
483
+ {"role": "user", "content": str(run.request.input or "")}
484
+ )
485
+ invoke_input = {
486
+ "messages": conversation,
487
+ "pending_tool_calls": [],
488
+ "turn_count": 0,
489
+ "route": "reason",
490
+ "mcp_listed": [],
491
+ "mcp_schema_read": [],
492
+ "finalization_retries": 0,
493
+ "delegation_synthesis_pending": False,
494
+ "run_control": (
495
+ run.controller.snapshot() if run.controller is not None else {}
496
+ ),
497
+ }
498
+ from ksadk.harness.engine.run_control_bridge import invoke_graph_with_control
499
+
500
+ with execution_policy_scope(run.execution_policy):
501
+ final_state = await invoke_graph_with_control(
502
+ graph, invoke_input, config, run.controller
503
+ )
504
+ interrupts = final_state.get("__interrupt__") if isinstance(final_state, dict) else None
505
+ if interrupts:
506
+ # Approval 挂起:图状态已由 Checkpointer 持久化,等待 resume。
507
+ run.state.status = RunStatus.AWAITING_APPROVAL
508
+ run.done = False
509
+ info = getattr(interrupts[0], "value", {}) or {}
510
+ run.pending_approval_call_id = str(info.get("call_id") or "")
511
+ run.pending_approval = dict(info)
512
+ approval_id = f"ap-{run.handle.run_id}-{info.get('call_id', '')}"
513
+ run.events.append(
514
+ self._event(
515
+ run,
516
+ EventType.APPROVAL_REQUESTED,
517
+ {
518
+ "approval_id": approval_id,
519
+ "call_id": str(info.get("call_id", "")),
520
+ "kind": "tool",
521
+ "detail": info,
522
+ },
523
+ )
524
+ )
525
+ run.events.append(
526
+ self._event(
527
+ run,
528
+ EventType.RUN_INTERRUPTED,
529
+ {"status": "awaiting_approval", "reason": "tool_approval",
530
+ "approval_id": approval_id},
531
+ )
532
+ )
533
+ return []
534
+ # 影子状态消息(§6.2.1):完整对话消息投影,供 Transcript 持久化。
535
+ final_messages = final_state.get("messages", [])
536
+ run.state.messages = self._messages(final_messages)
537
+ # 最终答案事件由 reason 节点统一产生。这里仅投影 Transcript;若再从
538
+ # final_state 补发,stream 已消费 reason 事件时会造成同一答案重复展示。
539
+ if run.cancel_requested:
540
+ raise asyncio.CancelledError
541
+ from ksadk.harness.engine.completion_guard import unfinished_delegations
542
+
543
+ unfinished = unfinished_delegations(run.events)
544
+ if unfinished:
545
+ labels = ", ".join(unfinished.values())
546
+ raise ExecutionEngineError(
547
+ "parent run cannot complete while delegated children lack terminal "
548
+ f"evidence: {labels}"
549
+ )
550
+ run.state.status = RunStatus.COMPLETED
551
+ run.events.append(
552
+ self._event(
553
+ run,
554
+ EventType.AGENT_COMPLETED,
555
+ {"agent_id": run.state.agent_id, "status": "completed"},
556
+ )
557
+ )
558
+ from ksadk.harness.engine.run_control_bridge import completion_payload
559
+
560
+ payload = completion_payload(run)
561
+ run.events.append(self._event(run, EventType.RUN_COMPLETED, payload))
562
+ run.done = True
563
+ return []
564
+ except asyncio.CancelledError:
565
+ if run.pause_requested:
566
+ # 通用 pause:非终止性挂起,Checkpoint 持久化后可 resume。
567
+ run.pause_requested = False
568
+ run.state.status = RunStatus.PAUSED
569
+ run.done = False
570
+ run.events.append(
571
+ self._event(
572
+ run,
573
+ EventType.RUN_INTERRUPTED,
574
+ {"status": "paused", "reason": "pause_requested"},
575
+ )
576
+ )
577
+ return []
578
+ run.state.status = RunStatus.CANCELED
579
+ run.done = True
580
+ run.events.append(self._event(run, EventType.RUN_CANCELED, {"status": "cancelled"}))
581
+ return []
582
+ except GraphInterrupt as exc:
583
+ # checkpoint=False 路径(无 Checkpointer 时 interrupt 直接抛出)。
584
+ run.state.status = RunStatus.AWAITING_APPROVAL
585
+ run.done = False
586
+ run.events.append(
587
+ self._event(
588
+ run,
589
+ EventType.RUN_INTERRUPTED,
590
+ {"status": "awaiting_approval", "reason": f"graph_interrupt: {exc}"},
591
+ )
592
+ )
593
+ return []
594
+ except RunControlStop as exc:
595
+ from ksadk.harness.engine.run_control_bridge import append_controlled_stop
596
+
597
+ append_controlled_stop(self, run, exc.reason)
598
+ return []
599
+ except Exception as exc: # noqa: BLE001
600
+ run.state.status = RunStatus.FAILED
601
+ run.done = True
602
+ run.events.append(
603
+ self._event(
604
+ run,
605
+ EventType.AGENT_COMPLETED,
606
+ {"agent_id": run.state.agent_id, "status": "failed"},
607
+ )
608
+ )
609
+ run.events.append(
610
+ self._event(
611
+ run,
612
+ EventType.RUN_FAILED,
613
+ {
614
+ "status": "failed",
615
+ "error": str(exc),
616
+ **(
617
+ {"error_category": str(exc.category)}
618
+ if getattr(exc, "category", None)
619
+ else {}
620
+ ),
621
+ },
622
+ )
623
+ )
624
+ return []
625
+
626
+ finally:
627
+ budgets.account_elapsed(run)
628
+ run.execution_started_at = None
629
+
630
+ # ---------------------------------------------------------------- graph
631
+
632
+ def _build_graph(self, run: _EngineRun):
633
+ # 图组装(节点实现/边/条件路由)拆至 graph_builder 模块,保持本模块
634
+ # <1000 行的仓库合同;节点闭包仍经 engine 访问运行时状态。
635
+ from ksadk.harness.engine.graph_builder import build_graph
636
+
637
+ return build_graph(self, run)
638
+
639
+ async def _invoke_tool(
640
+ self,
641
+ name: str,
642
+ arguments: dict[str, Any],
643
+ *,
644
+ run: Any = None,
645
+ mcp_cursors: McpDisclosureCursors | None = None,
646
+ call_id: str = "",
647
+ ) -> Any:
648
+ from ksadk.harness.engine.tool_dispatch import invoke_tool
649
+
650
+ if run is not None:
651
+ await revalidate_policy(self, run)
652
+ with execution_policy_scope(run.execution_policy if run is not None else None):
653
+ return await invoke_tool(
654
+ self, name, arguments, run=run, mcp_cursors=mcp_cursors, call_id=call_id
655
+ )
656
+
657
+ # --------------------------------------------------------------- cancel
658
+
659
+ async def cancel(self, handle: RunHandle) -> CancelResult:
660
+ run = self._runs.get(handle.run_id)
661
+ if run is None or run.done:
662
+ return CancelResult.NOT_RUNNING
663
+ run.cancel_requested = True
664
+ active_children = list(self._active_subagent_runs.get(handle.run_id, {}).values())
665
+ active_task = run.task if run.task is not None and not run.task.done() else None
666
+ if active_task is not None:
667
+ active_task.cancel()
668
+ await asyncio.gather(active_task, return_exceptions=True)
669
+ else:
670
+ from ksadk.harness.engine.subagents import cancel_and_drain
671
+ from ksadk.harness.subagent import resequence_child_events
672
+
673
+ for child_engine, child_handle in active_children:
674
+ await cancel_and_drain(
675
+ child_engine, child_handle,
676
+ lambda event: resequence_child_events(run, [event], observe=True),
677
+ )
678
+ self._active_subagent_runs.pop(handle.run_id, None)
679
+ if self._delegation_runtime is not None:
680
+ await self._delegation_runtime.cancel_parent(handle.run_id)
681
+ if run.task is None and run.state.status is RunStatus.PENDING:
682
+ return CancelResult.PENDING_CANCEL_RECORDED
683
+ if active_task is None:
684
+ run.done = True
685
+ run.state.status = RunStatus.CANCELED
686
+ run.events.append(self._event(run, EventType.RUN_CANCELED, {"status": "cancelled"}))
687
+ return CancelResult.INTERRUPTED_ACTIVE_TURN
688
+ return CancelResult.INTERRUPTED_ACTIVE_TURN
689
+
690
+ # --------------------------------------------------------------- pause
691
+
692
+ async def pause(self, handle: RunHandle) -> PauseResult:
693
+ """通用 pause:取消当前回合但保留状态,Checkpointer 持久化后可 resume。"""
694
+ run = self._runs.get(handle.run_id)
695
+ if run is None or run.done:
696
+ return PauseResult.NOT_RUNNING
697
+ if run.state.status not in (RunStatus.RUNNING, RunStatus.PENDING):
698
+ return PauseResult.NOT_RUNNING
699
+ if self._checkpointer is None:
700
+ return PauseResult.NOT_SUPPORTED
701
+ if run.task is None or run.task.done():
702
+ # 尚未启动流式执行:直接置 PAUSED,start 后由 stream/resume 驱动。
703
+ run.state.status = RunStatus.PAUSED
704
+ run.events.append(
705
+ self._event(
706
+ run,
707
+ EventType.RUN_INTERRUPTED,
708
+ {"status": "paused", "reason": "pause_requested"},
709
+ )
710
+ )
711
+ return PauseResult.PAUSED_ACTIVE_TURN
712
+ run.pause_requested = True
713
+ run.task.cancel()
714
+ return PauseResult.PAUSED_ACTIVE_TURN
715
+
716
+ # --------------------------------------------------------------- resume
717
+
718
+ async def resume(
719
+ self,
720
+ handle: RunHandle,
721
+ target: ResumeTarget,
722
+ payload: ResumePayload | None,
723
+ ) -> RunHandle:
724
+ run = self._require_run(handle)
725
+ await revalidate_policy(self, run)
726
+ if run.state.status is RunStatus.PAUSED:
727
+ if self._checkpointer is None:
728
+ raise ExecutionEngineError(
729
+ "resume 需要 Checkpointer:pause 状态由 Checkpoint 持久化"
730
+ )
731
+ # 通用恢复:从最近 Checkpoint 续跑(非审批通道)。
732
+ run.state.status = RunStatus.RUNNING
733
+ run.events.append(
734
+ self._event(
735
+ run,
736
+ EventType.RUN_RESUMED,
737
+ {"target": target.id, "resume_kind": "checkpoint"},
738
+ )
739
+ )
740
+ run.task = asyncio.create_task(self._execute(run, resume_from_checkpoint=True))
741
+ return handle
742
+ if run.state.status is not RunStatus.AWAITING_APPROVAL:
743
+ raise ExecutionEngineError(
744
+ f"resume 仅支持 awaiting_approval 状态,当前 {run.state.status.value}"
745
+ )
746
+ if self._checkpointer is None:
747
+ raise ExecutionEngineError(
748
+ "resume 需要 Checkpointer:interrupt 状态由 Checkpoint 持久化"
749
+ )
750
+ if (
751
+ payload is None or payload.kind != "approval_decision"
752
+ or not run.pending_approval_call_id
753
+ or payload.call_id != run.pending_approval_call_id
754
+ or payload.data not in ("approved", "denied", "rejected")
755
+ ):
756
+ raise ExecutionEngineError(
757
+ "approval resume requires an explicit decision for the pending call_id"
758
+ )
759
+ decision = "denied"
760
+ if payload is not None:
761
+ decision = str(payload.data) if payload.data is not None else "approved"
762
+ run.events.append(
763
+ self._event(
764
+ run,
765
+ EventType.APPROVAL_RESOLVED,
766
+ {
767
+ "approval_id": f"ap-{run.handle.run_id}-{payload.call_id or ''}",
768
+ "call_id": payload.call_id or "",
769
+ "decision": decision,
770
+ },
771
+ )
772
+ )
773
+ run.state.status = RunStatus.RUNNING
774
+ run.events.append(
775
+ self._event(
776
+ run,
777
+ EventType.RUN_RESUMED,
778
+ {"target": target.id, "resume_kind": "approval_decision"},
779
+ )
780
+ )
781
+ run.task = asyncio.create_task(self._execute(run, resume_command=Command(resume=decision)))
782
+ return handle
783
+
784
+ # ------------------------------------------------------------- snapshot
785
+
786
+ async def snapshot_state(self, handle: RunHandle) -> HarnessState | None:
787
+ run = self._runs.get(handle.run_id)
788
+ return run.state if run else None
789
+
790
+ def capabilities(self) -> EngineCapabilityMatrix:
791
+ return EngineCapabilityMatrix(
792
+ cancel=EngineCapability(supported=True),
793
+ resume=EngineCapability(
794
+ supported=True, reason="approval + checkpoint (paused) channels"
795
+ ),
796
+ checkpoint=EngineCapability(
797
+ supported=self._checkpointer is not None,
798
+ reason=None if self._checkpointer else "no checkpointer injected",
799
+ ),
800
+ interrupt=EngineCapability(supported=True, reason="approval channel only"),
801
+ durable_across_process=EngineCapability(
802
+ supported=self._checkpointer is not None and _is_durable(self._checkpointer),
803
+ reason=None,
804
+ ),
805
+ streaming=EngineCapability(supported=True),
806
+ )
807
+
808
+ async def close(self, handle: RunHandle) -> None:
809
+ if handle.run_id in self._runs and not self._runs[handle.run_id].done:
810
+ await self.cancel(handle)
811
+ run = self._runs.pop(handle.run_id, None)
812
+ if run and run.task and not run.task.done():
813
+ run.task.cancel()
814
+ await asyncio.gather(run.task, return_exceptions=True)
815
+ if run is not None:
816
+ self._skill_disclosure.clear_run(run.handle.run_id)
817
+ self._mcp_disclosure.clear_run(run.handle.run_id)
818
+ self._pending_child_events.pop(run.handle.run_id, None)
819
+ self._pending_subagent_events.pop(run.handle.run_id, None)
820
+ self._active_subagent_runs.pop(run.handle.run_id, None)
821
+ if self._delegation_runtime is not None:
822
+ self._delegation_runtime.clear_run(run.handle.run_id)
823
+
824
+ # ------------------------------------------------------------- helpers
825
+
826
+ async def _prepare_context(
827
+ self, run: _EngineRun, instructions: str
828
+ ) -> list[dict[str, Any]] | None:
829
+ """Context 构建管线委托(长任务方案 §6/§8,实现见 context_pipeline)。"""
830
+ if self._context_engine is None:
831
+ return None
832
+ return await self._context_pipeline.prepare_context(run, instructions)
833
+
834
+ def _require_run(self, handle: RunHandle) -> _EngineRun:
835
+ try:
836
+ return self._runs[handle.run_id]
837
+ except KeyError:
838
+ raise KeyError(f"unknown engine run: {handle.run_id}") from None
839
+
840
+ async def _invoke_mcp_tool(
841
+ self,
842
+ name: str,
843
+ arguments: dict[str, Any],
844
+ *,
845
+ run: _EngineRun | None,
846
+ cursors: McpDisclosureCursors,
847
+ call_id: str = "",
848
+ ) -> dict[str, Any]:
849
+ return await self._mcp_disclosure.invoke(
850
+ name,
851
+ arguments,
852
+ run=run,
853
+ cursors=cursors,
854
+ pending_events=self._pending_child_events,
855
+ call_id=call_id,
856
+ )
857
+
858
+ def _invoke_skill_tool(
859
+ self, name: str, arguments: dict[str, Any], *, run: _EngineRun | None
860
+ ) -> dict[str, Any]:
861
+ return self._skill_disclosure.invoke(
862
+ name,
863
+ arguments,
864
+ run=run,
865
+ pending_events=self._pending_child_events,
866
+ )
867
+
868
+ def _event(
869
+ self, run: _EngineRun, event_type: str, payload: dict[str, Any], *, phase: str | None = None
870
+ ) -> RuntimeEvent:
871
+ run.seq += 1
872
+ event = RuntimeEvent.create(
873
+ event_type,
874
+ agent_id=run.state.agent_id,
875
+ user_id=run.state.user_id,
876
+ session_id=run.state.session_id,
877
+ invocation_id=run.handle.run_id,
878
+ seq_id=run.seq,
879
+ payload=payload,
880
+ phase=phase,
881
+ )
882
+ if run.controller is not None:
883
+ run.control_events.append(event)
884
+ run.controller.observe(event)
885
+ run.observed_event_ids.add(event.event_id)
886
+ return event
887
+
888
+ @staticmethod
889
+ def _messages(messages):
890
+ return [
891
+ Message(
892
+ role=MessageRole(m.get("role", "user")), content=str(m.get("content") or ""),
893
+ tool_call_id=str(m["tool_call_id"]) if m.get("tool_call_id") else None,
894
+ name=str(m["name"]) if m.get("name") else None,
895
+ )
896
+ for m in messages if isinstance(m, dict)
897
+ ]
898
+
899
+ @staticmethod
900
+ def _new_run_controller(compiled: CompiledHarness) -> RunController | None:
901
+ from ksadk.harness.engine.run_control_bridge import new_run_controller
902
+
903
+ return new_run_controller(compiled)
904
+
905
+
906
+ def _is_durable(checkpointer: BaseCheckpointSaver) -> bool:
907
+ """SQLite/Postgres Checkpointer 视为跨进程持久;MemorySaver 不是。"""
908
+ from langgraph.checkpoint.memory import InMemorySaver, MemorySaver
909
+
910
+ return not isinstance(checkpointer, (MemorySaver, InMemorySaver))
911
+
912
+
913
+ def memory_checkpointer() -> BaseCheckpointSaver:
914
+ """进程内 Checkpointer(langgraph 类型不越出本模块的架构合同)。"""
915
+ from langgraph.checkpoint.memory import InMemorySaver
916
+
917
+ return InMemorySaver()
918
+
919
+
920
+ def sqlite_checkpointer(db_path: str) -> Any:
921
+ """SQLite 异步 Checkpointer 的上下文管理器(调用方负责 __aenter__)。
922
+
923
+ 经由本工厂获取,避免 langgraph import 越出引擎模块
924
+ (tests/architecture/test_harness_contract.py 守卫)。
925
+ """
926
+ from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
927
+
928
+ return AsyncSqliteSaver.from_conn_string(db_path)
929
+
930
+
931
+ __all__ = ["ManagedLangGraphEngine", "memory_checkpointer", "sqlite_checkpointer"]