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,884 @@
1
+ """Canonical RuntimeAdapter for the managed KsADK Harness engine.
2
+
3
+ Studio and the platform persist canonical RuntimeEvent v2 values, while the
4
+ managed engine intentionally owns a richer, engine-internal event vocabulary.
5
+ This adapter is the boundary between the two contracts: it keeps the managed
6
+ Agent Loop behind the stable ``runtime_type=harness`` product name and projects
7
+ the execution tree into canonical status items without teaching Studio about
8
+ engine-private Python objects.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ from pathlib import Path
15
+ from typing import Any, AsyncIterator
16
+
17
+ from ksadk.events.canonical import (
18
+ ApprovalRequest,
19
+ ErrorInfo,
20
+ InteractionRequested,
21
+ ItemCompleted,
22
+ ItemStarted,
23
+ ItemUpdated,
24
+ OutputRef,
25
+ RunCanceled,
26
+ RunCompleted,
27
+ RunFailed,
28
+ RunInterrupted,
29
+ RunStarted,
30
+ SourceRef,
31
+ UsageReported,
32
+ )
33
+ from ksadk.events.content import ContentSnapshot, TextContent
34
+ from ksadk.events.identity import stable_event_id, stable_item_id, stable_scope_id
35
+ from ksadk.harness.context_engine import HarnessContextEngine
36
+ from ksadk.harness.engine.langgraph import ManagedLangGraphEngine, memory_checkpointer
37
+ from ksadk.harness.events import EventType
38
+ from ksadk.harness.events import RuntimeEvent as HarnessEvent
39
+ from ksadk.harness.execution_policy import ExecutionPolicy, ExecutionPolicyResolver
40
+ from ksadk.harness.public_activity import tool_public_action
41
+ from ksadk.harness.reasoner import HarnessReasoner
42
+ from ksadk.harness.skill_composition import compose_engine
43
+ from ksadk.harness.spec import HarnessSpec
44
+ from ksadk.kernel.contracts import RuntimeCapability, RuntimeCapabilityMatrix
45
+ from ksadk.kernel.errors import UnsupportedControlError
46
+ from ksadk.runtime import (
47
+ BaseRuntime,
48
+ CancelResult,
49
+ CheckpointCapability,
50
+ CheckpointDescriptor,
51
+ ResumePayload,
52
+ ResumeTarget,
53
+ RunHandle,
54
+ RuntimeAdapter,
55
+ StartRequest,
56
+ )
57
+
58
+
59
+ class ManagedHarnessRuntime(BaseRuntime):
60
+ runtime_type = "harness"
61
+
62
+ def __init__(self, *, durable: bool = False) -> None:
63
+ self._durable = durable
64
+
65
+ def native_capabilities(self) -> dict[str, Any]:
66
+ return {
67
+ "cancel": {"supported": True},
68
+ "resume": {"supported": True},
69
+ "checkpoint": {"supported": True, "granularity": "snapshot"},
70
+ "session_continuity": {
71
+ "durable": self._durable,
72
+ "scope": "workspace" if self._durable else "process",
73
+ },
74
+ "progressive_disclosure": {"skill": True, "mcp": True},
75
+ }
76
+
77
+
78
+ class ManagedHarnessRuntimeAdapter(RuntimeAdapter):
79
+ """Expose :class:`ManagedLangGraphEngine` through the platform adapter API."""
80
+
81
+ def __init__(
82
+ self,
83
+ spec: HarnessSpec,
84
+ *,
85
+ reasoner: HarnessReasoner | None = None,
86
+ workspace_root: str | Path = ".",
87
+ engine: ManagedLangGraphEngine | None = None,
88
+ durable: bool = False,
89
+ shared_across_pods: bool = False,
90
+ execution_policy_resolver: ExecutionPolicyResolver | None = None,
91
+ ) -> None:
92
+ super().__init__(ManagedHarnessRuntime(durable=durable))
93
+ self._spec = spec
94
+ self._workspace_root = Path(workspace_root)
95
+ self._durable = durable
96
+ self._shared_across_pods = shared_across_pods
97
+ self._execution_policy_resolver = execution_policy_resolver
98
+ self._engine = engine or compose_engine(
99
+ spec,
100
+ reasoner=reasoner,
101
+ checkpointer=memory_checkpointer(),
102
+ context_engine=HarnessContextEngine(),
103
+ )
104
+ self._compiled: Any | None = None
105
+ self._external_handles: dict[str, RunHandle] = {}
106
+ #: 由装配层注入(持久 Checkpoint 分档时非空);为空则不持久化 Handle。
107
+ self._run_store: Any | None = None
108
+
109
+ def capabilities(self) -> RuntimeCapabilityMatrix:
110
+ return managed_harness_capabilities(
111
+ durable=self._durable,
112
+ execution_policy=self._execution_policy_resolver is not None,
113
+ )
114
+
115
+ async def _policy_options(self, request: StartRequest) -> dict[str, Any]:
116
+ ref = request.metadata.get("execution_policy_ref")
117
+ if ref is None:
118
+ return {}
119
+ if not isinstance(ref, str) or not ref.strip():
120
+ raise ValueError("execution_policy_ref must be a non-empty host reference")
121
+ if self._execution_policy_resolver is None:
122
+ raise UnsupportedControlError("execution policy requires a trusted host resolver")
123
+ policy = await self._execution_policy_resolver.resolve(ref, request=request)
124
+ if not isinstance(policy, ExecutionPolicy):
125
+ raise TypeError("host resolver must return ExecutionPolicy")
126
+ return {
127
+ "execution_policy": policy,
128
+ "execution_policy_resolver": self._execution_policy_resolver,
129
+ "execution_policy_request": request,
130
+ }
131
+
132
+ def _persist_durable_handle(
133
+ self,
134
+ handle: RunHandle,
135
+ status: str = "running",
136
+ *,
137
+ terminal: bool = False,
138
+ ) -> None:
139
+ if self._run_store is None:
140
+ return
141
+ runs, handles = self._run_store.load()
142
+ runs[handle.run_id] = {"runId": handle.run_id, "status": status}
143
+ if terminal:
144
+ handles.pop(handle.run_id, None)
145
+ else:
146
+ handles[handle.run_id] = handle
147
+ self._run_store.save(runs, handles)
148
+
149
+ async def attach(self, handle: RunHandle) -> RunHandle:
150
+ """Attach a persisted platform handle to the durable LangGraph thread."""
151
+
152
+ if not self._durable:
153
+ raise UnsupportedControlError(
154
+ f"managed Harness run {handle.run_id!r} has no durable checkpoint backend"
155
+ )
156
+ if handle.runtime_type != "harness":
157
+ raise ValueError(f"managed Harness cannot attach {handle.runtime_type!r} handle")
158
+ request = StartRequest(
159
+ input="", user_id=str(handle.native_ref.get("user_id") or "unknown"),
160
+ session_id=handle.session_id, agent_id=handle.native_ref.get("agent_id"),
161
+ metadata={
162
+ "invocation_id": handle.run_id,
163
+ **({"execution_policy_ref": handle.native_ref["execution_policy_ref"]}
164
+ if "execution_policy_ref" in handle.native_ref else {}),
165
+ },
166
+ )
167
+ options = await self._policy_options(request)
168
+ if handle.run_id in self._external_handles:
169
+ return handle
170
+ compiled = await self._ensure_compiled()
171
+ internal_handle = handle.model_copy(update={"runtime_type": "managed-langgraph"})
172
+ internal = await self._engine.attach(internal_handle, compiled, **options)
173
+ self._external_handles[handle.run_id] = internal
174
+ return handle
175
+
176
+ async def durable_restore(self, handle: RunHandle) -> RunHandle:
177
+ """Restore a persisted handle and continue non-interactive checkpoints.
178
+
179
+ Approval checkpoints deliberately remain ``awaiting_approval`` so the
180
+ Kernel can route the later interaction to the newly attached adapter.
181
+ A process crash during ordinary graph execution is reconstructed as a
182
+ paused checkpoint and must resume automatically; otherwise attach
183
+ succeeds but the durable Run remains open forever.
184
+ """
185
+
186
+ restored = await self.attach(handle)
187
+ internal = self._internal_handle(restored)
188
+ state = await self._engine.snapshot_state(internal)
189
+ status = str(getattr(getattr(state, "status", None), "value", ""))
190
+ if status == "paused":
191
+ await self._engine.resume(
192
+ internal,
193
+ ResumeTarget(
194
+ kind="checkpoint_id",
195
+ id=str(internal.native_ref.get("thread_id") or internal.run_id),
196
+ ),
197
+ None,
198
+ )
199
+ return restored
200
+
201
+ @property
202
+ def harness_spec(self) -> HarnessSpec:
203
+ return self._spec
204
+
205
+ async def preflight(self) -> None:
206
+ await self._ensure_compiled()
207
+
208
+ async def start(self, request: StartRequest) -> RunHandle:
209
+ compiled = await self._ensure_compiled()
210
+ conversation = request.conversation_preprocessing()
211
+ metadata = dict(request.metadata)
212
+ # 回合级审批档位(composer 完全访问/严格/询问)放在 config 里,
213
+ # 挪进 metadata 让 policy_runtime.configure_run 能按它调整审批面。
214
+ approval_mode = str((request.config or {}).get("tool_approval_mode") or "")
215
+ if approval_mode:
216
+ metadata["tool_approval_mode"] = approval_mode
217
+ if conversation is not None and conversation.messages:
218
+ metadata["conversation_history"] = [dict(item) for item in conversation.messages]
219
+ # Studio 的 Agent 合同给出 max_input_tokens + reserve_output_tokens,
220
+ # ContextEngine 需要完整窗口才能避免退回 32K 安全默认值。该值只作为
221
+ # 本次运行的模型窗口来源,不改变不可变 HarnessSpec。
222
+ if not metadata.get("context_window_tokens"):
223
+ max_input = _positive_int(request.config.get("max_input_tokens"))
224
+ reserve_output = _positive_int(request.config.get("reserve_output_tokens")) or 0
225
+ if max_input is not None:
226
+ metadata["context_window_tokens"] = max_input + reserve_output
227
+ internal_request = request.model_copy(update={"metadata": metadata})
228
+ options = await self._policy_options(internal_request)
229
+ # 始终把请求传给 configure_run:回合级 tool_approval_mode 在那里
230
+ # 覆盖静态审批面(execution_policy_request 仅在有 policy 时传)。
231
+ options.setdefault("execution_policy_request", internal_request)
232
+ internal = await self._engine.start(internal_request, compiled, **options)
233
+ external = internal.model_copy(update={"runtime_type": "harness"})
234
+ self._external_handles[external.run_id] = internal
235
+ self._persist_durable_handle(external)
236
+ return external
237
+
238
+ def stream(self, handle: RunHandle) -> AsyncIterator[Any]:
239
+ return self._stream(handle)
240
+
241
+ async def _stream(self, handle: RunHandle) -> AsyncIterator[Any]:
242
+ internal = self._internal_handle(handle)
243
+ async for event in self._engine.stream(internal):
244
+ rich = event.to_v2()
245
+ if not rich.parent_run_id:
246
+ terminal_status = {
247
+ EventType.RUN_COMPLETED: "completed",
248
+ EventType.RUN_FAILED: "failed",
249
+ EventType.RUN_CANCELED: "canceled",
250
+ }.get(rich.event_type)
251
+ if terminal_status is not None:
252
+ # A terminal checkpoint must not remain eligible for cold
253
+ # attach. Persist before yielding so a consumer that stops
254
+ # at the terminal event cannot leave a stale live handle.
255
+ self._persist_durable_handle(
256
+ handle,
257
+ terminal_status,
258
+ terminal=True,
259
+ )
260
+ for projected in _project_event(event):
261
+ yield projected
262
+
263
+ async def cancel(self, handle: RunHandle) -> CancelResult:
264
+ result = await self._engine.cancel(self._internal_handle(handle))
265
+ if result is CancelResult.INTERRUPTED_ACTIVE_TURN:
266
+ self._persist_durable_handle(handle, "canceled", terminal=True)
267
+ elif result is CancelResult.PENDING_CANCEL_RECORDED:
268
+ self._persist_durable_handle(handle, "cancel_requested")
269
+ return result
270
+
271
+ async def resume(
272
+ self,
273
+ handle: RunHandle,
274
+ target: ResumeTarget,
275
+ payload: ResumePayload | None,
276
+ ) -> RunHandle:
277
+ if payload is not None and payload.kind == "approval_decision":
278
+ decision = payload.data
279
+ if isinstance(decision, dict):
280
+ decision = decision.get("decision")
281
+ # Studio submits action-shaped data; the loop consumes a decision
282
+ # string. Unknown/missing decisions never become an approval.
283
+ normalized = {
284
+ "approve": "approved",
285
+ "approved": "approved",
286
+ "reject": "denied",
287
+ "rejected": "denied",
288
+ "deny": "denied",
289
+ "denied": "denied",
290
+ "cancel": "denied",
291
+ "canceled": "denied",
292
+ }.get(decision if isinstance(decision, str) else "", "denied")
293
+ payload = payload.model_copy(update={"data": normalized})
294
+ internal = await self._engine.resume(self._internal_handle(handle), target, payload)
295
+ external = internal.model_copy(update={"runtime_type": "harness"})
296
+ self._external_handles[external.run_id] = internal
297
+ return external
298
+
299
+ async def checkpoint(self, handle: RunHandle) -> CheckpointDescriptor:
300
+ internal = self._internal_handle(handle)
301
+ state = await self._engine.snapshot_state(internal)
302
+ return CheckpointDescriptor(
303
+ checkpoint_id=str(internal.native_ref.get("thread_id") or internal.run_id),
304
+ invocation_id=internal.run_id,
305
+ capability=CheckpointCapability(
306
+ supported=True,
307
+ granularity="snapshot",
308
+ rollback_scope="invocation",
309
+ fork_supported=False,
310
+ durable=self._durable,
311
+ shared_across_pods=self._shared_across_pods,
312
+ reason=(
313
+ "Managed Harness uses a durable LangGraph checkpointer"
314
+ if self._durable
315
+ else "Managed Harness uses an in-process LangGraph checkpointer"
316
+ ),
317
+ ),
318
+ ref={"status": state.status.value if state is not None else "unknown"},
319
+ )
320
+
321
+ async def close(self, handle: RunHandle) -> None:
322
+ internal = self._external_handles.pop(handle.run_id, None)
323
+ if internal is not None:
324
+ await self._engine.close(internal)
325
+
326
+ def is_handle_attached(self, handle: RunHandle) -> bool:
327
+ internal = self._external_handles.get(handle.run_id)
328
+ return internal is not None and self._engine.is_handle_attached(internal)
329
+
330
+ async def _ensure_compiled(self) -> Any:
331
+ if self._compiled is None:
332
+ self._compiled = await self._engine.compile(self._spec)
333
+ return self._compiled
334
+
335
+ def _internal_handle(self, handle: RunHandle) -> RunHandle:
336
+ if handle.runtime_type != "harness":
337
+ raise ValueError(f"managed Harness cannot use {handle.runtime_type!r} handle")
338
+ try:
339
+ return self._external_handles[handle.run_id]
340
+ except KeyError:
341
+ raise KeyError(f"unknown managed Harness run: {handle.run_id}") from None
342
+
343
+
344
+ def _project_event(event: HarnessEvent) -> list[Any]:
345
+ """Project one rich Harness event to one or more canonical v2 events."""
346
+
347
+ rich = event.to_v2()
348
+ native_run_id = str(rich.run_id or rich.invocation_id)
349
+ run_id = str(rich.invocation_id if rich.parent_run_id else native_run_id)
350
+ scope_id = stable_scope_id("ksadk", native_run_id, str(rich.scope_id or rich.agent_id))
351
+ source = SourceRef(
352
+ framework="ksadk",
353
+ native_event_id=rich.event_id,
354
+ native_run_id=native_run_id,
355
+ metadata={
356
+ "native_event_type": rich.event_type,
357
+ "agent_id": rich.agent_id,
358
+ "session_id": rich.session_id,
359
+ **({"phase": rich.phase} if rich.phase else {}),
360
+ **({"parent_run_id": rich.parent_run_id} if rich.parent_run_id else {}),
361
+ },
362
+ )
363
+
364
+ def envelope(event_type: str, item_id: str, part_id: str, ordinal: int = 0) -> dict[str, Any]:
365
+ return {
366
+ "schema_version": 2,
367
+ "event_id": stable_event_id(
368
+ "ksadk", scope_id, item_id, event_type, part_id, rich.event_id, ordinal
369
+ ),
370
+ "seq": rich.seq_id * 10 + ordinal,
371
+ "timestamp": rich.timestamp,
372
+ "run_id": run_id,
373
+ "scope_id": scope_id,
374
+ "parent_scope_id": (
375
+ stable_scope_id("ksadk", run_id, rich.parent_scope_id)
376
+ if rich.parent_scope_id
377
+ else None
378
+ ),
379
+ "source": source,
380
+ }
381
+
382
+ def status_projection(details: dict[str, Any] | None = None) -> list[Any]:
383
+ """Keep internal evidence in the canonical trace, not the chat timeline."""
384
+ item_id = stable_item_id("ksadk", run_id, "status", rich.event_id)
385
+ part_id = "status-0"
386
+ text = json.dumps(
387
+ {"event": rich.event_type, "details": rich.payload if details is None else details},
388
+ ensure_ascii=False,
389
+ separators=(",", ":"),
390
+ default=str,
391
+ )
392
+ snapshot = ContentSnapshot(parts=(TextContent(part_id=part_id, text=text),))
393
+ return [
394
+ ItemCompleted(
395
+ **envelope("item.completed", item_id, part_id),
396
+ item_id=item_id,
397
+ item_kind="status",
398
+ snapshot=snapshot,
399
+ )
400
+ ]
401
+
402
+ run_item = stable_item_id("ksadk", run_id, "$run")
403
+ payload = rich.payload
404
+ if rich.parent_run_id and rich.event_type in {
405
+ EventType.RUN_STARTED, EventType.RUN_COMPLETED, EventType.RUN_FAILED,
406
+ EventType.RUN_CANCELED, EventType.RUN_INTERRUPTED, EventType.APPROVAL_REQUESTED,
407
+ EventType.TEXT_DELTA, EventType.TEXT_COMPLETED, EventType.REASONING_DELTA,
408
+ EventType.MODEL_CALL_FAILED,
409
+ }:
410
+ return status_projection()
411
+ if rich.event_type == EventType.RUN_STARTED:
412
+ return [RunStarted(**envelope("run.started", run_item, "run"), status="running")]
413
+ if rich.event_type == EventType.RUN_COMPLETED:
414
+ message_id = stable_item_id("ksadk", run_id, "message", "final")
415
+ return [
416
+ RunCompleted(
417
+ **envelope("run.completed", run_item, "run"),
418
+ status="completed",
419
+ output_refs=(OutputRef(scope_id=scope_id, item_id=message_id),),
420
+ )
421
+ ]
422
+ if rich.event_type == EventType.RUN_FAILED:
423
+ return [
424
+ RunFailed(
425
+ **envelope("run.failed", run_item, "run"),
426
+ status="failed",
427
+ error=ErrorInfo(
428
+ code="HARNESS_EXECUTION_FAILED",
429
+ message=str(payload.get("error") or "Managed Harness run failed"),
430
+ source="ksadk.harness.managed",
431
+ scope_id=scope_id,
432
+ ),
433
+ )
434
+ ]
435
+ if rich.event_type == EventType.RUN_CANCELED:
436
+ return [
437
+ RunCanceled(
438
+ **envelope("run.canceled", run_item, "run"),
439
+ status="canceled",
440
+ reason=str(payload.get("reason") or payload.get("status") or "canceled"),
441
+ )
442
+ ]
443
+ if rich.event_type == EventType.RUN_INTERRUPTED:
444
+ return [
445
+ RunInterrupted(
446
+ **envelope("run.interrupted", run_item, "run"),
447
+ status="interrupted",
448
+ reason=str(payload.get("reason") or "harness_interrupted"),
449
+ interaction_id=(
450
+ str(payload.get("approval_id") or f"ap-{run_id}")
451
+ if payload.get("reason") == "tool_approval"
452
+ else None
453
+ ),
454
+ )
455
+ ]
456
+ # Provider reasoning is retained as trace evidence but is not a stable or
457
+ # user-oriented progress contract. Exposing every model turn creates noisy
458
+ # "thought" cards and may reveal private reasoning. Chat progress comes
459
+ # exclusively from the compact RUN_PROGRESS events below.
460
+ if rich.event_type in {EventType.REASONING_DELTA, EventType.REASONING_COMPLETED}:
461
+ return status_projection()
462
+ # Public commentary is rendered by Studio's chronological activity
463
+ # projection. Keeping it as a canonical status fact prevents the shared
464
+ # chat reducer from concatenating every checkpoint into the final answer.
465
+ # The final-answer text remains a normal message item below.
466
+ if rich.event_type == EventType.TEXT_COMPLETED and rich.phase == "commentary":
467
+ return status_projection({"text": str(payload.get("text") or "")})
468
+ if rich.event_type == EventType.MODEL_CALL_FAILED:
469
+ if payload.get("action") != "retry_same_model":
470
+ return status_projection()
471
+ return _public_activity_items(
472
+ rich=rich,
473
+ run_id=run_id,
474
+ scope_id=scope_id,
475
+ source=source,
476
+ envelope=envelope,
477
+ key=f"provider-retry-{payload.get('attempt') or rich.event_id}",
478
+ summary=_provider_retry_text(payload),
479
+ completed=True,
480
+ )
481
+ # A child Run's text is an input to the parent, not a second assistant
482
+ # answer. Keep it inspectable without rendering it in the parent chat.
483
+ if rich.parent_scope_id and rich.event_type in {
484
+ EventType.TEXT_DELTA,
485
+ EventType.TEXT_COMPLETED,
486
+ }:
487
+ return status_projection()
488
+ if rich.event_type == EventType.RUN_PROGRESS:
489
+ # Child lifecycle transitions remain available in Trace, but showing
490
+ # accepted/running/completed as separate chat rows duplicates the
491
+ # aggregate delegation card and makes parallel work unreadable.
492
+ if payload.get("kind") in {"delegation.route", "subagent.event"}:
493
+ return status_projection()
494
+ kind = str(payload.get("kind") or "")
495
+ if kind == "provider.retry":
496
+ return _public_activity_items(
497
+ rich=rich,
498
+ run_id=run_id,
499
+ scope_id=scope_id,
500
+ source=source,
501
+ envelope=envelope,
502
+ key=f"provider-retry-{rich.event_id}",
503
+ summary=_provider_retry_text(payload),
504
+ completed=True,
505
+ )
506
+ if kind == "delegation.batch":
507
+ status = str(payload.get("status") or "running")
508
+ # One quiet line stays visible; responsibility details live in an
509
+ # expandable reasoning-style card. The content is a public
510
+ # activity summary, never provider chain-of-thought.
511
+ summary = _delegation_summary(payload)
512
+ detail = _delegation_detail(payload)
513
+ return [
514
+ *_public_activity_items(
515
+ rich=rich,
516
+ run_id=run_id,
517
+ scope_id=scope_id,
518
+ source=source,
519
+ envelope=envelope,
520
+ key="delegation-summary",
521
+ summary=summary,
522
+ completed=status != "running",
523
+ existing=status != "running",
524
+ ),
525
+ *_public_activity_items(
526
+ rich=rich,
527
+ run_id=run_id,
528
+ scope_id=scope_id,
529
+ source=source,
530
+ envelope=envelope,
531
+ key="delegation-detail",
532
+ summary=detail,
533
+ completed=status != "running",
534
+ item_kind="reasoning",
535
+ existing=status != "running",
536
+ ),
537
+ ]
538
+ progress_completed = str(payload.get("status") or "running") != "running"
539
+ progress_key = (
540
+ f"tool-activity-{payload.get('batch_id') or rich.event_id}"
541
+ if kind == "tool.batch"
542
+ else rich.event_id
543
+ )
544
+ return _public_activity_items(
545
+ rich=rich,
546
+ run_id=run_id,
547
+ scope_id=scope_id,
548
+ source=source,
549
+ envelope=envelope,
550
+ key=progress_key,
551
+ summary=_progress_text(payload),
552
+ completed=progress_completed,
553
+ existing=kind == "tool.batch" and progress_completed,
554
+ )
555
+ if rich.event_type == EventType.USAGE_REPORTED:
556
+ input_tokens = max(0, int(payload.get("input_tokens") or 0))
557
+ output_tokens = max(0, int(payload.get("output_tokens") or 0))
558
+ return [
559
+ UsageReported(
560
+ **envelope("usage.reported", run_item, "usage"),
561
+ input_tokens=input_tokens,
562
+ output_tokens=output_tokens,
563
+ total_tokens=input_tokens + output_tokens,
564
+ cached_tokens=max(0, int(payload.get("cached_tokens") or 0)),
565
+ reasoning_tokens=max(0, int(payload.get("reasoning_tokens") or 0)),
566
+ )
567
+ ]
568
+ if rich.event_type == EventType.APPROVAL_REQUESTED:
569
+ interaction_id = str(payload.get("approval_id") or f"ap-{run_id}")
570
+ return [
571
+ InteractionRequested(
572
+ **envelope("interaction.requested", interaction_id, "approval"),
573
+ interaction_id=interaction_id,
574
+ interaction_kind="approval",
575
+ request=ApprovalRequest(
576
+ call_id=str(payload.get("call_id") or "") or None,
577
+ kind=str(payload.get("kind") or "tool"),
578
+ detail=_public_approval_detail(payload.get("detail")),
579
+ ),
580
+ )
581
+ ]
582
+ if rich.event_type in {EventType.TEXT_COMPLETED, EventType.REASONING_COMPLETED}:
583
+ kind = "message" if rich.event_type == EventType.TEXT_COMPLETED else "reasoning"
584
+ phase = str(rich.phase or ("final_answer" if kind == "message" else "commentary"))
585
+ item_id = (
586
+ stable_item_id("ksadk", run_id, "message", "final")
587
+ if kind == "message" and phase == "final_answer"
588
+ else stable_item_id("ksadk", run_id, kind, rich.event_id)
589
+ )
590
+ part_id = "text-0"
591
+ text = str(payload.get("text") or payload.get("summary") or "")
592
+ content = ContentSnapshot(parts=(TextContent(part_id=part_id, text=text),))
593
+ if payload.get("streamed"):
594
+ return [
595
+ ItemCompleted(
596
+ **envelope("item.completed", item_id, part_id, 1),
597
+ item_id=item_id,
598
+ item_kind=kind,
599
+ snapshot=content,
600
+ )
601
+ ]
602
+ return [
603
+ ItemStarted(
604
+ **envelope("item.started", item_id, part_id, 0),
605
+ item_id=item_id,
606
+ item_kind=kind,
607
+ phase=phase,
608
+ initial=None,
609
+ ),
610
+ ItemCompleted(
611
+ **envelope("item.completed", item_id, part_id, 1),
612
+ item_id=item_id,
613
+ item_kind=kind,
614
+ snapshot=content,
615
+ ),
616
+ ]
617
+ if rich.event_type in {EventType.TEXT_DELTA, EventType.REASONING_DELTA}:
618
+ kind = "message" if rich.event_type == EventType.TEXT_DELTA else "reasoning"
619
+ phase = str(rich.phase or ("final_answer" if kind == "message" else "commentary"))
620
+ item_id = (
621
+ stable_item_id("ksadk", native_run_id, "message", "final")
622
+ if kind == "message" and phase == "final_answer"
623
+ else stable_item_id("ksadk", run_id, kind, "stream")
624
+ )
625
+ part_id = "text-0"
626
+ text = str(payload.get("text") or "")
627
+ update = TextContent(part_id=part_id, text=text)
628
+ if int(payload.get("delta_index") or 0) == 0:
629
+ return [
630
+ ItemStarted(
631
+ **envelope("item.started", item_id, part_id, 0),
632
+ item_id=item_id,
633
+ item_kind=kind,
634
+ phase=phase,
635
+ initial=ContentSnapshot(parts=(update,)),
636
+ )
637
+ ]
638
+ return [
639
+ ItemUpdated(
640
+ **envelope("item.updated", item_id, part_id, int(payload.get("delta_index") or 0)),
641
+ item_id=item_id,
642
+ item_kind=kind,
643
+ op="append",
644
+ update=update,
645
+ )
646
+ ]
647
+ if rich.event_type in {EventType.TOOL_CALL_BEGIN, EventType.TOOL_CALL_END}:
648
+ # Arguments, results and receipts remain in the canonical Trace. The
649
+ # conversation receives the corresponding human-readable tool.batch
650
+ # progress item, avoiding duplicate technical cards and configuration-
651
+ # shaped payloads in the user-facing activity stream.
652
+ action = tool_public_action(payload)
653
+ return status_projection(
654
+ {
655
+ "name": str(payload.get("name") or "tool"),
656
+ "call_id": str(payload.get("call_id") or rich.event_id),
657
+ **({"public_action": action} if action else {}),
658
+ "status": (
659
+ "started"
660
+ if rich.event_type == EventType.TOOL_CALL_BEGIN
661
+ else "failed" if payload.get("error") else "completed"
662
+ ),
663
+ }
664
+ )
665
+
666
+ # Preserve the rich execution tree as canonical status items. Studio can
667
+ # render these in the existing Trace inspector without a Harness-only page.
668
+ return status_projection()
669
+
670
+
671
+ def _public_activity_items(
672
+ *,
673
+ rich: Any,
674
+ run_id: str,
675
+ scope_id: str,
676
+ source: Any,
677
+ envelope: Any,
678
+ key: str,
679
+ summary: str,
680
+ completed: bool,
681
+ item_kind: str = "message",
682
+ existing: bool = False,
683
+ ) -> list[Any]:
684
+ """Build one identity-stable, replaceable public activity item."""
685
+ del rich, scope_id, source
686
+ item_id = stable_item_id("ksadk", run_id, item_kind, f"activity-{key}")
687
+ part_id = "text-0"
688
+ snapshot = ContentSnapshot(parts=(TextContent(part_id=part_id, text=summary),))
689
+ events: list[Any] = []
690
+ if not existing:
691
+ events.append(ItemStarted(
692
+ **envelope("item.started", item_id, part_id, 0),
693
+ item_id=item_id,
694
+ item_kind=item_kind,
695
+ phase="commentary",
696
+ initial=snapshot,
697
+ ))
698
+ events.append(
699
+ ItemUpdated(
700
+ **envelope("item.updated", item_id, part_id, 1),
701
+ item_id=item_id,
702
+ item_kind=item_kind,
703
+ op="replace",
704
+ update=TextContent(part_id=part_id, text=summary),
705
+ )
706
+ )
707
+ if completed:
708
+ events.append(
709
+ ItemCompleted(
710
+ **envelope("item.completed", item_id, part_id, 2),
711
+ item_id=item_id,
712
+ item_kind=item_kind,
713
+ snapshot=snapshot,
714
+ )
715
+ )
716
+ return events
717
+
718
+
719
+ def _progress_text(payload: dict[str, Any]) -> str:
720
+ """Render public execution progress without exposing private chain-of-thought."""
721
+ kind = str(payload.get("kind") or "progress")
722
+ if kind == "plan":
723
+ return f"计划:{_compact_progress_message(payload.get('message'))}"
724
+ if kind == "delegation.batch":
725
+ return _delegation_summary(payload)
726
+ if kind == "tool.batch":
727
+ status = str(payload.get("status") or "running")
728
+ tools = [str(name) for name in payload.get("tools") or []]
729
+ action = _tool_activity_label(tools)
730
+ if status == "failed":
731
+ return f"{action}时遇到问题,正在调整"
732
+ if status == "completed":
733
+ return f"已{action}"
734
+ return f"正在{action}"
735
+ if kind == "provider.retry":
736
+ return _provider_retry_text(payload)
737
+ if kind == "delegation.route":
738
+ provider = "Codex" if "codex" in str(payload.get("provider_ref") or "") else "Harness"
739
+ return f"子任务「{payload.get('label') or '未命名'}」已分派给 {provider}。"
740
+ if kind == "subagent.event":
741
+ status = str(payload.get("status") or "in_progress")
742
+ status_text = {
743
+ "accepted": "等待执行",
744
+ "running": "正在执行",
745
+ "succeeded": "已完成",
746
+ "failed": "执行失败",
747
+ "cancelled": "已取消",
748
+ "interrupted": "已中断",
749
+ }.get(status, status)
750
+ return f"子任务「{payload.get('label') or '未命名'}」:{status_text}。"
751
+ action = str(payload.get("action") or payload.get("status") or "in_progress")
752
+ return f"执行进度:{action}"
753
+
754
+
755
+ def _delegation_summary(payload: dict[str, Any]) -> str:
756
+ count = max(1, int(payload.get("count") or 1))
757
+ status = str(payload.get("status") or "running")
758
+ if status == "failed":
759
+ return f"{count} 个子智能体已结束,部分任务需要调整"
760
+ if status == "completed":
761
+ return f"{count} 个子智能体已完成,正在整理结果"
762
+ return f"{count} 个子智能体正在运行"
763
+
764
+
765
+ def _delegation_detail(payload: dict[str, Any]) -> str:
766
+ status = str(payload.get("status") or "running")
767
+ labels = [
768
+ str(label).strip() for label in (payload.get("labels") or []) if str(label).strip()
769
+ ]
770
+ marker = "已完成" if status == "completed" else "需要调整" if status == "failed" else "正在运行"
771
+ if not labels:
772
+ return marker
773
+ return "\n".join(f"• {marker}:{label}" for label in labels[:6])
774
+
775
+
776
+ def _provider_retry_text(payload: dict[str, Any]) -> str:
777
+ if payload.get("next_attempt") is not None:
778
+ attempt = max(2, int(payload["next_attempt"]))
779
+ else:
780
+ attempt = max(2, int(payload.get("model_attempt") or 1) + 1)
781
+ maximum = max(attempt, int(payload.get("max_attempts") or 10))
782
+ delay_ms = max(0, int(payload.get("delay_ms") or payload.get("retry_delay_ms") or 0))
783
+ wait = f",{delay_ms / 1000:g} 秒后" if delay_ms else ""
784
+ label = str(payload.get("label") or "").strip()
785
+ scope = f"({label})" if label else ""
786
+ return f"模型服务繁忙{scope}{wait}自动重试(第 {attempt}/{maximum} 次)"
787
+
788
+
789
+ def _public_approval_detail(value: Any) -> dict[str, Any]:
790
+ """Keep approvals actionable without copying document bodies or secrets into chat."""
791
+ detail = dict(value) if isinstance(value, dict) else {}
792
+ arguments = detail.get("arguments") or detail.get("args")
793
+ safe_arguments: dict[str, str] = {}
794
+ if isinstance(arguments, dict):
795
+ for key in ("path", "file_path", "url", "command"):
796
+ raw = arguments.get(key)
797
+ if raw is not None:
798
+ safe_arguments[key] = _compact_progress_message(raw, max_chars=160)
799
+ public: dict[str, Any] = {
800
+ "name": str(detail.get("name") or detail.get("tool_name") or "tool"),
801
+ }
802
+ if safe_arguments:
803
+ public["args"] = safe_arguments
804
+ return public
805
+
806
+
807
+ def _tool_activity_label(tools: list[str]) -> str:
808
+ lowered = " ".join(tools).lower()
809
+ if "write" in lowered or "edit" in lowered or "save" in lowered:
810
+ return "编辑并保存结果"
811
+ if "web_search" in lowered or "search" in lowered:
812
+ return "搜索资料"
813
+ if "web_fetch" in lowered or "fetch" in lowered:
814
+ return "查看资料"
815
+ if "read" in lowered or "list" in lowered:
816
+ return "查看工作区内容"
817
+ if "command" in lowered or "shell" in lowered or "exec" in lowered:
818
+ return "运行任务"
819
+ return "使用工具处理任务"
820
+
821
+
822
+ def _compact_progress_message(value: Any, *, max_chars: int = 120) -> str:
823
+ """Keep only the first useful plan lines for the conversational surface."""
824
+ lines = [line.strip(" -\t") for line in str(value or "计划已生成").splitlines()]
825
+ text = ";".join(line for line in lines if line) or "计划已生成"
826
+ if len(text) <= max_chars:
827
+ return text
828
+ return text[: max_chars - 1].rstrip(";,。 ") + "…"
829
+
830
+
831
+ def _compact_responsibilities(labels: list[str], *, max_items: int = 4) -> str:
832
+ if not labels:
833
+ return ""
834
+ visible = labels[:max_items]
835
+ lines = [f"• {label}" for label in visible]
836
+ if len(labels) > max_items:
837
+ lines.append(f"• 另有 {len(labels) - max_items} 项")
838
+ return "\n" + "\n".join(lines)
839
+
840
+
841
+ def _positive_int(value: Any) -> int | None:
842
+ try:
843
+ parsed = int(value)
844
+ except (TypeError, ValueError):
845
+ return None
846
+ return parsed if parsed > 0 else None
847
+
848
+
849
+ def managed_harness_capabilities(
850
+ *, durable: bool, execution_policy: bool = False
851
+ ) -> RuntimeCapabilityMatrix:
852
+ """Return the canonical control matrix for one concrete assembly tier."""
853
+
854
+ def available() -> RuntimeCapability:
855
+ return RuntimeCapability(supported=True, mode="native")
856
+
857
+ def unavailable(reason: str) -> RuntimeCapability:
858
+ return RuntimeCapability(supported=False, mode="unavailable", reason=reason)
859
+
860
+ durable_capability = (
861
+ available() if durable else unavailable("managed_harness_checkpoint_is_process_local")
862
+ )
863
+ return RuntimeCapabilityMatrix(
864
+ cancel=available(),
865
+ pause=unavailable("managed_harness_pause_not_implemented"),
866
+ resume=available(),
867
+ submit_interaction=durable_capability,
868
+ attach=durable_capability,
869
+ steer=unavailable("runtime_no_native_steer"),
870
+ inject=unavailable("runtime_no_native_inject"),
871
+ checkpoint=available(),
872
+ durable_restore=durable_capability,
873
+ interaction_mode="durable_resume" if durable else "unavailable",
874
+ execution_policy=(
875
+ available() if execution_policy else unavailable("managed_harness_no_host_resolver")
876
+ ),
877
+ )
878
+
879
+
880
+ __all__ = [
881
+ "ManagedHarnessRuntime",
882
+ "ManagedHarnessRuntimeAdapter",
883
+ "managed_harness_capabilities",
884
+ ]