agentengine-sdk-python 0.8.3__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 (819) hide show
  1. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +13 -9
  2. agentengine_sdk_python-0.8.5.dist-info/RECORD +1296 -0
  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 +111 -91
  8. ksadk/builders/code_builder.py +74 -21
  9. ksadk/builders/framework_requirements.py +22 -3
  10. ksadk/builders/ks3_uploader.py +36 -7
  11. ksadk/builders/managed_runtime_builder.py +1 -0
  12. ksadk/cli/__init__.py +68 -3
  13. ksadk/cli/cmd_config.py +4 -4
  14. ksadk/cli/cmd_create.py +12 -12
  15. ksadk/cli/cmd_hermes.py +24 -2
  16. ksadk/cli/cmd_invoke.py +28 -5
  17. ksadk/cli/cmd_managed_runtime.py +13 -1
  18. ksadk/cli/cmd_openclaw.py +26 -1
  19. ksadk/cli/cmd_plugin.py +76 -13
  20. ksadk/cli/cmd_studio.py +64 -16
  21. ksadk/cli/cmd_web.py +2 -5
  22. ksadk/cli/openclaw_env.py +1 -1
  23. ksadk/cli/resource_common.py +26 -0
  24. ksadk/cli/runtime_bootstrap.py +23 -1
  25. ksadk/codex/client.py +425 -96
  26. ksadk/codex/projection.py +24 -0
  27. ksadk/codex/runtime.py +56 -298
  28. ksadk/common/auth.py +16 -10
  29. ksadk/configs/__init__.py +1 -1
  30. ksadk/configs/env_registry.py +153 -31
  31. ksadk/configs/env_registry_studio.py +86 -0
  32. ksadk/configs/global_config.py +1 -1
  33. ksadk/configs/settings.py +3 -3
  34. ksadk/connector/__init__.py +17 -0
  35. ksadk/connector/channel.py +477 -0
  36. ksadk/context_engine/capabilities.py +52 -4
  37. ksadk/conversations/attachment_storage.py +10 -3
  38. ksadk/conversations/attachments.py +16 -5
  39. ksadk/conversations/message_projection.py +133 -21
  40. ksadk/conversations/normalize.py +28 -10
  41. ksadk/conversations/projector.py +4 -6
  42. ksadk/conversations/runtime_baseline.py +37 -0
  43. ksadk/conversations/runtime_invocation.py +22 -4
  44. ksadk/conversations/runtime_observability.py +39 -10
  45. ksadk/conversations/runtime_payloads.py +9 -0
  46. ksadk/conversations/runtime_persistence.py +105 -9
  47. ksadk/conversations/runtime_preparation.py +42 -33
  48. ksadk/conversations/runtime_resume.py +50 -2
  49. ksadk/conversations/runtime_stream_events.py +34 -35
  50. ksadk/conversations/runtime_streaming.py +33 -7
  51. ksadk/deployment/env_forward.py +2 -2
  52. ksadk/deployment/providers/serverless.py +1 -1
  53. ksadk/events/adapters/_codex_items.py +16 -8
  54. ksadk/events/adapters/_codex_validators.py +18 -7
  55. ksadk/events/adapters/_langgraph_support.py +34 -0
  56. ksadk/events/adapters/langgraph.py +15 -1
  57. ksadk/events/canonical_store.py +3 -1
  58. ksadk/events/projections.py +1 -1
  59. ksadk/events/session_event.py +2 -2
  60. ksadk/harness/__init__.py +14 -0
  61. ksadk/harness/app.py +11 -0
  62. ksadk/harness/artifact_store.py +213 -0
  63. ksadk/harness/capabilities.py +115 -0
  64. ksadk/harness/capability_runtime.py +237 -0
  65. ksadk/harness/closure_contract.py +92 -0
  66. ksadk/harness/compaction_record.py +122 -0
  67. ksadk/harness/compiler.py +284 -0
  68. ksadk/harness/config.py +2 -2
  69. ksadk/harness/conformance/__init__.py +33 -0
  70. ksadk/harness/conformance/contract.py +506 -0
  71. ksadk/harness/conformance/fixtures.py +102 -0
  72. ksadk/harness/context_engine.py +403 -0
  73. ksadk/harness/context_maintenance.py +259 -0
  74. ksadk/harness/context_manifest.py +188 -0
  75. ksadk/harness/context_tuning.py +168 -0
  76. ksadk/harness/draft_runtime.py +322 -0
  77. ksadk/harness/engine/__init__.py +40 -0
  78. ksadk/harness/engine/base.py +122 -0
  79. ksadk/harness/engine/budgets.py +108 -0
  80. ksadk/harness/engine/capability_declarations.py +59 -0
  81. ksadk/harness/engine/completion_guard.py +42 -0
  82. ksadk/harness/engine/context_pipeline.py +579 -0
  83. ksadk/harness/engine/graph_builder.py +859 -0
  84. ksadk/harness/engine/langgraph.py +931 -0
  85. ksadk/harness/engine/mcp_disclosure.py +750 -0
  86. ksadk/harness/engine/policy_runtime.py +70 -0
  87. ksadk/harness/engine/postgres_checkpointer.py +63 -0
  88. ksadk/harness/engine/run_control_bridge.py +80 -0
  89. ksadk/harness/engine/run_types.py +88 -0
  90. ksadk/harness/engine/skill_disclosure.py +189 -0
  91. ksadk/harness/engine/spans.py +41 -0
  92. ksadk/harness/engine/subagents.py +343 -0
  93. ksadk/harness/engine/thread_ids.py +112 -0
  94. ksadk/harness/engine/tool_dispatch.py +144 -0
  95. ksadk/harness/event_tree.py +212 -0
  96. ksadk/harness/events.py +461 -0
  97. ksadk/harness/execution_policy.py +94 -0
  98. ksadk/harness/insights.py +210 -0
  99. ksadk/harness/lifecycle.py +578 -0
  100. ksadk/harness/lifecycle_conformance.py +233 -0
  101. ksadk/harness/lifecycle_local_plane.py +104 -0
  102. ksadk/harness/loop/__init__.py +44 -0
  103. ksadk/harness/loop/reason.py +454 -0
  104. ksadk/harness/loop/tools.py +762 -0
  105. ksadk/harness/managed_runtime.py +884 -0
  106. ksadk/harness/mcp_matrix.py +474 -0
  107. ksadk/harness/mcp_runtime.py +471 -0
  108. ksadk/harness/memory_consolidation.py +157 -0
  109. ksadk/harness/memory_loop.py +156 -0
  110. ksadk/harness/memory_runtime.py +541 -0
  111. ksadk/harness/metrics.py +90 -0
  112. ksadk/harness/model_capability.py +253 -0
  113. ksadk/harness/model_provider.py +220 -0
  114. ksadk/harness/observability/__init__.py +29 -0
  115. ksadk/harness/observability/inspection.py +528 -0
  116. ksadk/harness/observability/metrics.py +167 -0
  117. ksadk/harness/observability/otel_exporter.py +218 -0
  118. ksadk/harness/prompt_cache.py +70 -0
  119. ksadk/harness/public_activity.py +154 -0
  120. ksadk/harness/readiness.py +249 -0
  121. ksadk/harness/reasoner.py +466 -13
  122. ksadk/harness/release_readiness.py +140 -0
  123. ksadk/harness/resource_ref.py +69 -0
  124. ksadk/harness/run_control.py +668 -0
  125. ksadk/harness/runtime.py +171 -136
  126. ksadk/harness/runtime_capabilities.py +158 -0
  127. ksadk/harness/runtime_server.py +514 -0
  128. ksadk/harness/sandbox_adapters.py +739 -0
  129. ksadk/harness/sandbox_backend.py +530 -0
  130. ksadk/harness/sandbox_conformance.py +288 -0
  131. ksadk/harness/sandbox_lease.py +77 -0
  132. ksadk/harness/sandbox_lease_conformance.py +259 -0
  133. ksadk/harness/sandbox_matrix.py +170 -0
  134. ksadk/harness/sandbox_reconciliation.py +140 -0
  135. ksadk/harness/sandbox_recovery.py +586 -0
  136. ksadk/harness/sandbox_recovery_conformance.py +246 -0
  137. ksadk/harness/session_store.py +243 -0
  138. ksadk/harness/skill_composition.py +212 -0
  139. ksadk/harness/skill_feedback.py +123 -0
  140. ksadk/harness/skill_matrix.py +233 -0
  141. ksadk/harness/skill_runtime.py +259 -0
  142. ksadk/harness/spec.py +332 -0
  143. ksadk/harness/state.py +153 -0
  144. ksadk/harness/strategies.py +149 -0
  145. ksadk/harness/subagent.py +253 -0
  146. ksadk/harness/tool_policy.py +131 -0
  147. ksadk/harness/tool_receipts.py +96 -0
  148. ksadk/harness/tool_reliability.py +81 -0
  149. ksadk/harness/tools.py +38 -13
  150. ksadk/harness/user_errors.py +69 -0
  151. ksadk/harness/working_context.py +81 -0
  152. ksadk/harness/working_context_patch.py +99 -0
  153. ksadk/identity/resolver.py +18 -0
  154. ksadk/interaction/__init__.py +1 -1
  155. ksadk/interaction/ledger.py +1 -1
  156. ksadk/interaction/provider.py +2 -1
  157. ksadk/interaction/providers/__init__.py +3 -1
  158. ksadk/interaction/providers/adk.py +1 -1
  159. ksadk/interaction/providers/codex.py +1 -1
  160. ksadk/interaction/providers/harness.py +50 -0
  161. ksadk/interaction/providers/langgraph.py +2 -1
  162. ksadk/kernel/__init__.py +10 -0
  163. ksadk/kernel/approval_presentation.py +91 -0
  164. ksadk/kernel/authorization.py +1 -1
  165. ksadk/kernel/bootstrap.py +114 -106
  166. ksadk/kernel/contract_fingerprints.py +1 -1
  167. ksadk/kernel/contracts.py +5 -0
  168. ksadk/kernel/control.py +32 -1
  169. ksadk/kernel/execution_grants.py +221 -0
  170. ksadk/kernel/execution_grants_memory.py +133 -0
  171. ksadk/kernel/execution_grants_postgres.py +217 -0
  172. ksadk/kernel/execution_grants_sqlite.py +209 -0
  173. ksadk/kernel/ingress.py +42 -29
  174. ksadk/kernel/mapping.py +1 -1
  175. ksadk/kernel/memory_store.py +24 -11
  176. ksadk/kernel/postgres_store.py +63 -33
  177. ksadk/kernel/recovery.py +78 -14
  178. ksadk/kernel/sql/001_agent_kernel.sql +23 -0
  179. ksadk/kernel/sqlite_store.py +331 -25
  180. ksadk/kernel/state.py +2 -3
  181. ksadk/kernel/store.py +72 -2
  182. ksadk/kernel/worker.py +144 -51
  183. ksadk/kernel/worker_history.py +72 -0
  184. ksadk/kernel/worker_identity.py +47 -0
  185. ksadk/knowledge_base/client.py +57 -27
  186. ksadk/mcp_runtime/__init__.py +12 -4
  187. ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
  188. ksadk/memory/adk/resilient_session_service.py +25 -17
  189. ksadk/memory/adk/short_term_memory.py +26 -9
  190. ksadk/memory/coordinator.py +22 -6
  191. ksadk/memory/extraction.py +40 -1
  192. ksadk/memory/models.py +84 -5
  193. ksadk/memory/provider_resolver.py +8 -0
  194. ksadk/memory/providers/local_postgres.py +200 -0
  195. ksadk/memory/providers/local_sqlite.py +42 -3
  196. ksadk/memory/retrieval.py +189 -0
  197. ksadk/memory/store_adapter.py +150 -0
  198. ksadk/model_policy.py +2 -2
  199. ksadk/model_proxy/detect.py +254 -0
  200. ksadk/model_proxy/server.py +14 -7
  201. ksadk/model_proxy/transform.py +40 -2
  202. ksadk/plugins/__init__.py +5 -1
  203. ksadk/plugins/artifacts.py +275 -0
  204. ksadk/plugins/bridges/__init__.py +4 -2
  205. ksadk/plugins/bridges/codex.py +120 -13
  206. ksadk/plugins/bridges/dsh.py +351 -156
  207. ksadk/plugins/builtins.py +72 -35
  208. ksadk/plugins/bundle_security.py +28 -4
  209. ksadk/plugins/codex_manifest.py +983 -0
  210. ksadk/plugins/companion_artifacts.py +83 -0
  211. ksadk/plugins/companions.py +368 -0
  212. ksadk/plugins/composition.py +8 -0
  213. ksadk/plugins/contracts.py +119 -1
  214. ksadk/plugins/delivery.py +153 -0
  215. ksadk/plugins/dsh_channels.py +156 -0
  216. ksadk/plugins/dsh_home.py +140 -0
  217. ksadk/plugins/dsh_installation_digest.py +71 -0
  218. ksadk/plugins/dsh_teams.py +105 -0
  219. ksadk/plugins/dsh_toolchain.py +203 -32
  220. ksadk/plugins/ecosystem_probe.py +6 -6
  221. ksadk/plugins/execution_host.py +99 -0
  222. ksadk/plugins/host.py +102 -39
  223. ksadk/plugins/kernel_adapter.py +205 -0
  224. ksadk/plugins/providers/__init__.py +23 -0
  225. ksadk/plugins/providers/bundles/dsh-channels-client/client.js +19 -0
  226. ksadk/plugins/providers/bundles/dsh-channels-client/cordis.patch.yml +3 -0
  227. ksadk/plugins/providers/bundles/dsh-channels-client/index.mjs +7 -0
  228. ksadk/plugins/providers/bundles/dsh-channels-client/package.json +12 -0
  229. ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
  230. ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
  231. ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
  232. ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
  233. ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
  234. ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
  235. ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
  236. ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
  237. ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
  238. ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
  239. ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
  240. ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
  241. ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
  242. ksadk/plugins/providers/bundles/dsh-teams-client/client.js +29 -0
  243. ksadk/plugins/providers/bundles/dsh-teams-client/cordis.patch.yml +3 -0
  244. ksadk/plugins/providers/bundles/dsh-teams-client/index.mjs +11 -0
  245. ksadk/plugins/providers/bundles/dsh-teams-client/package.json +35 -0
  246. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/cordis.patch.yml +3 -0
  247. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/index.mjs +13 -0
  248. ksadk/plugins/providers/bundles/dsh-teams-leader-policy/package.json +27 -0
  249. ksadk/plugins/providers/bundles/dsh-teams-profile/cordis.patch.yml +3 -0
  250. ksadk/plugins/providers/bundles/dsh-teams-profile/index.mjs +12 -0
  251. ksadk/plugins/providers/bundles/dsh-teams-profile/package.json +26 -0
  252. ksadk/plugins/providers/bundles/dsh-teams-router/cordis.patch.yml +3 -0
  253. ksadk/plugins/providers/bundles/dsh-teams-router/index.mjs +16 -0
  254. ksadk/plugins/providers/bundles/dsh-teams-router/package.json +27 -0
  255. ksadk/plugins/providers/bundles/dsh-teams-tasks/cordis.patch.yml +3 -0
  256. ksadk/plugins/providers/bundles/dsh-teams-tasks/index.mjs +16 -0
  257. ksadk/plugins/providers/bundles/dsh-teams-tasks/package.json +27 -0
  258. ksadk/plugins/providers/bundles/dsh-teams-tools/cordis.patch.yml +3 -0
  259. ksadk/plugins/providers/bundles/dsh-teams-tools/index.mjs +25 -0
  260. ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +29 -0
  261. ksadk/plugins/providers/bundles/dsh-teams-tools/tools.json +235 -0
  262. ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +1 -1
  263. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
  264. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +920 -0
  265. ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
  266. ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/client.mjs +133 -0
  267. ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/index.mjs +14 -0
  268. ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +115 -0
  269. ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +19 -0
  270. ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
  271. ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
  272. ksadk/plugins/providers/codex.py +344 -70
  273. ksadk/plugins/providers/codex_native.py +368 -0
  274. ksadk/plugins/providers/codex_turn.py +301 -0
  275. ksadk/plugins/providers/dsh_capabilities.py +1450 -0
  276. ksadk/plugins/providers/dsh_mcp.py +467 -0
  277. ksadk/plugins/providers/harness.py +294 -141
  278. ksadk/plugins/providers/harness_delegation.py +593 -0
  279. ksadk/plugins/providers/harness_managed.py +456 -0
  280. ksadk/plugins/providers/harness_tools.py +326 -0
  281. ksadk/plugins/providers/mcp_projection.py +150 -0
  282. ksadk/plugins/providers/platform_resources.py +657 -0
  283. ksadk/plugins/providers/shipped_dsh.py +4 -1
  284. ksadk/plugins/resolver.py +8 -1
  285. ksadk/plugins/subagent_providers/codex.py +28 -6
  286. ksadk/plugins/teams/__init__.py +5 -0
  287. ksadk/plugins/teams/api.py +405 -0
  288. ksadk/plugins/teams/application.py +680 -0
  289. ksadk/plugins/teams/artifacts.py +60 -0
  290. ksadk/plugins/teams/context.py +96 -0
  291. ksadk/plugins/teams/contracts.py +136 -0
  292. ksadk/plugins/teams/domain.py +1427 -0
  293. ksadk/plugins/teams/domain_values.py +24 -0
  294. ksadk/plugins/teams/errors.py +13 -0
  295. ksadk/plugins/teams/migration.py +311 -0
  296. ksadk/plugins/teams/migration_cli.py +322 -0
  297. ksadk/plugins/teams/postgres_store.py +138 -0
  298. ksadk/plugins/teams/runtime.py +777 -0
  299. ksadk/plugins/teams/source_projection.py +84 -0
  300. ksadk/plugins/teams/store.py +311 -0
  301. ksadk/plugins/teams/task_decisions.py +423 -0
  302. ksadk/plugins/teams/transport.py +91 -0
  303. ksadk/plugins/teams/workspaces.py +255 -0
  304. ksadk/resource_runtime/__init__.py +4 -0
  305. ksadk/resource_runtime/broker.py +616 -0
  306. ksadk/resource_runtime/build_artifacts.py +165 -0
  307. ksadk/resource_runtime/contracts.py +138 -0
  308. ksadk/resource_runtime/discovery_receipts.py +100 -0
  309. ksadk/resource_runtime/discovery_skills.py +172 -0
  310. ksadk/resource_runtime/errors.py +6 -0
  311. ksadk/resource_runtime/ipc.py +142 -0
  312. ksadk/resource_runtime/kernel_approval.py +165 -0
  313. ksadk/resource_runtime/knowledge.py +114 -0
  314. ksadk/resource_runtime/langgraph.py +94 -0
  315. ksadk/resource_runtime/leases.py +191 -0
  316. ksadk/resource_runtime/managed_projection.py +186 -0
  317. ksadk/resource_runtime/mcp_server.py +138 -0
  318. ksadk/resource_runtime/memory_provider.py +318 -0
  319. ksadk/resource_runtime/memory_receipts.py +34 -0
  320. ksadk/resource_runtime/operation_ledger.py +211 -0
  321. ksadk/resource_runtime/plugin_config.py +48 -0
  322. ksadk/resource_runtime/policy_authorization.py +54 -0
  323. ksadk/resource_runtime/process.py +110 -0
  324. ksadk/resource_runtime/skill_artifacts.py +153 -0
  325. ksadk/resource_runtime/skill_runtime.py +42 -0
  326. ksadk/resource_runtime/skill_workspace.py +118 -0
  327. ksadk/resource_runtime/skills.py +215 -0
  328. ksadk/resource_runtime/snapshots.py +180 -0
  329. ksadk/resource_runtime/socket_server.py +103 -0
  330. ksadk/resource_runtime/supervisor.py +380 -0
  331. ksadk/resource_runtime/worker.py +504 -0
  332. ksadk/runners/_langgraph_runner_streams.py +182 -38
  333. ksadk/runners/_langgraph_state_reader.py +106 -0
  334. ksadk/runners/_session_identity.py +285 -0
  335. ksadk/runners/adk_runner.py +166 -63
  336. ksadk/runners/base_runner.py +29 -1
  337. ksadk/runners/langgraph_runner.py +542 -195
  338. ksadk/runners/patch_langchain.py +47 -0
  339. ksadk/runners/usage_accumulator.py +11 -3
  340. ksadk/runtime/_runner_adapter/stream_mapping.py +194 -20
  341. ksadk/runtime/adapter.py +2 -0
  342. ksadk/runtime/conversation_execution.py +117 -17
  343. ksadk/runtime/executor.py +87 -3
  344. ksadk/runtime/factory.py +65 -274
  345. ksadk/runtime/framework_adapters.py +23 -0
  346. ksadk/runtime/preprocessing.py +21 -5
  347. ksadk/runtime/runner_adapter.py +106 -18
  348. ksadk/runtime/skill_eval_result.py +36 -0
  349. ksadk/runtime/timing.py +46 -0
  350. ksadk/runtime/usage.py +49 -18
  351. ksadk/runtime_context.py +142 -2
  352. ksadk/sandbox/backends/e2b.py +288 -25
  353. ksadk/sandbox/backends/local_process.py +72 -39
  354. ksadk/sandbox/base.py +64 -1
  355. ksadk/sandbox/diagnostics.py +82 -0
  356. ksadk/sandbox/e2b_connection.py +66 -0
  357. ksadk/sandbox/local_controls.py +746 -0
  358. ksadk/sandbox/local_launcher.py +90 -0
  359. ksadk/scheduler/dispatcher.py +1 -1
  360. ksadk/scheduler/sqlite_store.py +18 -0
  361. ksadk/server/composition.py +2 -0
  362. ksadk/server/factory.py +5 -0
  363. ksadk/server/invocation_identity.py +118 -0
  364. ksadk/server/persistence_capability.py +516 -0
  365. ksadk/server/routes/common.py +32 -3
  366. ksadk/server/routes/control.py +271 -52
  367. ksadk/server/routes/dependencies.py +16 -0
  368. ksadk/server/routes/kernel_ingress.py +9 -1
  369. ksadk/server/routes/misc.py +233 -25
  370. ksadk/server/routes/models.py +47 -4
  371. ksadk/server/routes/openai_compat.py +76 -13
  372. ksadk/server/routes/projection.py +252 -12
  373. ksadk/server/routes/run.py +106 -35
  374. ksadk/server/routes/sessions.py +491 -138
  375. ksadk/server/routes/streaming.py +43 -9
  376. ksadk/server/routes/workspace.py +130 -21
  377. ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
  378. ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-DHuAWfr5.js} +10 -7
  379. ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
  380. ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-DeBkbJvI.js} +9 -9
  381. ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
  382. ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
  383. ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-C35w-pn1.js} +1 -1
  384. ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
  385. ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
  386. ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
  387. ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-BCtGGkhN.js} +1 -1
  388. ksadk/server/static/assets/channel-_KDifNys.js +1 -0
  389. ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +1 -0
  390. ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
  391. ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
  392. ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
  393. ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
  394. ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
  395. ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
  396. ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
  397. ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
  398. ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-Bx1jS-X-.js} +1 -1
  399. ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +1 -0
  400. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +1 -0
  401. ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
  402. ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
  403. ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
  404. ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
  405. ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-B7nCawed.js} +1 -1
  406. ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
  407. ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
  408. ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
  409. ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
  410. ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
  411. ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
  412. ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-1nXCdsej.js} +1 -1
  413. ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-2vL2sAdF.js} +1 -1
  414. ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-B3bA05-e.js} +1 -1
  415. ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-BLpRy_Yx.js} +1 -1
  416. ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-BO_UwatH.js} +1 -1
  417. ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-BdNFAney.js} +1 -1
  418. ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-C0J5_3qM.js} +1 -1
  419. ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-CGt_UGeO.js} +1 -1
  420. ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CIRMvUM4.js} +1 -1
  421. ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-CIpWk_5f.js} +1 -1
  422. ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-CPyieXEf.js} +1 -1
  423. ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-D-92S-Fd.js} +1 -1
  424. ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-DNKuMzWc.js} +1 -1
  425. ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-DWfdmz9s.js} +2 -2
  426. ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DppE_r-D.js} +1 -1
  427. ksadk/server/static/assets/{dist-C71CsujO.js → dist-DyG6Ya-z.js} +1 -1
  428. ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-M-SrdhhZ.js} +1 -1
  429. ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-mqD5TZup.js} +1 -1
  430. ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-n3n6t_FO.js} +1 -1
  431. ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-qe8xjesy.js} +1 -1
  432. ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-t6MzE0jU.js} +1 -1
  433. ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
  434. ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-Dpz9_0zn.js} +1 -1
  435. ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +1 -0
  436. ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +1 -0
  437. ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
  438. ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
  439. ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-DcxzRwYC.js} +1 -1
  440. ksadk/server/static/assets/index-BMd2mucF.css +2 -0
  441. ksadk/server/static/assets/index-D5qyyhTH.js +244 -0
  442. ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +1 -0
  443. ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
  444. ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
  445. ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
  446. ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
  447. ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-mtjOi4KM.js} +1 -1
  448. ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-BETqsxE_.js} +1 -1
  449. ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-DPWrvs90.js} +2 -2
  450. ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-CJG2mfBP.js} +1 -1
  451. ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +1 -0
  452. ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
  453. ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
  454. ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
  455. ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-4d78KiEY.js} +1 -1
  456. ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +1 -0
  457. ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +1 -0
  458. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +1 -0
  459. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +1 -0
  460. ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +1 -0
  461. ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
  462. ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
  463. ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
  464. ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
  465. ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
  466. ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
  467. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
  468. ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
  469. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
  470. ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-CMD3x_U_.js} +1 -1
  471. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +1 -0
  472. ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +1 -0
  473. ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
  474. ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
  475. ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
  476. ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
  477. ksadk/server/static/index.html +2 -2
  478. ksadk/server/terminal_sessions.py +34 -2
  479. ksadk/session_context.py +66 -0
  480. ksadk/sessions/__init__.py +11 -21
  481. ksadk/sessions/_local_service_sync.py +263 -1
  482. ksadk/sessions/base.py +176 -0
  483. ksadk/sessions/errors.py +4 -0
  484. ksadk/sessions/in_memory.py +309 -19
  485. ksadk/sessions/invocation_identity.py +235 -0
  486. ksadk/sessions/local_service.py +83 -1
  487. ksadk/sessions/persistence.py +275 -0
  488. ksadk/sessions/postgres_service.py +358 -0
  489. ksadk/sessions/resilience.py +8 -0
  490. ksadk/sessions/resilient.py +362 -4
  491. ksadk/sessions/topology.py +135 -0
  492. ksadk/skills/__init__.py +26 -0
  493. ksadk/skills/events.py +464 -0
  494. ksadk/skills/manifest_cache.py +263 -0
  495. ksadk/skills/mcp_server/__init__.py +0 -0
  496. ksadk/skills/mcp_server/_registry.py +33 -0
  497. ksadk/skills/mcp_server/_routing.py +26 -0
  498. ksadk/skills/mcp_server/_workspace_files.py +160 -0
  499. ksadk/skills/mcp_server/register.py +415 -0
  500. ksadk/skills/mcp_server/server.py +218 -0
  501. ksadk/skills/models.py +37 -4
  502. ksadk/skills/observability.py +132 -0
  503. ksadk/skills/package_store.py +261 -40
  504. ksadk/skills/runtime/agent.py +67 -9
  505. ksadk/skills/runtime/artifact_delivery.py +139 -0
  506. ksadk/skills/runtime/artifacts.py +87 -0
  507. ksadk/skills/runtime/backends/e2b.py +460 -27
  508. ksadk/skills/runtime/backends/local.py +629 -62
  509. ksadk/skills/runtime/base.py +81 -7
  510. ksadk/skills/runtime/executor.py +268 -1
  511. ksadk/skills/runtime/loader.py +118 -5
  512. ksadk/skills/runtime/pinned.py +114 -0
  513. ksadk/skills/runtime/request.py +49 -0
  514. ksadk/skills/service_client.py +167 -28
  515. ksadk/skills/tool_defs.py +108 -3
  516. ksadk/studio/api.py +810 -93
  517. ksadk/studio/api_catalog_routes.py +18 -0
  518. ksadk/studio/api_contracts.py +8 -2
  519. ksadk/studio/api_plugin_routes.py +562 -104
  520. ksadk/studio/api_resource_connections.py +221 -0
  521. ksadk/studio/authoring.py +12 -6
  522. ksadk/studio/authoring_coordinator.py +23 -16
  523. ksadk/studio/builder.py +88 -0
  524. ksadk/studio/capabilities.py +23 -6
  525. ksadk/studio/channel_connections.py +333 -0
  526. ksadk/studio/cloud.py +370 -112
  527. ksadk/studio/cloud_shared_web.py +638 -0
  528. ksadk/studio/codex_agent_service.py +130 -28
  529. ksadk/studio/codex_builder.py +242 -3
  530. ksadk/studio/codex_credentials.py +90 -0
  531. ksadk/studio/codex_manifest.py +31 -4
  532. ksadk/studio/codex_plugin_store.py +746 -0
  533. ksadk/studio/codex_provider_build.py +231 -0
  534. ksadk/studio/codex_run.py +190 -26
  535. ksadk/studio/compatibility_report.py +12 -1
  536. ksadk/studio/compiler.py +88 -14
  537. ksadk/studio/configuration.py +182 -0
  538. ksadk/studio/contracts.py +165 -11
  539. ksadk/studio/dsh_application.py +247 -0
  540. ksadk/studio/dsh_capability_service.py +1374 -0
  541. ksadk/studio/dsh_lifecycle.py +58 -0
  542. ksadk/studio/dsh_models.py +59 -0
  543. ksadk/studio/dsh_provider_registration.py +367 -21
  544. ksadk/studio/entry.py +53 -0
  545. ksadk/studio/event_store.py +36 -5
  546. ksadk/studio/execution_host.py +525 -0
  547. ksadk/studio/framework_run.py +32 -10
  548. ksadk/studio/hosted_kernel.py +89 -14
  549. ksadk/studio/kernel_registry.py +418 -0
  550. ksadk/studio/kernel_sqlite_migration.py +181 -0
  551. ksadk/studio/mcp_runtime.py +11 -3
  552. ksadk/studio/model_client.py +1180 -66
  553. ksadk/studio/model_profile_service.py +26 -11
  554. ksadk/studio/native_documents.py +172 -0
  555. ksadk/studio/plugin_composition.py +202 -24
  556. ksadk/studio/plugin_kernel_adapter.py +21 -106
  557. ksadk/studio/plugin_lifecycle.py +80 -0
  558. ksadk/studio/plugin_runtime.py +448 -56
  559. ksadk/studio/provider_recovery.py +59 -0
  560. ksadk/studio/recovery_page.py +70 -0
  561. ksadk/studio/resource_authority.py +664 -0
  562. ksadk/studio/resource_binding_validation.py +77 -0
  563. ksadk/studio/resource_build_admission.py +196 -0
  564. ksadk/studio/resource_build_materializer.py +149 -0
  565. ksadk/studio/resource_catalog.py +149 -2
  566. ksadk/studio/resource_connections.py +220 -0
  567. ksadk/studio/run_activity.py +895 -0
  568. ksadk/studio/run_documents.py +127 -0
  569. ksadk/studio/run_service.py +789 -83
  570. ksadk/studio/runtime_catalog.py +53 -10
  571. ksadk/studio/runtime_source.py +16 -8
  572. ksadk/studio/scheduler_assistant.py +317 -0
  573. ksadk/studio/scheduler_runtime.py +32 -280
  574. ksadk/studio/scheduler_service.py +3 -0
  575. ksadk/studio/service.py +861 -120
  576. ksadk/studio/shared_web.py +579 -82
  577. ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +8 -0
  578. ksadk/studio/static/assets/CodeBlock-DMIf4h33-UIqo-BPW.js +44 -0
  579. ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -0
  580. ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  581. ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  582. ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  583. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  584. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  585. ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  586. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  587. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  588. ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  589. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  590. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  591. ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  592. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  593. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  594. ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  595. ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  596. ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  597. ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  598. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  599. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  600. ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  601. ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  602. ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  603. ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  604. ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  605. ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  606. ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  607. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  608. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  609. ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  610. ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  611. ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  612. ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  613. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  614. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  615. ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  616. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  617. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  618. ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  619. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  620. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  621. ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  622. ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  623. ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  624. ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  625. ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  626. ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  627. ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  628. ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  629. ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  630. ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  631. ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  632. ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  633. ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  634. ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  635. ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  636. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  637. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  638. ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  639. ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-BEOyPC3w.css +1 -0
  640. ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-OhNwH4K9.js +8 -0
  641. ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
  642. ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-g0I-I4dD.js +59 -0
  643. ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
  644. ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +3 -0
  645. ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
  646. ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
  647. ksadk/studio/static/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
  648. ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
  649. ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
  650. ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CLB4L11u.js +129 -0
  651. ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BOma_Z_F.js +38 -0
  652. ksadk/studio/static/assets/channel-r8itPEik.js +1 -0
  653. ksadk/studio/static/assets/chunk-2E4U76K2-BFf_huql.js +2 -0
  654. ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
  655. ksadk/studio/static/assets/chunk-2ZTRR5NV-C2qZJila.js +2 -0
  656. ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
  657. ksadk/studio/static/assets/chunk-4HAMMTFA-DVtDP4rm.js +62 -0
  658. ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
  659. ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
  660. ksadk/studio/static/assets/chunk-6AZGARVD-BB6FqMl-.js +1 -0
  661. ksadk/studio/static/assets/chunk-6EIED4P4-DdUJkP0f.js +1 -0
  662. ksadk/studio/static/assets/chunk-6K3QC6MW-CqVsVn-y.js +1 -0
  663. ksadk/studio/static/assets/chunk-6TQVIW2G-DKlLbNIP.js +1 -0
  664. ksadk/studio/static/assets/chunk-747NJXEK-BFkZPlab.js +2 -0
  665. ksadk/studio/static/assets/chunk-75Z2AOVW-BZNhM4vB.js +2 -0
  666. ksadk/studio/static/assets/chunk-CLGD4ZFX-D-GTtyKs.js +1 -0
  667. ksadk/studio/static/assets/chunk-DU6HZSFF-CpEZCUgg.js +128 -0
  668. ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
  669. ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
  670. ksadk/studio/static/assets/chunk-GMAD6QVW-DE_8H717.js +72 -0
  671. ksadk/studio/static/assets/chunk-GVQU2GXP-BfEB0lNv.js +1 -0
  672. ksadk/studio/static/assets/chunk-I5DQTOEV-Hm2LfiYI.js +1 -0
  673. ksadk/studio/static/assets/chunk-ICYGCRZG-749o-pGJ.js +1 -0
  674. ksadk/studio/static/assets/chunk-IH6LHLGP-CC6I9F3i.js +1 -0
  675. ksadk/studio/static/assets/chunk-IMKFNOWR-D38axYOR.js +231 -0
  676. ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
  677. ksadk/studio/static/assets/chunk-KI3K4JFJ-Rma-0k_M.js +1 -0
  678. ksadk/studio/static/assets/chunk-L3NEJ4N5-Dq5xn7aL.js +1 -0
  679. ksadk/studio/static/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
  680. ksadk/studio/static/assets/chunk-OSK3NFVY-DiCQjx9b.js +10 -0
  681. ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
  682. ksadk/studio/static/assets/chunk-P2QGCYS3-VdhKmfYq.js +1 -0
  683. ksadk/studio/static/assets/chunk-POPQ4Y6H-C1_rzO5M.js +1 -0
  684. ksadk/studio/static/assets/chunk-PWAF6VOD-B45HvflI.js +1 -0
  685. ksadk/studio/static/assets/chunk-SHT3W25Y-DsCFnRVE.js +168 -0
  686. ksadk/studio/static/assets/chunk-SVP7TREG-DljApgRX.js +88 -0
  687. ksadk/studio/static/assets/chunk-TICWLB2K-DWqRtyqa.js +206 -0
  688. ksadk/studio/static/assets/chunk-TLUHSLCS-DUeGgnD5.js +2 -0
  689. ksadk/studio/static/assets/chunk-UY3FDG6J-CnmaAkG5.js +1 -0
  690. ksadk/studio/static/assets/chunk-XHIXRSVI-BFQ6B8BE.js +1 -0
  691. ksadk/studio/static/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
  692. ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
  693. ksadk/studio/static/assets/classDiagram-ZZMXUADV-DjeMNJmu.js +1 -0
  694. ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-DjeMNJmu.js +1 -0
  695. ksadk/studio/static/assets/clsx-DB0hHKMi.js +1 -0
  696. ksadk/studio/static/assets/cose-bilkent-JH36ORCC-om8AY0Mc.js +1 -0
  697. ksadk/studio/static/assets/createLucideIcon-DR0LGTP5.js +1 -0
  698. ksadk/studio/static/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
  699. ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-6BrmK52S.js +62 -0
  700. ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
  701. ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
  702. ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
  703. ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
  704. ksadk/studio/static/assets/diagram-S7CK7UJ4-C6aH78c4.js +30 -0
  705. ksadk/studio/static/assets/diagram-UQ7AKVKN-DY_tQ6C_.js +41 -0
  706. ksadk/studio/static/assets/diagram-VSXAHHWV-DX9p5cQT.js +3 -0
  707. ksadk/studio/static/assets/diagram-VX7I27RA-DB2WSH8X.js +24 -0
  708. ksadk/studio/static/assets/diagram-Z3DM3KII-Ce1BJwHE.js +24 -0
  709. ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
  710. ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
  711. ksadk/studio/static/assets/erDiagram-RLTQ6QDP-CGthTMmJ.js +99 -0
  712. ksadk/studio/static/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
  713. ksadk/studio/static/assets/flowDiagram-HODETNUW-CZ1tEenp.js +1 -0
  714. ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BfoAZW9X.js +292 -0
  715. ksadk/studio/static/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
  716. ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-S985OIJF.js +106 -0
  717. ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
  718. ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
  719. ksadk/studio/static/assets/index-CfEnms6Y.css +2 -0
  720. ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
  721. ksadk/studio/static/assets/index.dom-BQenBtFm.js +1 -0
  722. ksadk/studio/static/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
  723. ksadk/studio/static/assets/infoDiagram-27XIBGKW-CO3W8tFn.js +2 -0
  724. ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
  725. ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-BUGEl8cO.js +70 -0
  726. ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-Ch2ZYxvr.js +139 -0
  727. ksadk/studio/static/assets/kanban-definition-UXKFOSKX-Da-Fp4vC.js +89 -0
  728. ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
  729. ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
  730. ksadk/studio/static/assets/line-BDaeq300.js +1 -0
  731. ksadk/studio/static/assets/linear-DmucvK78.js +1 -0
  732. ksadk/studio/static/assets/mermaid-parser.core-Cj5mYdBi.js +4 -0
  733. ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-CvlsVQ38.js +96 -0
  734. ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
  735. ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
  736. ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
  737. ksadk/studio/static/assets/pegDiagram-XKGWAZYB-BuHuNgT5.js +1 -0
  738. ksadk/studio/static/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
  739. ksadk/studio/static/assets/pieDiagram-E7YTZNPT-DlrWiSOv.js +39 -0
  740. ksadk/studio/static/assets/preload-helper-CO68xz6u.js +1 -0
  741. ksadk/studio/static/assets/presentation-yYw7xK60-BmcZriri.js +1 -0
  742. ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-BA3hpUZM.js +7 -0
  743. ksadk/studio/static/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
  744. ksadk/studio/static/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
  745. ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
  746. ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
  747. ksadk/studio/static/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
  748. ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-BxpAazym.js +1 -0
  749. ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-E-Ge0FcV.js +84 -0
  750. ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
  751. ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
  752. ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
  753. ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-CcElXGg4.js +162 -0
  754. ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
  755. ksadk/studio/static/assets/src-B6xuSHsQ.js +1 -0
  756. ksadk/studio/static/assets/stateDiagram-D77RDMKH-DdXZOFqY.js +1 -0
  757. ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-CJbOM-QK.js +1 -0
  758. ksadk/studio/static/assets/swimlanes-42K2YHIH-NtgEEHLY.js +1 -0
  759. ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-D-AVlW8B.js +8 -0
  760. ksadk/studio/static/assets/timeline-definition-24CTP7MA-CIuYhNy3.js +120 -0
  761. ksadk/studio/static/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
  762. ksadk/studio/static/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
  763. ksadk/studio/static/assets/vennDiagram-4TSXK5OY-7HbApbrv.js +34 -0
  764. ksadk/studio/static/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
  765. ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-CMJiaedy.js +78 -0
  766. ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-BdgtMvW2.js +7 -0
  767. ksadk/studio/static/index.html +8 -2
  768. ksadk/studio/teams_catalog.py +133 -0
  769. ksadk/studio/teams_installation.py +214 -0
  770. ksadk/studio/teams_node.py +545 -0
  771. ksadk/studio/teams_node_runner.py +69 -0
  772. ksadk/studio/teams_remote.py +274 -0
  773. ksadk/studio/templates.py +40 -19
  774. ksadk/studio/validator.py +13 -0
  775. ksadk/studio/workspace.py +19 -4
  776. ksadk/studio/workspace_plugins.py +136 -0
  777. ksadk/studio/workspace_registry.py +286 -0
  778. ksadk/toolsets/__init__.py +11 -0
  779. ksadk/toolsets/skills.py +446 -378
  780. ksadk/toolsets/workspace.py +3 -3
  781. ksadk/toolsets/workspace_identity.py +15 -0
  782. ksadk/version.py +1 -1
  783. ksadk_runtime_common/memory_backend/providers/lancedb.py +56 -2
  784. ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -148
  785. ksadk_runtime_common/workspace_files/router.py +26 -13
  786. agentengine_sdk_python-0.8.3.dist-info/RECORD +0 -833
  787. ksadk/server/static/assets/MathMessageMarkdown-D9uB55Oh.js +0 -8
  788. ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
  789. ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
  790. ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
  791. ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
  792. ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
  793. ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
  794. ksadk/server/static/assets/dist-DdRBIceA.js +0 -1
  795. ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
  796. ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
  797. ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
  798. ksadk/server/static/assets/index-B2k_urY8.js +0 -241
  799. ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
  800. ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
  801. ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
  802. ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
  803. ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
  804. ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
  805. ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
  806. ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
  807. ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
  808. ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
  809. ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
  810. ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
  811. ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
  812. ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
  813. ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
  814. ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
  815. ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
  816. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
  817. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
  818. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
  819. {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,920 @@
1
+ import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto'
2
+
3
+ export const name = 'ksadk-dsh-capability-host'
4
+ export const inject = ['tools', 'webServer', 'connection']
5
+
6
+ export const HOST_PROTOCOL = 'ksadk.dsh-capability-host/v1'
7
+ export const HOST_VERSION = '1.0.0'
8
+ export const MCP_PROTOCOL_VERSION = '2025-06-18'
9
+ export const DEFAULT_CALL_TIMEOUT_MS = 60_000
10
+ export const DEFAULT_MAX_ARGUMENT_BYTES = 256 * 1024
11
+ export const DEFAULT_MAX_RESULT_BYTES = 1024 * 1024
12
+ export const DEFAULT_MAX_REQUEST_BYTES = 1024 * 1024
13
+ export const DEFAULT_MAX_IN_FLIGHT = 64
14
+
15
+ const SUPPORTED_MCP_PROTOCOLS = new Set([
16
+ MCP_PROTOCOL_VERSION,
17
+ '2025-03-26',
18
+ '2024-11-05',
19
+ ])
20
+ const DIGEST_PATTERN = /^sha256:[0-9a-f]{64}$/
21
+ const TOOL_NAME_PATTERN = /^[A-Za-z0-9_.:-]+$/
22
+
23
+ class RequestTooLargeError extends Error {}
24
+
25
+ function byteLength(value) {
26
+ return Buffer.byteLength(JSON.stringify(value), 'utf8')
27
+ }
28
+
29
+ function assertUnicodeScalars(value) {
30
+ if (typeof value === 'string') {
31
+ for (let index = 0; index < value.length; index += 1) {
32
+ const code = value.charCodeAt(index)
33
+ if (code >= 0xD800 && code <= 0xDBFF) {
34
+ const next = value.charCodeAt(index + 1)
35
+ if (!(next >= 0xDC00 && next <= 0xDFFF)) {
36
+ throw new Error('DSH tool schema contains invalid Unicode')
37
+ }
38
+ index += 1
39
+ } else if (code >= 0xDC00 && code <= 0xDFFF) {
40
+ throw new Error('DSH tool schema contains invalid Unicode')
41
+ }
42
+ }
43
+ return
44
+ }
45
+ if (Array.isArray(value)) {
46
+ for (const item of value) assertUnicodeScalars(item)
47
+ return
48
+ }
49
+ if (value !== null && typeof value === 'object') {
50
+ for (const [key, child] of Object.entries(value)) {
51
+ assertUnicodeScalars(key)
52
+ assertUnicodeScalars(child)
53
+ }
54
+ }
55
+ }
56
+
57
+ function canonical(value) {
58
+ if (value === null) return Buffer.from('n;')
59
+ if (typeof value === 'boolean') return Buffer.from(value ? 'b1;' : 'b0;')
60
+ if (typeof value === 'number') {
61
+ if (!Number.isFinite(value)) throw new Error('tool schemas require finite JSON numbers')
62
+ const bits = Buffer.allocUnsafe(8)
63
+ bits.writeDoubleBE(Object.is(value, -0) ? 0 : value)
64
+ return Buffer.from(`d${bits.toString('hex')};`)
65
+ }
66
+ if (typeof value === 'string') {
67
+ const encoded = Buffer.from(value, 'utf8')
68
+ return Buffer.concat([Buffer.from(`s${encoded.length}:`), encoded])
69
+ }
70
+ if (Array.isArray(value)) {
71
+ return Buffer.concat([Buffer.from(`a${value.length}:`), ...value.map(canonical)])
72
+ }
73
+ if (value !== null && typeof value === 'object') {
74
+ const keys = Object.keys(value).sort((left, right) =>
75
+ Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8')))
76
+ return Buffer.concat([
77
+ Buffer.from(`o${keys.length}:`),
78
+ ...keys.flatMap((key) => [canonical(key), canonical(value[key])]),
79
+ ])
80
+ }
81
+ throw new Error('tool schemas must contain only JSON values')
82
+ }
83
+
84
+ function digest(value) {
85
+ return `sha256:${createHash('sha256').update(canonical(value)).digest('hex')}`
86
+ }
87
+
88
+ function positiveInteger(value, fallback, label, maximum) {
89
+ const resolved = value === undefined ? fallback : value
90
+ if (!Number.isSafeInteger(resolved) || resolved < 1 || resolved > maximum) {
91
+ throw new Error(`${label} must be a positive bounded integer`)
92
+ }
93
+ return resolved
94
+ }
95
+
96
+ function requiredEnvironment(name, maximum) {
97
+ const value = process.env[name]
98
+ if (typeof value !== 'string' || value.length < 1 || value.length > maximum || value.includes('\0')) {
99
+ throw new Error(`${name} is required and must be bounded`)
100
+ }
101
+ return value
102
+ }
103
+
104
+ function secureTokenEqual(actual, expected) {
105
+ const left = Buffer.from(actual, 'utf8')
106
+ const right = Buffer.from(expected, 'utf8')
107
+ return left.length === right.length && timingSafeEqual(left, right)
108
+ }
109
+
110
+ function parseScopedToken(presented, token, profileDigest, tools, allowExpired = false) {
111
+ const parts = presented.split('.')
112
+ if (parts[0] === 'ks3') return parseCompanionToken(parts, token, profileDigest, tools, allowExpired)
113
+ if (parts[0] === 'ks2') return parseResourceToken(parts, token, profileDigest, tools, allowExpired)
114
+ if (parts.length !== 3 || parts[0] !== 'ks1') return null
115
+ const [, payloadEncoded, signature] = parts
116
+ const expected = createHmac('sha256', token).update(payloadEncoded).digest('base64url')
117
+ if (!secureTokenEqual(signature, expected)) return null
118
+ let payload
119
+ try {
120
+ payload = JSON.parse(Buffer.from(payloadEncoded, 'base64url').toString('utf8'))
121
+ } catch {
122
+ return null
123
+ }
124
+ if (
125
+ payload === null ||
126
+ typeof payload !== 'object' ||
127
+ Array.isArray(payload) ||
128
+ payload.v !== 1 ||
129
+ payload.profileDigest !== profileDigest ||
130
+ typeof payload.jti !== 'string' ||
131
+ !/^[A-Za-z0-9_-]{16,64}$/.test(payload.jti) ||
132
+ !Number.isSafeInteger(payload.exp) ||
133
+ (!allowExpired && payload.exp < Math.floor(Date.now() / 1000)) ||
134
+ payload.exp > Math.floor(Date.now() / 1000) + 86_400 ||
135
+ payload.aliases === null ||
136
+ typeof payload.aliases !== 'object' ||
137
+ Array.isArray(payload.aliases) ||
138
+ Object.keys(payload.aliases).length < 1 ||
139
+ Object.keys(payload.aliases).length > 32
140
+ ) return null
141
+ const aliases = new Map(Object.entries(payload.aliases))
142
+ if ([...aliases].some(([alias, source]) =>
143
+ !/^[A-Za-z0-9_-]{1,64}$/.test(alias) ||
144
+ typeof source !== 'string' ||
145
+ !tools.some((tool) => tool.name === source)
146
+ )) return null
147
+ return { root: false, scopeId: signature, aliases, expiresAt: payload.exp }
148
+ }
149
+
150
+ function parseCompanionToken(parts, token, profileDigest, tools, allowExpired) {
151
+ if (parts.length !== 3) return null
152
+ const [, encoded, signature] = parts
153
+ const expected = createHmac('sha256', token).update(`ks3.${encoded}`).digest('base64url')
154
+ if (!secureTokenEqual(signature, expected)) return null
155
+ let payload
156
+ try { payload = JSON.parse(Buffer.from(encoded, 'base64url').toString('utf8')) }
157
+ catch { return null }
158
+ if (!payload || payload.v !== 3 || payload.profileDigest !== profileDigest ||
159
+ !/^[A-Za-z0-9_.-]{1,128}$/.test(payload.pluginId) ||
160
+ !/^dshgen_[A-Za-z0-9_-]{24,96}$/.test(payload.generationId) ||
161
+ !/^[A-Za-z0-9_-]{32,256}$/.test(payload.handle) ||
162
+ !/^[A-Za-z0-9_.:-]{1,128}$/.test(payload.callId) ||
163
+ !/^[A-Za-z0-9_-]{16,64}$/.test(payload.jti) ||
164
+ !Number.isSafeInteger(payload.exp) ||
165
+ (!allowExpired && payload.exp <= Math.floor(Date.now() / 1000)) ||
166
+ payload.exp > Math.floor(Date.now() / 1000) + 120 ||
167
+ !payload.aliases || typeof payload.aliases !== 'object' || Array.isArray(payload.aliases) ||
168
+ Object.keys(payload.aliases).length !== 1) return null
169
+ const aliases = new Map(Object.entries(payload.aliases))
170
+ if ([...aliases].some(([alias, source]) => alias !== source ||
171
+ !tools.some(tool => tool.name === source))) return null
172
+ return { root: false, scopeId: signature, aliases, expiresAt: payload.exp,
173
+ companion: { pluginId: payload.pluginId, generationId: payload.generationId,
174
+ handle: payload.handle, callId: payload.callId } }
175
+ }
176
+
177
+ function parseResourceToken(parts, token, profileDigest, tools, allowExpired) {
178
+ if (parts.length !== 3) return null
179
+ const [, encoded, signature] = parts
180
+ const expected = createHmac('sha256', token).update(`ks2.${encoded}`).digest('base64url')
181
+ if (!secureTokenEqual(signature, expected)) return null
182
+ let payload
183
+ try { payload = JSON.parse(Buffer.from(encoded, 'base64url').toString('utf8')) }
184
+ catch { return null }
185
+ const record = value => value !== null && typeof value === 'object' && !Array.isArray(value)
186
+ const ref = value => typeof value === 'string' && /^\S{1,256}$/u.test(value)
187
+ const now = Math.floor(Date.now() / 1000)
188
+ if (!record(payload) || payload.v !== 2 || payload.profileDigest !== profileDigest ||
189
+ !ref(payload.generationId) || !ref(payload.activationId) ||
190
+ !DIGEST_PATTERN.test(payload.buildDigest ?? '') || !DIGEST_PATTERN.test(payload.bindingSnapshotDigest ?? '') ||
191
+ !Number.isSafeInteger(payload.issuedAt) || !Number.isSafeInteger(payload.expiresAt) ||
192
+ payload.issuedAt > now + 5 || payload.expiresAt <= payload.issuedAt ||
193
+ payload.expiresAt - payload.issuedAt > 600 || (!allowExpired && payload.expiresAt <= now) ||
194
+ typeof payload.jti !== 'string' || !/^[A-Za-z0-9_-]{16,64}$/.test(payload.jti) ||
195
+ !record(payload.identity) || !record(payload.aliases) || !record(payload.resources)) return null
196
+ const identityKeys = ['tenantRef', 'resourcePrincipalRef', 'actorRef', 'memorySubjectRef', 'agentId', 'sessionRef']
197
+ if (Object.keys(payload.identity).length !== identityKeys.length ||
198
+ identityKeys.some(key => !ref(payload.identity[key]))) return null
199
+ const aliases = new Map(Object.entries(payload.aliases))
200
+ if (!aliases.size || aliases.size > 32 || [...aliases].some(([alias, source]) =>
201
+ !/^[A-Za-z0-9_-]{1,64}$/.test(alias) || typeof source !== 'string' ||
202
+ !tools.some(tool => tool.name === source))) return null
203
+ const resources = new Map(Object.entries(payload.resources))
204
+ if (!resources.size || resources.size > 32 || [...resources].some(([source, item]) =>
205
+ ![...aliases.values()].includes(source) || !record(item) || !ref(item.bindingId) ||
206
+ item.operation !== source || typeof item.handle !== 'string' ||
207
+ !/^[A-Za-z0-9_-]{32,256}$/.test(item.handle))) return null
208
+ return { root: false, scopeId: signature, aliases, resources, expiresAt: payload.expiresAt }
209
+ }
210
+
211
+ function authorize(request, token, profileDigest, tools, revokedScopes) {
212
+ const header = request.headers.authorization
213
+ if (typeof header !== 'string' || !header.startsWith('Bearer ')) return null
214
+ if (secureTokenEqual(header, `Bearer ${token}`)) {
215
+ return { root: true, scopeId: 'root', aliases: null, expiresAt: null }
216
+ }
217
+ const now = Math.floor(Date.now() / 1000)
218
+ for (const [scopeId, expiresAt] of revokedScopes) {
219
+ if (expiresAt < now) revokedScopes.delete(scopeId)
220
+ }
221
+ const authorization = parseScopedToken(
222
+ header.slice('Bearer '.length), token, profileDigest, tools)
223
+ if (authorization === null || revokedScopes.has(authorization.scopeId)) return null
224
+ return authorization
225
+ }
226
+
227
+ function originAllowed(request) {
228
+ const origin = request.headers.origin
229
+ if (origin === undefined) return true
230
+ if (Array.isArray(origin) || origin.length > 2048) return false
231
+ try {
232
+ const parsed = new URL(origin)
233
+ return (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&
234
+ (parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' || parsed.hostname === '[::1]')
235
+ } catch {
236
+ return false
237
+ }
238
+ }
239
+
240
+ function writeJson(response, status, payload, extraHeaders = {}) {
241
+ const body = Buffer.from(JSON.stringify(payload), 'utf8')
242
+ response.writeHead(status, {
243
+ 'Cache-Control': 'no-store',
244
+ 'Content-Type': 'application/json; charset=utf-8',
245
+ 'Content-Length': String(body.length),
246
+ ...extraHeaders,
247
+ })
248
+ response.end(body)
249
+ }
250
+
251
+ function writeEmpty(response, status) {
252
+ response.writeHead(status, {
253
+ 'Cache-Control': 'no-store',
254
+ 'Content-Length': '0',
255
+ })
256
+ response.end()
257
+ }
258
+
259
+ function jsonRpcError(id, code, message, data) {
260
+ return {
261
+ jsonrpc: '2.0',
262
+ id: id ?? null,
263
+ error: {
264
+ code,
265
+ message,
266
+ ...(data === undefined ? {} : { data }),
267
+ },
268
+ }
269
+ }
270
+
271
+ function readBody(request, maximum) {
272
+ return new Promise((resolve, reject) => {
273
+ const declared = Number(request.headers['content-length'])
274
+ if (Number.isFinite(declared) && declared > maximum) {
275
+ request.resume()
276
+ reject(new RequestTooLargeError('request body exceeds the configured limit'))
277
+ return
278
+ }
279
+ const chunks = []
280
+ let size = 0
281
+ let settled = false
282
+ request.on('data', (chunk) => {
283
+ if (settled) return
284
+ size += chunk.length
285
+ if (size > maximum) {
286
+ settled = true
287
+ chunks.length = 0
288
+ reject(new RequestTooLargeError('request body exceeds the configured limit'))
289
+ return
290
+ }
291
+ chunks.push(chunk)
292
+ })
293
+ request.on('end', () => {
294
+ if (!settled) resolve(Buffer.concat(chunks).toString('utf8'))
295
+ })
296
+ request.on('error', (error) => {
297
+ if (!settled) reject(error)
298
+ })
299
+ })
300
+ }
301
+
302
+ function snapshotTools(runtime, maximumBytes) {
303
+ const raw = runtime.schemas()
304
+ if (!Array.isArray(raw) || raw.length > 2048) {
305
+ throw new Error('DSH tool inventory is invalid or too large')
306
+ }
307
+ const seen = new Set()
308
+ const tools = raw.map((schema) => {
309
+ if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) {
310
+ throw new Error('DSH emitted an invalid tool schema')
311
+ }
312
+ const { name, description, parameters } = schema
313
+ if (
314
+ typeof name !== 'string' ||
315
+ name.length < 1 ||
316
+ name.length > 128 ||
317
+ !TOOL_NAME_PATTERN.test(name) ||
318
+ seen.has(name)
319
+ ) {
320
+ throw new Error('DSH emitted an invalid or duplicate tool name')
321
+ }
322
+ if (typeof description !== 'string' || description.length > 16_384) {
323
+ throw new Error(`DSH tool ${name} emitted an invalid description`)
324
+ }
325
+ if (parameters === null || typeof parameters !== 'object' || Array.isArray(parameters)) {
326
+ throw new Error(`DSH tool ${name} emitted an invalid parameters schema`)
327
+ }
328
+ seen.add(name)
329
+ const detached = JSON.parse(JSON.stringify({
330
+ name,
331
+ description: Array.from(description).slice(0, 1024).join(''),
332
+ inputSchema: parameters,
333
+ }))
334
+ assertUnicodeScalars(detached)
335
+ if (byteLength(detached) > maximumBytes) {
336
+ throw new Error(`DSH tool ${name} schema exceeds the configured limit`)
337
+ }
338
+ return detached
339
+ })
340
+ tools.sort((left, right) =>
341
+ Buffer.compare(Buffer.from(left.name, 'utf8'), Buffer.from(right.name, 'utf8')))
342
+ if (byteLength(tools) > maximumBytes) {
343
+ throw new Error('DSH tool inventory exceeds the configured limit')
344
+ }
345
+ return tools
346
+ }
347
+
348
+ function textContent(text) {
349
+ return { type: 'text', text: String(text) }
350
+ }
351
+
352
+ function projectContent(content) {
353
+ if (!Array.isArray(content)) return []
354
+ return content.map((block) => {
355
+ if (block !== null && typeof block === 'object' && !Array.isArray(block)) {
356
+ if (block.type === 'text' && typeof block.text === 'string') return textContent(block.text)
357
+ if (block.type === 'reasoning' && typeof block.text === 'string') return textContent(block.text)
358
+ const kind = typeof block.type === 'string' ? block.type : 'unknown'
359
+ return textContent(`[DSH ${kind} content is not representable on this MCP bridge]`)
360
+ }
361
+ return textContent('[DSH emitted an invalid content block]')
362
+ })
363
+ }
364
+
365
+ function toolFailure(message, code = 'DSH_TOOL_BRIDGE_ERROR') {
366
+ return {
367
+ content: [textContent(`Error: ${message}`)],
368
+ isError: true,
369
+ _meta: { 'io.ksadk/dsh': { code } },
370
+ }
371
+ }
372
+
373
+ function projectToolResult(result, maximumBytes, resourceInvocation = false) {
374
+ if (result === null || typeof result !== 'object' || Array.isArray(result)) {
375
+ return toolFailure('DSH returned an invalid tool result')
376
+ }
377
+ const content = projectContent(result.content)
378
+ const projected = {
379
+ content,
380
+ isError: result.isError === true,
381
+ }
382
+ if (result.isError === true) {
383
+ const failure = result.error
384
+ const message = failure && typeof failure.message === 'string'
385
+ ? failure.message.slice(0, 16_384)
386
+ : 'DSH tool execution failed'
387
+ if (projected.content.length === 0) projected.content.push(textContent(`Error: ${message}`))
388
+ const code = failure?.info && typeof failure.info.code === 'string'
389
+ ? failure.info.code.slice(0, 256)
390
+ : 'DSH_TOOL_ERROR'
391
+ projected._meta = { 'io.ksadk/dsh': { code } }
392
+ } else if (
393
+ result.value !== null &&
394
+ typeof result.value === 'object' &&
395
+ !Array.isArray(result.value)
396
+ ) {
397
+ projected.structuredContent = result.value
398
+ // A successful Cordis invocation may carry a failed resource operation.
399
+ // Apply this domain contract only after authenticated resource admission;
400
+ // ordinary third-party values named "status" retain their existing meaning.
401
+ if (resourceInvocation && ['failed', 'unauthorized'].includes(result.value.status)) {
402
+ projected.isError = true
403
+ const code = typeof result.value.errorCode === 'string'
404
+ && /^(RESOURCE|MEMORY|KNOWLEDGE|SKILL)_[A-Z_]{1,96}$/.test(result.value.errorCode)
405
+ ? result.value.errorCode : 'RESOURCE_OPERATION_FAILED'
406
+ projected._meta = { 'io.ksadk/dsh': { code } }
407
+ }
408
+ } else if (projected.content.length === 0 && result.value !== undefined) {
409
+ projected.content.push(textContent(JSON.stringify(result.value)))
410
+ }
411
+ try {
412
+ if (byteLength(projected) <= maximumBytes) return projected
413
+ } catch {}
414
+ return toolFailure('DSH tool result exceeds the configured bridge limit', 'DSH_RESULT_TOO_LARGE')
415
+ }
416
+
417
+ function requestKey(scopeId, id) {
418
+ return JSON.stringify([scopeId, typeof id, id])
419
+ }
420
+
421
+ function abortOutcome(controller) {
422
+ return new Promise((resolve) => {
423
+ const finish = () => {
424
+ const reason = controller.signal.reason
425
+ resolve({
426
+ kind: 'aborted',
427
+ code: reason?.code === 'DEADLINE_EXCEEDED' ? 'DEADLINE_EXCEEDED' : 'ABORTED',
428
+ })
429
+ }
430
+ if (controller.signal.aborted) finish()
431
+ else controller.signal.addEventListener('abort', finish, { once: true })
432
+ })
433
+ }
434
+
435
+ function validateRequestEnvelope(message) {
436
+ return message !== null &&
437
+ typeof message === 'object' &&
438
+ !Array.isArray(message) &&
439
+ message.jsonrpc === '2.0' &&
440
+ typeof message.method === 'string' &&
441
+ (
442
+ message.id === undefined ||
443
+ typeof message.id === 'string' ||
444
+ (typeof message.id === 'number' && Number.isSafeInteger(message.id))
445
+ )
446
+ }
447
+
448
+ function normalizedProtocol(requested) {
449
+ return SUPPORTED_MCP_PROTOCOLS.has(requested) ? requested : MCP_PROTOCOL_VERSION
450
+ }
451
+
452
+ function emitReadyRecord(record) {
453
+ process.stdout.write(`@@KSADK_DSH_CAPABILITY_READY@@${JSON.stringify(record)}\n`)
454
+ }
455
+
456
+ function emitRuntimeToken(token) {
457
+ process.stdout.write(`@@KSADK_DSH_CAPABILITY_TOKEN@@${token}\n`)
458
+ }
459
+
460
+ function emitBrowserToken(token) {
461
+ process.stdout.write(`@@KSADK_DSH_CORE_TOKEN@@${token}\n`)
462
+ }
463
+
464
+ export async function apply(ctx, config = {}) {
465
+ const profile = requiredEnvironment('KSADK_DSH_PROFILE', 64)
466
+ const profileDigest = requiredEnvironment('KSADK_DSH_PROFILE_DIGEST', 80)
467
+ const dshVersion = requiredEnvironment('KSADK_DSH_VERSION', 64)
468
+ requiredEnvironment('KSADK_DSH_CAPABILITY_READY_STDOUT', 8)
469
+ const token = randomBytes(48).toString('base64url')
470
+ if (!DIGEST_PATTERN.test(profileDigest)) throw new Error('KSADK_DSH_PROFILE_DIGEST is invalid')
471
+
472
+ const callTimeoutMs = positiveInteger(config.callTimeoutMs, DEFAULT_CALL_TIMEOUT_MS, 'callTimeoutMs', 3_600_000)
473
+ const maxArgumentBytes = positiveInteger(config.maxArgumentBytes, DEFAULT_MAX_ARGUMENT_BYTES, 'maxArgumentBytes', 8 * 1024 * 1024)
474
+ const maxResultBytes = positiveInteger(config.maxResultBytes, DEFAULT_MAX_RESULT_BYTES, 'maxResultBytes', 8 * 1024 * 1024)
475
+ const maxRequestBytes = positiveInteger(config.maxRequestBytes, DEFAULT_MAX_REQUEST_BYTES, 'maxRequestBytes', 8 * 1024 * 1024)
476
+ const maxInFlight = positiveInteger(config.maxInFlight, DEFAULT_MAX_IN_FLIGHT, 'maxInFlight', 1024)
477
+ const inventoryQuietMs = positiveInteger(config.inventoryQuietMs, 50, 'inventoryQuietMs', 5_000)
478
+
479
+ const pending = new Map()
480
+ const revokedScopes = new Map()
481
+ let draining = false
482
+ let drifted = false
483
+ let readyWritten = false
484
+ let lastToolChange = Date.now()
485
+ let tools = []
486
+ let resourceBridge = null
487
+ let companionBridge = null
488
+ if (typeof ctx.inject === 'function') ctx.inject(['pluginCompanions'], companionCtx => {
489
+ const bridge = companionCtx.pluginCompanions
490
+ companionBridge = bridge
491
+ companionCtx.effect(() => () => { if (companionBridge === bridge) companionBridge = null })
492
+ })
493
+ // A pending optional child does not add another Core or block ordinary tools.
494
+ // Its dependency lifecycle clears the reference when the resource plugin stops.
495
+ if (typeof ctx.inject === 'function') ctx.inject(['platformResources'], resourceCtx => {
496
+ const bridge = resourceCtx.platformResources
497
+ resourceBridge = bridge
498
+ resourceCtx.effect(() => () => { if (resourceBridge === bridge) resourceBridge = null })
499
+ })
500
+ let inventoryDigest = digest(tools)
501
+
502
+ let driftCheckTimer = null
503
+ ctx.on('tools/change', () => {
504
+ lastToolChange = Date.now()
505
+ // Upstream plugins (e.g. dsh-ssh) dispose+re-register the same tools when
506
+ // settings re-sync; the intermediate state has a different fingerprint but
507
+ // converges. Debounce: only mark drift if the fingerprint is still
508
+ // different after the quiet window settles.
509
+ if (readyWritten) {
510
+ if (driftCheckTimer !== null) clearTimeout(driftCheckTimer)
511
+ driftCheckTimer = setTimeout(() => {
512
+ driftCheckTimer = null
513
+ const next = snapshotTools(ctx.tools, maxRequestBytes)
514
+ if (digest(next) !== inventoryDigest) drifted = true
515
+ }, inventoryQuietMs)
516
+ }
517
+ }, { global: true })
518
+
519
+ const handleRequest = async (request, response) => {
520
+ response.setHeader('X-Content-Type-Options', 'nosniff')
521
+ response.setHeader('Referrer-Policy', 'no-referrer')
522
+ if (!originAllowed(request)) {
523
+ writeJson(response, 403, { error: 'origin_denied' })
524
+ return
525
+ }
526
+
527
+ let parsedUrl
528
+ try {
529
+ parsedUrl = new URL(request.url ?? '/', 'http://127.0.0.1')
530
+ } catch {
531
+ writeJson(response, 400, { error: 'invalid_url' })
532
+ return
533
+ }
534
+
535
+ const authorization = authorize(request, token, profileDigest, tools, revokedScopes)
536
+
537
+ if (request.method === 'GET' && parsedUrl.pathname === '/health' && parsedUrl.search === '') {
538
+ if (authorization === null) {
539
+ response.setHeader('WWW-Authenticate', 'Bearer')
540
+ writeJson(response, 401, { error: 'unauthorized' })
541
+ return
542
+ }
543
+ writeJson(response, drifted || draining ? 503 : 200, {
544
+ protocolVersion: HOST_PROTOCOL,
545
+ healthy: !drifted && !draining,
546
+ profile,
547
+ profileDigest,
548
+ inventoryDigest,
549
+ toolCount: tools.length,
550
+ inFlight: pending.size,
551
+ drifted,
552
+ draining,
553
+ })
554
+ return
555
+ }
556
+
557
+ if (request.method !== 'POST' || parsedUrl.pathname !== '/mcp' || parsedUrl.search !== '') {
558
+ writeJson(response, 404, { error: 'not_found' })
559
+ return
560
+ }
561
+ if (authorization === null) {
562
+ response.setHeader('WWW-Authenticate', 'Bearer')
563
+ writeJson(response, 401, { error: 'unauthorized' })
564
+ return
565
+ }
566
+ if (!(request.headers['content-type'] ?? '').toLowerCase().startsWith('application/json')) {
567
+ writeJson(response, 415, { error: 'content_type_required' })
568
+ return
569
+ }
570
+
571
+ let message
572
+ try {
573
+ const body = await readBody(request, maxRequestBytes)
574
+ message = JSON.parse(body)
575
+ } catch (error) {
576
+ if (error instanceof RequestTooLargeError) {
577
+ writeJson(response, 413, { error: 'request_too_large' })
578
+ } else {
579
+ writeJson(response, 400, jsonRpcError(null, -32700, 'Parse error'))
580
+ }
581
+ return
582
+ }
583
+ if (!validateRequestEnvelope(message)) {
584
+ writeJson(response, 400, jsonRpcError(message?.id, -32600, 'Invalid Request'))
585
+ return
586
+ }
587
+ // A scoped request may have been authorized before a slow body finished
588
+ // while its activation was revoked by a concurrent root request.
589
+ if (!authorization.root && revokedScopes.has(authorization.scopeId)) {
590
+ response.setHeader('WWW-Authenticate', 'Bearer')
591
+ writeJson(response, 401, { error: 'unauthorized' })
592
+ return
593
+ }
594
+
595
+ const isNotification = message.id === undefined
596
+ const params = message.params ?? {}
597
+ if (params === null || typeof params !== 'object' || Array.isArray(params)) {
598
+ if (isNotification) writeEmpty(response, 202)
599
+ else writeJson(response, 200, jsonRpcError(message.id, -32602, 'Invalid params'))
600
+ return
601
+ }
602
+
603
+ if (message.method === 'notifications/initialized') {
604
+ writeEmpty(response, 202)
605
+ return
606
+ }
607
+ if (message.method === 'notifications/cancelled') {
608
+ const error = new Error('MCP client cancelled the request')
609
+ error.code = 'ABORTED'
610
+ if (authorization.root) {
611
+ for (const active of pending.values()) {
612
+ if (active.requestIdKey === requestKey('', params.requestId)) {
613
+ active.controller.abort(error)
614
+ }
615
+ }
616
+ } else {
617
+ const active = pending.get(requestKey(authorization.scopeId, params.requestId))
618
+ if (active) active.controller.abort(error)
619
+ }
620
+ writeEmpty(response, 202)
621
+ return
622
+ }
623
+ if (isNotification) {
624
+ writeEmpty(response, 202)
625
+ return
626
+ }
627
+
628
+ if (message.method === 'initialize') {
629
+ if (typeof params.protocolVersion !== 'string') {
630
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'protocolVersion is required'))
631
+ return
632
+ }
633
+ writeJson(response, 200, {
634
+ jsonrpc: '2.0',
635
+ id: message.id,
636
+ result: {
637
+ protocolVersion: normalizedProtocol(params.protocolVersion),
638
+ capabilities: { tools: {} },
639
+ serverInfo: { name: '@kingsoftcloud/ksadk-dsh-capability-host', version: HOST_VERSION },
640
+ },
641
+ })
642
+ return
643
+ }
644
+ if (message.method === 'ping') {
645
+ writeJson(response, 200, { jsonrpc: '2.0', id: message.id, result: {} })
646
+ return
647
+ }
648
+ if (message.method === 'io.ksadk/scopes/revoke') {
649
+ if (!authorization.root || typeof params.token !== 'string' || params.token.length > 12 * 1024) {
650
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'valid scoped token is required'))
651
+ return
652
+ }
653
+ const scoped = parseScopedToken(params.token, token, profileDigest, tools, true)
654
+ if (scoped === null) {
655
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'valid scoped token is required'))
656
+ return
657
+ }
658
+ if (!revokedScopes.has(scoped.scopeId) && revokedScopes.size >= 4096) {
659
+ writeJson(response, 200, jsonRpcError(message.id, -32001, 'revocation capacity reached'))
660
+ return
661
+ }
662
+ revokedScopes.set(scoped.scopeId, scoped.expiresAt)
663
+ const error = new Error('MCP credential scope was revoked')
664
+ error.code = 'ABORTED'
665
+ for (const active of pending.values()) {
666
+ if (active.scopeId === scoped.scopeId) active.controller.abort(error)
667
+ }
668
+ writeJson(response, 200, {
669
+ jsonrpc: '2.0',
670
+ id: message.id,
671
+ result: { revoked: true },
672
+ })
673
+ return
674
+ }
675
+ if (draining || drifted) {
676
+ writeJson(response, 200, jsonRpcError(message.id, -32002, 'DSH capability inventory is unavailable'))
677
+ return
678
+ }
679
+ if (message.method === 'tools/list') {
680
+ if (params.cursor !== undefined && params.cursor !== null && params.cursor !== '') {
681
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'cursor is not supported'))
682
+ return
683
+ }
684
+ const candidates = authorization.aliases === null
685
+ ? tools
686
+ : [...authorization.aliases].filter(([, source]) =>
687
+ !resourceBridge?.operationForTool(source) || authorization.resources?.has(source)
688
+ ).map(([alias, source]) => {
689
+ const tool = tools.find((item) => item.name === source)
690
+ return { ...tool, name: alias }
691
+ })
692
+ const checked = await Promise.all(candidates.map(async tool => {
693
+ const source = authorization.aliases?.get(tool.name)
694
+ const resource = authorization.resources?.get(source)
695
+ if (!resource) return tool
696
+ if (!resourceBridge || resourceBridge.operationForTool(source) !== resource.operation) return null
697
+ try {
698
+ const result = await resourceBridge.withInvocation({
699
+ handle: resource.handle,
700
+ deadline: Math.min(Date.now() + 3000, authorization.expiresAt * 1000),
701
+ }, () => resourceBridge.check(resource.operation))
702
+ return result.available === true ? tool : null
703
+ } catch { return null }
704
+ }))
705
+ if (!authorization.root && (revokedScopes.has(authorization.scopeId) ||
706
+ authorization.expiresAt * 1000 <= Date.now())) {
707
+ response.setHeader('WWW-Authenticate', 'Bearer')
708
+ writeJson(response, 401, { error: 'unauthorized' })
709
+ return
710
+ }
711
+ const visibleTools = checked.filter(Boolean)
712
+ writeJson(response, 200, { jsonrpc: '2.0', id: message.id, result: { tools: visibleTools } })
713
+ return
714
+ }
715
+ if (message.method !== 'tools/call') {
716
+ writeJson(response, 200, jsonRpcError(message.id, -32601, 'Method not found'))
717
+ return
718
+ }
719
+ if (typeof params.name !== 'string') {
720
+ writeJson(response, 200, {
721
+ jsonrpc: '2.0',
722
+ id: message.id,
723
+ result: toolFailure('unknown DSH tool', 'UNKNOWN_TOOL'),
724
+ })
725
+ return
726
+ }
727
+ const sourceToolName = authorization.aliases === null
728
+ ? params.name
729
+ : authorization.aliases.get(params.name)
730
+ if (sourceToolName === undefined) {
731
+ writeJson(response, 200, jsonRpcError(message.id, -32003, 'Tool is outside credential scope'))
732
+ return
733
+ }
734
+ if (!tools.some((tool) => tool.name === sourceToolName)) {
735
+ writeJson(response, 200, {
736
+ jsonrpc: '2.0',
737
+ id: message.id,
738
+ result: toolFailure('unknown DSH tool', 'UNKNOWN_TOOL'),
739
+ })
740
+ return
741
+ }
742
+ const resourceOperation = resourceBridge?.operationForTool(sourceToolName)
743
+ const resourceScope = authorization.resources?.get(sourceToolName)
744
+ if ((resourceOperation || resourceScope) &&
745
+ (!resourceBridge || !resourceScope || resourceScope.operation !== resourceOperation)) {
746
+ writeJson(response, 200, { jsonrpc: '2.0', id: message.id,
747
+ result: toolFailure('Resource invocation context is required', 'RESOURCE_CONTEXT_REQUIRED') })
748
+ return
749
+ }
750
+ const companionOperation = companionBridge?.operationForTool(sourceToolName)
751
+ const companionScope = authorization.companion
752
+ if ((companionOperation || companionScope) &&
753
+ (!companionBridge || !companionScope || !companionOperation ||
754
+ companionScope.pluginId !== companionOperation.pluginId ||
755
+ companionScope.generationId !== companionBridge.generationId ||
756
+ companionScope.callId !== message.id)) {
757
+ writeJson(response, 200, { jsonrpc: '2.0', id: message.id,
758
+ result: toolFailure('Companion invocation context is required', 'COMPANION_CONTEXT_REQUIRED') })
759
+ return
760
+ }
761
+ const argumentsValue = params.arguments ?? {}
762
+ if (argumentsValue === null || typeof argumentsValue !== 'object' || Array.isArray(argumentsValue)) {
763
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments must be an object'))
764
+ return
765
+ }
766
+ try {
767
+ if (byteLength(argumentsValue) > maxArgumentBytes) {
768
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments exceed the configured limit'))
769
+ return
770
+ }
771
+ } catch {
772
+ writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments must be JSON'))
773
+ return
774
+ }
775
+ if (pending.size >= maxInFlight) {
776
+ writeJson(response, 200, jsonRpcError(message.id, -32001, 'too many in-flight tool calls'))
777
+ return
778
+ }
779
+
780
+ const key = requestKey(authorization.scopeId, message.id)
781
+ if (pending.has(key)) {
782
+ writeJson(response, 200, jsonRpcError(message.id, -32600, 'duplicate in-flight request id'))
783
+ return
784
+ }
785
+ const controller = new AbortController()
786
+ const timeout = setTimeout(() => {
787
+ const error = new Error('DSH tool call deadline exceeded')
788
+ error.code = 'DEADLINE_EXCEEDED'
789
+ controller.abort(error)
790
+ }, callTimeoutMs)
791
+ const completion = Promise.resolve()
792
+ .then(() => {
793
+ const invoke = () => ctx.tools.execute({
794
+ callId: companionScope?.callId ?? `mcp-${randomUUID()}`, name: sourceToolName,
795
+ arguments: argumentsValue, signal: controller.signal,
796
+ })
797
+ if (companionScope) return companionBridge.withInvocation({
798
+ ...companionScope,
799
+ deadline: Math.min(Date.now() + callTimeoutMs, authorization.expiresAt * 1000),
800
+ signal: controller.signal,
801
+ }, invoke)
802
+ return resourceScope ? resourceBridge.withInvocation({
803
+ handle: resourceScope.handle,
804
+ deadline: Math.min(Date.now() + callTimeoutMs, authorization.expiresAt * 1000),
805
+ signal: controller.signal,
806
+ }, invoke) : invoke()
807
+ })
808
+ .then(
809
+ (result) => ({ kind: 'result', result }),
810
+ (error) => ({ kind: 'error', error }),
811
+ )
812
+ pending.set(key, {
813
+ controller,
814
+ completion,
815
+ scopeId: authorization.scopeId,
816
+ requestIdKey: requestKey('', message.id),
817
+ })
818
+ response.on('close', () => {
819
+ if (!response.writableEnded) {
820
+ const error = new Error('MCP client disconnected')
821
+ error.code = 'ABORTED'
822
+ controller.abort(error)
823
+ }
824
+ })
825
+ let completed = false
826
+ try {
827
+ const outcome = await Promise.race([completion, abortOutcome(controller)])
828
+ completed = outcome.kind !== 'aborted'
829
+ if (outcome.kind === 'result') {
830
+ writeJson(response, 200, {
831
+ jsonrpc: '2.0',
832
+ id: message.id,
833
+ result: projectToolResult(outcome.result, maxResultBytes, Boolean(resourceScope)),
834
+ })
835
+ } else if (outcome.kind === 'aborted') {
836
+ const messageText = outcome.code === 'DEADLINE_EXCEEDED'
837
+ ? 'DSH tool call deadline exceeded'
838
+ : 'DSH tool call was cancelled'
839
+ writeJson(response, 200, {
840
+ jsonrpc: '2.0',
841
+ id: message.id,
842
+ result: toolFailure(messageText, outcome.code),
843
+ })
844
+ } else {
845
+ writeJson(response, 200, jsonRpcError(message.id, -32603, 'DSH tool pipeline failed'))
846
+ }
847
+ } finally {
848
+ clearTimeout(timeout)
849
+ if (completed) pending.delete(key)
850
+ else {
851
+ void completion.then(() => pending.delete(key))
852
+ // AbortSignal is cooperative. A third-party Cordis tool may ignore it
853
+ // forever, so an aborted call cannot be allowed to retain one in-flight
854
+ // slot indefinitely. Give a cooperative tool a short unwind window;
855
+ // otherwise crash this isolated generation and let the Python
856
+ // supervisor reap the process group and start a clean generation.
857
+ const abortGrace = setTimeout(() => {
858
+ if (!pending.has(key)) return
859
+ draining = true
860
+ process.exit(70)
861
+ }, 250)
862
+ abortGrace.unref()
863
+ void completion.then(() => clearTimeout(abortGrace))
864
+ }
865
+ }
866
+ }
867
+ const disposeMcp = ctx.webServer.register({ kind: 'exact', path: '/mcp', handler: handleRequest })
868
+ const disposeHealth = ctx.webServer.register({ kind: 'exact', path: '/health', handler: handleRequest })
869
+ ctx.effect(() => () => {
870
+ draining = true
871
+ for (const entry of pending.values()) {
872
+ entry.controller.abort(new Error('DSH capability host is stopping'))
873
+ }
874
+ disposeHealth()
875
+ disposeMcp()
876
+ })
877
+
878
+ // Reset the quiet baseline after the official Core server has activated:
879
+ // plugins may still be registering tools while the overlay starts.
880
+ lastToolChange = Date.now()
881
+ while (Date.now() - lastToolChange < inventoryQuietMs) {
882
+ await new Promise((resolve) => setTimeout(resolve, inventoryQuietMs))
883
+ }
884
+ tools = snapshotTools(ctx.tools, maxRequestBytes)
885
+ inventoryDigest = digest(tools)
886
+ const port = ctx.webServer.port
887
+ if (!Number.isSafeInteger(port) || port < 1 || port > 65535 || ctx.webServer.host !== '127.0.0.1') {
888
+ throw new Error('DSH Core webServer must bind a loopback TCP port')
889
+ }
890
+ const coreUrl = new URL(ctx.connection.authenticatedUrl(`http://127.0.0.1:${port}`))
891
+ const browserTokens = coreUrl.searchParams.getAll('token')
892
+ if (
893
+ coreUrl.protocol !== 'http:' ||
894
+ coreUrl.hostname !== '127.0.0.1' ||
895
+ coreUrl.port !== String(port) ||
896
+ coreUrl.pathname !== '/' ||
897
+ coreUrl.hash !== '' ||
898
+ [...coreUrl.searchParams.keys()].some((key) => key !== 'token') ||
899
+ browserTokens.length !== 1 ||
900
+ !/^[A-Za-z0-9_-]{32,128}$/.test(browserTokens[0])
901
+ ) {
902
+ throw new Error('DSH Core connection did not provide an authenticated browser URL')
903
+ }
904
+ readyWritten = true
905
+ emitRuntimeToken(token)
906
+ emitBrowserToken(browserTokens[0])
907
+ emitReadyRecord({
908
+ protocolVersion: HOST_PROTOCOL,
909
+ hostVersion: HOST_VERSION,
910
+ dshVersion,
911
+ profile,
912
+ profileDigest,
913
+ definition: 'mcp.connector/v1',
914
+ transport: 'streamable-http',
915
+ endpoint: `http://127.0.0.1:${port}/mcp`,
916
+ inventoryDigest,
917
+ tools,
918
+ webRouteCount: 2,
919
+ })
920
+ }