agentengine-sdk-python 0.8.2__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +22 -28
- agentengine_sdk_python-0.8.4.dist-info/RECORD +1070 -0
- ksadk/_build_provenance.json +1 -0
- ksadk/agui/_agent_helpers.py +4 -0
- ksadk/api/client.py +108 -91
- ksadk/builders/code_builder.py +36 -9
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +4 -0
- ksadk/cli/__init__.py +38 -3
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_plugin.py +662 -0
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +424 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +83 -283
- ksadk/common/auth.py +16 -10
- ksadk/configs/env_registry.py +59 -3
- ksadk/configs/settings.py +9 -0
- ksadk/context_engine/contributors.py +73 -8
- ksadk/conversations/__init__.py +19 -0
- ksadk/conversations/context.py +104 -24
- ksadk/conversations/contracts.py +266 -0
- ksadk/conversations/message_projection.py +154 -15
- ksadk/conversations/projector.py +614 -0
- ksadk/conversations/reducer.py +98 -0
- ksadk/conversations/runtime_invocation.py +5 -0
- ksadk/conversations/runtime_payloads.py +1 -0
- ksadk/conversations/runtime_preparation.py +30 -27
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +5 -0
- ksadk/conversations/runtime_streaming.py +25 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/_v1_compat/projection.py +2 -0
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/codex.py +190 -0
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/harness/__init__.py +45 -35
- ksadk/harness/config.py +2 -2
- ksadk/harness/runtime.py +75 -16
- ksadk/harness/tools.py +38 -13
- ksadk/interaction/provider.py +1 -0
- ksadk/interaction/providers/langgraph.py +1 -0
- ksadk/kernel/bootstrap.py +28 -4
- ksadk/kernel/contract_fingerprints.py +5 -4
- ksadk/kernel/contracts.py +8 -0
- ksadk/kernel/control.py +1 -0
- ksadk/kernel/ingress.py +36 -2
- ksadk/kernel/memory_store.py +1 -0
- ksadk/kernel/postgres_store.py +1 -0
- ksadk/kernel/sqlite_store.py +28 -0
- ksadk/kernel/store.py +3 -0
- ksadk/kernel/worker.py +76 -10
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/models.py +7 -4
- ksadk/memory/provider_resolver.py +3 -0
- ksadk/memory/providers/local_sqlite.py +7 -0
- ksadk/model_proxy/server.py +10 -5
- ksadk/plugins/__init__.py +171 -0
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +47 -0
- ksadk/plugins/bridges/codex.py +659 -0
- ksadk/plugins/bridges/dsh.py +1300 -0
- ksadk/plugins/builtins.py +746 -0
- ksadk/plugins/bundle.py +246 -0
- ksadk/plugins/bundle_security.py +191 -0
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/composition.py +537 -0
- ksadk/plugins/context_contributor.py +437 -0
- ksadk/plugins/contracts.py +569 -0
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_toolchain.py +1024 -0
- ksadk/plugins/ecosystem_bridge.py +1105 -0
- ksadk/plugins/ecosystem_probe.py +191 -0
- ksadk/plugins/host.py +787 -0
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +108 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
- ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
- ksadk/plugins/providers/codex.py +988 -0
- ksadk/plugins/providers/codex_dsh.py +83 -0
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh.py +951 -0
- ksadk/plugins/providers/dsh_capabilities.py +1389 -0
- ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +632 -0
- ksadk/plugins/providers/harness_dsh.py +91 -0
- ksadk/plugins/providers/legacy.py +215 -0
- ksadk/plugins/providers/legacy_catalog.py +100 -0
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/providers/shipped_dsh.py +370 -0
- ksadk/plugins/resolver.py +338 -0
- ksadk/plugins/subagent_providers/__init__.py +12 -0
- ksadk/plugins/subagent_providers/codex.py +443 -0
- ksadk/plugins/subagents.py +333 -0
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +74 -6
- ksadk/runners/adk_runner.py +149 -11
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +475 -145
- ksadk/runtime/_runner_adapter/stream_mapping.py +193 -60
- ksadk/runtime/adapter.py +3 -0
- ksadk/runtime/conversation_execution.py +92 -16
- ksadk/runtime/executor.py +78 -2
- ksadk/runtime/factory.py +30 -200
- ksadk/runtime/framework_adapters.py +41 -0
- ksadk/runtime/preprocessing.py +10 -2
- ksadk/runtime/runner_adapter.py +78 -14
- ksadk/runtime_context.py +40 -2
- ksadk/sandbox/__init__.py +2 -1
- ksadk/sandbox/backends/e2b.py +52 -11
- ksadk/sandbox/backends/local_process.py +9 -0
- ksadk/sandbox/base.py +2 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/sandbox/factory.py +72 -0
- ksadk/scheduler/__init__.py +18 -0
- ksadk/scheduler/calendar.py +102 -0
- ksadk/scheduler/contracts.py +254 -0
- ksadk/scheduler/dispatcher.py +129 -0
- ksadk/scheduler/engine.py +416 -0
- ksadk/scheduler/sqlite_store.py +581 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/control.py +210 -46
- ksadk/server/routes/dependencies.py +15 -0
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/sessions.py +284 -107
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-b4C7upmO.js} +3 -3
- ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
- ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock-BEBN4Ksz.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
- ksadk/server/static/assets/{arc-C4FzinUA.js → arc-bTohInsS.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
- ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-UBpgon5q.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
- ksadk/server/static/assets/{dist-B7seoj3d.js → dist-B2_CVgKv.js} +1 -1
- ksadk/server/static/assets/{dist-CSh_DE14.js → dist-B3FR1SKK.js} +1 -1
- ksadk/server/static/assets/{dist-DUX-id_F.js → dist-BIr4DSRq.js} +1 -1
- ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-BgV_owcB.js} +1 -1
- ksadk/server/static/assets/{dist-W-TIVntx.js → dist-Bj730Ib4.js} +1 -1
- ksadk/server/static/assets/{dist-BytlxIDT.js → dist-BnaTiyzN.js} +1 -1
- ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C1NMAY5a.js} +1 -1
- ksadk/server/static/assets/{dist-dDdADKFA.js → dist-C5_ZAZsG.js} +1 -1
- ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-CB9iJrvg.js} +1 -1
- ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-CFzsn6BG.js} +1 -1
- ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-Cf125P_m.js} +1 -1
- ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-ClYUxfeK.js} +1 -1
- ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DFD6Qa6T.js} +1 -1
- ksadk/server/static/assets/{dist-BX8z72IC.js → dist-DVCOWtha.js} +1 -1
- ksadk/server/static/assets/{dist-dydu68Fl.js → dist-D_ctSS2i.js} +1 -1
- ksadk/server/static/assets/{dist-ClxGviKw.js → dist-DiixqL0J.js} +1 -1
- ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-DoVSwoDb.js} +1 -1
- ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-DvFK7p5S.js} +1 -1
- ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-QfkEHOlb.js} +1 -1
- ksadk/server/static/assets/{dist-CttYUqzS.js → dist-btbmmX5O.js} +1 -1
- ksadk/server/static/assets/{dist-DmldrHd_.js → dist-fBO2v5Kt.js} +1 -1
- ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-ufY3F5p6.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
- ksadk/server/static/assets/index-DcTML1Up.css +2 -0
- ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
- ksadk/server/static/assets/{katex-vFWytM5c.js → katex-B4weu383.js} +1 -1
- ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-V-MgYHW1.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-CBijEX_c.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/models.py +26 -4
- ksadk/skills/package_store.py +186 -38
- ksadk/skills/runtime/agent.py +31 -6
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/backends/e2b.py +98 -6
- ksadk/skills/runtime/backends/local.py +73 -8
- ksadk/skills/runtime/base.py +3 -0
- ksadk/skills/runtime/executor.py +2 -0
- ksadk/skills/runtime/loader.py +10 -2
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +31 -0
- ksadk/skills/service_client.py +211 -24
- ksadk/studio/agent_lifecycle.py +26 -20
- ksadk/studio/api.py +714 -90
- ksadk/studio/api_catalog_routes.py +23 -0
- ksadk/studio/api_contracts.py +34 -1
- ksadk/studio/api_plugin_routes.py +911 -0
- ksadk/studio/api_resource_connections.py +183 -0
- ksadk/studio/attachment_store.py +187 -0
- ksadk/studio/authoring.py +10 -4
- ksadk/studio/authoring_coordinator.py +31 -16
- ksadk/studio/builder.py +199 -43
- ksadk/studio/cloud.py +346 -104
- ksadk/studio/cloud_shared_web.py +565 -0
- ksadk/studio/codex_agent_service.py +140 -27
- ksadk/studio/codex_builder.py +294 -16
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +51 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +200 -29
- ksadk/studio/compatibility_report.py +456 -0
- ksadk/studio/compiler.py +84 -15
- ksadk/studio/contracts.py +249 -4
- ksadk/studio/dsh_application.py +137 -0
- ksadk/studio/dsh_capability_service.py +1107 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +1075 -0
- ksadk/studio/event_store.py +54 -6
- ksadk/studio/framework_run.py +37 -4
- ksadk/studio/hosted_kernel.py +89 -14
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +2 -2
- ksadk/studio/operations.py +12 -2
- ksadk/studio/plugin_composition.py +468 -0
- ksadk/studio/plugin_kernel_adapter.py +28 -0
- ksadk/studio/plugin_runtime.py +831 -0
- ksadk/studio/resource_authority.py +637 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +149 -3
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_service.py +1144 -96
- ksadk/studio/runtime_source.py +24 -8
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +383 -0
- ksadk/studio/scheduler_service.py +214 -0
- ksadk/studio/service.py +1131 -95
- ksadk/studio/shared_web.py +610 -87
- ksadk/studio/soul.py +52 -0
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
- ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
- ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
- ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/validator.py +1 -1
- ksadk/studio/workspace.py +1 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/workspace_files/path_utils.py +41 -0
- agentengine_sdk_python-0.8.2.dist-info/RECORD +0 -778
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
- ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
- ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
- ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
- ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,870 @@
|
|
|
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] === 'ks2') return parseResourceToken(parts, token, profileDigest, tools, allowExpired)
|
|
113
|
+
if (parts.length !== 3 || parts[0] !== 'ks1') return null
|
|
114
|
+
const [, payloadEncoded, signature] = parts
|
|
115
|
+
const expected = createHmac('sha256', token).update(payloadEncoded).digest('base64url')
|
|
116
|
+
if (!secureTokenEqual(signature, expected)) return null
|
|
117
|
+
let payload
|
|
118
|
+
try {
|
|
119
|
+
payload = JSON.parse(Buffer.from(payloadEncoded, 'base64url').toString('utf8'))
|
|
120
|
+
} catch {
|
|
121
|
+
return null
|
|
122
|
+
}
|
|
123
|
+
if (
|
|
124
|
+
payload === null ||
|
|
125
|
+
typeof payload !== 'object' ||
|
|
126
|
+
Array.isArray(payload) ||
|
|
127
|
+
payload.v !== 1 ||
|
|
128
|
+
payload.profileDigest !== profileDigest ||
|
|
129
|
+
typeof payload.jti !== 'string' ||
|
|
130
|
+
!/^[A-Za-z0-9_-]{16,64}$/.test(payload.jti) ||
|
|
131
|
+
!Number.isSafeInteger(payload.exp) ||
|
|
132
|
+
(!allowExpired && payload.exp < Math.floor(Date.now() / 1000)) ||
|
|
133
|
+
payload.exp > Math.floor(Date.now() / 1000) + 86_400 ||
|
|
134
|
+
payload.aliases === null ||
|
|
135
|
+
typeof payload.aliases !== 'object' ||
|
|
136
|
+
Array.isArray(payload.aliases) ||
|
|
137
|
+
Object.keys(payload.aliases).length < 1 ||
|
|
138
|
+
Object.keys(payload.aliases).length > 32
|
|
139
|
+
) return null
|
|
140
|
+
const aliases = new Map(Object.entries(payload.aliases))
|
|
141
|
+
if ([...aliases].some(([alias, source]) =>
|
|
142
|
+
!/^[A-Za-z0-9_-]{1,64}$/.test(alias) ||
|
|
143
|
+
typeof source !== 'string' ||
|
|
144
|
+
!tools.some((tool) => tool.name === source)
|
|
145
|
+
)) return null
|
|
146
|
+
return { root: false, scopeId: signature, aliases, expiresAt: payload.exp }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function parseResourceToken(parts, token, profileDigest, tools, allowExpired) {
|
|
150
|
+
if (parts.length !== 3) return null
|
|
151
|
+
const [, encoded, signature] = parts
|
|
152
|
+
const expected = createHmac('sha256', token).update(`ks2.${encoded}`).digest('base64url')
|
|
153
|
+
if (!secureTokenEqual(signature, expected)) return null
|
|
154
|
+
let payload
|
|
155
|
+
try { payload = JSON.parse(Buffer.from(encoded, 'base64url').toString('utf8')) }
|
|
156
|
+
catch { return null }
|
|
157
|
+
const record = value => value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
158
|
+
const ref = value => typeof value === 'string' && /^\S{1,256}$/u.test(value)
|
|
159
|
+
const now = Math.floor(Date.now() / 1000)
|
|
160
|
+
if (!record(payload) || payload.v !== 2 || payload.profileDigest !== profileDigest ||
|
|
161
|
+
!ref(payload.generationId) || !ref(payload.activationId) ||
|
|
162
|
+
!DIGEST_PATTERN.test(payload.buildDigest ?? '') || !DIGEST_PATTERN.test(payload.bindingSnapshotDigest ?? '') ||
|
|
163
|
+
!Number.isSafeInteger(payload.issuedAt) || !Number.isSafeInteger(payload.expiresAt) ||
|
|
164
|
+
payload.issuedAt > now + 5 || payload.expiresAt <= payload.issuedAt ||
|
|
165
|
+
payload.expiresAt - payload.issuedAt > 600 || (!allowExpired && payload.expiresAt <= now) ||
|
|
166
|
+
typeof payload.jti !== 'string' || !/^[A-Za-z0-9_-]{16,64}$/.test(payload.jti) ||
|
|
167
|
+
!record(payload.identity) || !record(payload.aliases) || !record(payload.resources)) return null
|
|
168
|
+
const identityKeys = ['tenantRef', 'resourcePrincipalRef', 'actorRef', 'memorySubjectRef', 'agentId', 'sessionRef']
|
|
169
|
+
if (Object.keys(payload.identity).length !== identityKeys.length ||
|
|
170
|
+
identityKeys.some(key => !ref(payload.identity[key]))) return null
|
|
171
|
+
const aliases = new Map(Object.entries(payload.aliases))
|
|
172
|
+
if (!aliases.size || aliases.size > 32 || [...aliases].some(([alias, source]) =>
|
|
173
|
+
!/^[A-Za-z0-9_-]{1,64}$/.test(alias) || typeof source !== 'string' ||
|
|
174
|
+
!tools.some(tool => tool.name === source))) return null
|
|
175
|
+
const resources = new Map(Object.entries(payload.resources))
|
|
176
|
+
if (!resources.size || resources.size > 32 || [...resources].some(([source, item]) =>
|
|
177
|
+
![...aliases.values()].includes(source) || !record(item) || !ref(item.bindingId) ||
|
|
178
|
+
item.operation !== source || typeof item.handle !== 'string' ||
|
|
179
|
+
!/^[A-Za-z0-9_-]{32,256}$/.test(item.handle))) return null
|
|
180
|
+
return { root: false, scopeId: signature, aliases, resources, expiresAt: payload.expiresAt }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function authorize(request, token, profileDigest, tools, revokedScopes) {
|
|
184
|
+
const header = request.headers.authorization
|
|
185
|
+
if (typeof header !== 'string' || !header.startsWith('Bearer ')) return null
|
|
186
|
+
if (secureTokenEqual(header, `Bearer ${token}`)) {
|
|
187
|
+
return { root: true, scopeId: 'root', aliases: null, expiresAt: null }
|
|
188
|
+
}
|
|
189
|
+
const now = Math.floor(Date.now() / 1000)
|
|
190
|
+
for (const [scopeId, expiresAt] of revokedScopes) {
|
|
191
|
+
if (expiresAt < now) revokedScopes.delete(scopeId)
|
|
192
|
+
}
|
|
193
|
+
const authorization = parseScopedToken(
|
|
194
|
+
header.slice('Bearer '.length), token, profileDigest, tools)
|
|
195
|
+
if (authorization === null || revokedScopes.has(authorization.scopeId)) return null
|
|
196
|
+
return authorization
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function originAllowed(request) {
|
|
200
|
+
const origin = request.headers.origin
|
|
201
|
+
if (origin === undefined) return true
|
|
202
|
+
if (Array.isArray(origin) || origin.length > 2048) return false
|
|
203
|
+
try {
|
|
204
|
+
const parsed = new URL(origin)
|
|
205
|
+
return (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&
|
|
206
|
+
(parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' || parsed.hostname === '[::1]')
|
|
207
|
+
} catch {
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function writeJson(response, status, payload, extraHeaders = {}) {
|
|
213
|
+
const body = Buffer.from(JSON.stringify(payload), 'utf8')
|
|
214
|
+
response.writeHead(status, {
|
|
215
|
+
'Cache-Control': 'no-store',
|
|
216
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
217
|
+
'Content-Length': String(body.length),
|
|
218
|
+
...extraHeaders,
|
|
219
|
+
})
|
|
220
|
+
response.end(body)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function writeEmpty(response, status) {
|
|
224
|
+
response.writeHead(status, {
|
|
225
|
+
'Cache-Control': 'no-store',
|
|
226
|
+
'Content-Length': '0',
|
|
227
|
+
})
|
|
228
|
+
response.end()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function jsonRpcError(id, code, message, data) {
|
|
232
|
+
return {
|
|
233
|
+
jsonrpc: '2.0',
|
|
234
|
+
id: id ?? null,
|
|
235
|
+
error: {
|
|
236
|
+
code,
|
|
237
|
+
message,
|
|
238
|
+
...(data === undefined ? {} : { data }),
|
|
239
|
+
},
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function readBody(request, maximum) {
|
|
244
|
+
return new Promise((resolve, reject) => {
|
|
245
|
+
const declared = Number(request.headers['content-length'])
|
|
246
|
+
if (Number.isFinite(declared) && declared > maximum) {
|
|
247
|
+
request.resume()
|
|
248
|
+
reject(new RequestTooLargeError('request body exceeds the configured limit'))
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
const chunks = []
|
|
252
|
+
let size = 0
|
|
253
|
+
let settled = false
|
|
254
|
+
request.on('data', (chunk) => {
|
|
255
|
+
if (settled) return
|
|
256
|
+
size += chunk.length
|
|
257
|
+
if (size > maximum) {
|
|
258
|
+
settled = true
|
|
259
|
+
chunks.length = 0
|
|
260
|
+
reject(new RequestTooLargeError('request body exceeds the configured limit'))
|
|
261
|
+
return
|
|
262
|
+
}
|
|
263
|
+
chunks.push(chunk)
|
|
264
|
+
})
|
|
265
|
+
request.on('end', () => {
|
|
266
|
+
if (!settled) resolve(Buffer.concat(chunks).toString('utf8'))
|
|
267
|
+
})
|
|
268
|
+
request.on('error', (error) => {
|
|
269
|
+
if (!settled) reject(error)
|
|
270
|
+
})
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function snapshotTools(runtime, maximumBytes) {
|
|
275
|
+
const raw = runtime.schemas()
|
|
276
|
+
if (!Array.isArray(raw) || raw.length > 2048) {
|
|
277
|
+
throw new Error('DSH tool inventory is invalid or too large')
|
|
278
|
+
}
|
|
279
|
+
const seen = new Set()
|
|
280
|
+
const tools = raw.map((schema) => {
|
|
281
|
+
if (schema === null || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
282
|
+
throw new Error('DSH emitted an invalid tool schema')
|
|
283
|
+
}
|
|
284
|
+
const { name, description, parameters } = schema
|
|
285
|
+
if (
|
|
286
|
+
typeof name !== 'string' ||
|
|
287
|
+
name.length < 1 ||
|
|
288
|
+
name.length > 128 ||
|
|
289
|
+
!TOOL_NAME_PATTERN.test(name) ||
|
|
290
|
+
seen.has(name)
|
|
291
|
+
) {
|
|
292
|
+
throw new Error('DSH emitted an invalid or duplicate tool name')
|
|
293
|
+
}
|
|
294
|
+
if (typeof description !== 'string' || description.length > 16_384) {
|
|
295
|
+
throw new Error(`DSH tool ${name} emitted an invalid description`)
|
|
296
|
+
}
|
|
297
|
+
if (parameters === null || typeof parameters !== 'object' || Array.isArray(parameters)) {
|
|
298
|
+
throw new Error(`DSH tool ${name} emitted an invalid parameters schema`)
|
|
299
|
+
}
|
|
300
|
+
seen.add(name)
|
|
301
|
+
const detached = JSON.parse(JSON.stringify({
|
|
302
|
+
name,
|
|
303
|
+
description: Array.from(description).slice(0, 1024).join(''),
|
|
304
|
+
inputSchema: parameters,
|
|
305
|
+
}))
|
|
306
|
+
assertUnicodeScalars(detached)
|
|
307
|
+
if (byteLength(detached) > maximumBytes) {
|
|
308
|
+
throw new Error(`DSH tool ${name} schema exceeds the configured limit`)
|
|
309
|
+
}
|
|
310
|
+
return detached
|
|
311
|
+
})
|
|
312
|
+
tools.sort((left, right) =>
|
|
313
|
+
Buffer.compare(Buffer.from(left.name, 'utf8'), Buffer.from(right.name, 'utf8')))
|
|
314
|
+
if (byteLength(tools) > maximumBytes) {
|
|
315
|
+
throw new Error('DSH tool inventory exceeds the configured limit')
|
|
316
|
+
}
|
|
317
|
+
return tools
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function textContent(text) {
|
|
321
|
+
return { type: 'text', text: String(text) }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function projectContent(content) {
|
|
325
|
+
if (!Array.isArray(content)) return []
|
|
326
|
+
return content.map((block) => {
|
|
327
|
+
if (block !== null && typeof block === 'object' && !Array.isArray(block)) {
|
|
328
|
+
if (block.type === 'text' && typeof block.text === 'string') return textContent(block.text)
|
|
329
|
+
if (block.type === 'reasoning' && typeof block.text === 'string') return textContent(block.text)
|
|
330
|
+
const kind = typeof block.type === 'string' ? block.type : 'unknown'
|
|
331
|
+
return textContent(`[DSH ${kind} content is not representable on this MCP bridge]`)
|
|
332
|
+
}
|
|
333
|
+
return textContent('[DSH emitted an invalid content block]')
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function toolFailure(message, code = 'DSH_TOOL_BRIDGE_ERROR') {
|
|
338
|
+
return {
|
|
339
|
+
content: [textContent(`Error: ${message}`)],
|
|
340
|
+
isError: true,
|
|
341
|
+
_meta: { 'io.ksadk/dsh': { code } },
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function projectToolResult(result, maximumBytes, resourceInvocation = false) {
|
|
346
|
+
if (result === null || typeof result !== 'object' || Array.isArray(result)) {
|
|
347
|
+
return toolFailure('DSH returned an invalid tool result')
|
|
348
|
+
}
|
|
349
|
+
const content = projectContent(result.content)
|
|
350
|
+
const projected = {
|
|
351
|
+
content,
|
|
352
|
+
isError: result.isError === true,
|
|
353
|
+
}
|
|
354
|
+
if (result.isError === true) {
|
|
355
|
+
const failure = result.error
|
|
356
|
+
const message = failure && typeof failure.message === 'string'
|
|
357
|
+
? failure.message.slice(0, 16_384)
|
|
358
|
+
: 'DSH tool execution failed'
|
|
359
|
+
if (projected.content.length === 0) projected.content.push(textContent(`Error: ${message}`))
|
|
360
|
+
const code = failure?.info && typeof failure.info.code === 'string'
|
|
361
|
+
? failure.info.code.slice(0, 256)
|
|
362
|
+
: 'DSH_TOOL_ERROR'
|
|
363
|
+
projected._meta = { 'io.ksadk/dsh': { code } }
|
|
364
|
+
} else if (
|
|
365
|
+
result.value !== null &&
|
|
366
|
+
typeof result.value === 'object' &&
|
|
367
|
+
!Array.isArray(result.value)
|
|
368
|
+
) {
|
|
369
|
+
projected.structuredContent = result.value
|
|
370
|
+
// A successful Cordis invocation may carry a failed resource operation.
|
|
371
|
+
// Apply this domain contract only after authenticated resource admission;
|
|
372
|
+
// ordinary third-party values named "status" retain their existing meaning.
|
|
373
|
+
if (resourceInvocation && ['failed', 'unauthorized'].includes(result.value.status)) {
|
|
374
|
+
projected.isError = true
|
|
375
|
+
const code = typeof result.value.errorCode === 'string'
|
|
376
|
+
&& /^(RESOURCE|MEMORY|KNOWLEDGE|SKILL)_[A-Z_]{1,96}$/.test(result.value.errorCode)
|
|
377
|
+
? result.value.errorCode : 'RESOURCE_OPERATION_FAILED'
|
|
378
|
+
projected._meta = { 'io.ksadk/dsh': { code } }
|
|
379
|
+
}
|
|
380
|
+
} else if (projected.content.length === 0 && result.value !== undefined) {
|
|
381
|
+
projected.content.push(textContent(JSON.stringify(result.value)))
|
|
382
|
+
}
|
|
383
|
+
try {
|
|
384
|
+
if (byteLength(projected) <= maximumBytes) return projected
|
|
385
|
+
} catch {}
|
|
386
|
+
return toolFailure('DSH tool result exceeds the configured bridge limit', 'DSH_RESULT_TOO_LARGE')
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function requestKey(scopeId, id) {
|
|
390
|
+
return JSON.stringify([scopeId, typeof id, id])
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function abortOutcome(controller) {
|
|
394
|
+
return new Promise((resolve) => {
|
|
395
|
+
const finish = () => {
|
|
396
|
+
const reason = controller.signal.reason
|
|
397
|
+
resolve({
|
|
398
|
+
kind: 'aborted',
|
|
399
|
+
code: reason?.code === 'DEADLINE_EXCEEDED' ? 'DEADLINE_EXCEEDED' : 'ABORTED',
|
|
400
|
+
})
|
|
401
|
+
}
|
|
402
|
+
if (controller.signal.aborted) finish()
|
|
403
|
+
else controller.signal.addEventListener('abort', finish, { once: true })
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function validateRequestEnvelope(message) {
|
|
408
|
+
return message !== null &&
|
|
409
|
+
typeof message === 'object' &&
|
|
410
|
+
!Array.isArray(message) &&
|
|
411
|
+
message.jsonrpc === '2.0' &&
|
|
412
|
+
typeof message.method === 'string' &&
|
|
413
|
+
(
|
|
414
|
+
message.id === undefined ||
|
|
415
|
+
typeof message.id === 'string' ||
|
|
416
|
+
(typeof message.id === 'number' && Number.isSafeInteger(message.id))
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function normalizedProtocol(requested) {
|
|
421
|
+
return SUPPORTED_MCP_PROTOCOLS.has(requested) ? requested : MCP_PROTOCOL_VERSION
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function emitReadyRecord(record) {
|
|
425
|
+
process.stdout.write(`@@KSADK_DSH_CAPABILITY_READY@@${JSON.stringify(record)}\n`)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function emitRuntimeToken(token) {
|
|
429
|
+
process.stdout.write(`@@KSADK_DSH_CAPABILITY_TOKEN@@${token}\n`)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function emitBrowserToken(token) {
|
|
433
|
+
process.stdout.write(`@@KSADK_DSH_CORE_TOKEN@@${token}\n`)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export async function apply(ctx, config = {}) {
|
|
437
|
+
const profile = requiredEnvironment('KSADK_DSH_PROFILE', 64)
|
|
438
|
+
const profileDigest = requiredEnvironment('KSADK_DSH_PROFILE_DIGEST', 80)
|
|
439
|
+
const dshVersion = requiredEnvironment('KSADK_DSH_VERSION', 64)
|
|
440
|
+
requiredEnvironment('KSADK_DSH_CAPABILITY_READY_STDOUT', 8)
|
|
441
|
+
const token = randomBytes(48).toString('base64url')
|
|
442
|
+
if (!DIGEST_PATTERN.test(profileDigest)) throw new Error('KSADK_DSH_PROFILE_DIGEST is invalid')
|
|
443
|
+
|
|
444
|
+
const callTimeoutMs = positiveInteger(config.callTimeoutMs, DEFAULT_CALL_TIMEOUT_MS, 'callTimeoutMs', 3_600_000)
|
|
445
|
+
const maxArgumentBytes = positiveInteger(config.maxArgumentBytes, DEFAULT_MAX_ARGUMENT_BYTES, 'maxArgumentBytes', 8 * 1024 * 1024)
|
|
446
|
+
const maxResultBytes = positiveInteger(config.maxResultBytes, DEFAULT_MAX_RESULT_BYTES, 'maxResultBytes', 8 * 1024 * 1024)
|
|
447
|
+
const maxRequestBytes = positiveInteger(config.maxRequestBytes, DEFAULT_MAX_REQUEST_BYTES, 'maxRequestBytes', 8 * 1024 * 1024)
|
|
448
|
+
const maxInFlight = positiveInteger(config.maxInFlight, DEFAULT_MAX_IN_FLIGHT, 'maxInFlight', 1024)
|
|
449
|
+
const inventoryQuietMs = positiveInteger(config.inventoryQuietMs, 50, 'inventoryQuietMs', 5_000)
|
|
450
|
+
|
|
451
|
+
const pending = new Map()
|
|
452
|
+
const revokedScopes = new Map()
|
|
453
|
+
let draining = false
|
|
454
|
+
let drifted = false
|
|
455
|
+
let readyWritten = false
|
|
456
|
+
let lastToolChange = Date.now()
|
|
457
|
+
let tools = []
|
|
458
|
+
let resourceBridge = null
|
|
459
|
+
// A pending optional child does not add another Core or block ordinary tools.
|
|
460
|
+
// Its dependency lifecycle clears the reference when the resource plugin stops.
|
|
461
|
+
if (typeof ctx.inject === 'function') ctx.inject(['platformResources'], resourceCtx => {
|
|
462
|
+
const bridge = resourceCtx.platformResources
|
|
463
|
+
resourceBridge = bridge
|
|
464
|
+
resourceCtx.effect(() => () => { if (resourceBridge === bridge) resourceBridge = null })
|
|
465
|
+
})
|
|
466
|
+
let inventoryDigest = digest(tools)
|
|
467
|
+
|
|
468
|
+
let driftCheckTimer = null
|
|
469
|
+
ctx.on('tools/change', () => {
|
|
470
|
+
lastToolChange = Date.now()
|
|
471
|
+
// Upstream plugins (e.g. dsh-ssh) dispose+re-register the same tools when
|
|
472
|
+
// settings re-sync; the intermediate state has a different fingerprint but
|
|
473
|
+
// converges. Debounce: only mark drift if the fingerprint is still
|
|
474
|
+
// different after the quiet window settles.
|
|
475
|
+
if (readyWritten) {
|
|
476
|
+
if (driftCheckTimer !== null) clearTimeout(driftCheckTimer)
|
|
477
|
+
driftCheckTimer = setTimeout(() => {
|
|
478
|
+
driftCheckTimer = null
|
|
479
|
+
const next = snapshotTools(ctx.tools, maxRequestBytes)
|
|
480
|
+
if (digest(next) !== inventoryDigest) drifted = true
|
|
481
|
+
}, inventoryQuietMs)
|
|
482
|
+
}
|
|
483
|
+
}, { global: true })
|
|
484
|
+
|
|
485
|
+
const handleRequest = async (request, response) => {
|
|
486
|
+
response.setHeader('X-Content-Type-Options', 'nosniff')
|
|
487
|
+
response.setHeader('Referrer-Policy', 'no-referrer')
|
|
488
|
+
if (!originAllowed(request)) {
|
|
489
|
+
writeJson(response, 403, { error: 'origin_denied' })
|
|
490
|
+
return
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
let parsedUrl
|
|
494
|
+
try {
|
|
495
|
+
parsedUrl = new URL(request.url ?? '/', 'http://127.0.0.1')
|
|
496
|
+
} catch {
|
|
497
|
+
writeJson(response, 400, { error: 'invalid_url' })
|
|
498
|
+
return
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const authorization = authorize(request, token, profileDigest, tools, revokedScopes)
|
|
502
|
+
|
|
503
|
+
if (request.method === 'GET' && parsedUrl.pathname === '/health' && parsedUrl.search === '') {
|
|
504
|
+
if (authorization === null) {
|
|
505
|
+
response.setHeader('WWW-Authenticate', 'Bearer')
|
|
506
|
+
writeJson(response, 401, { error: 'unauthorized' })
|
|
507
|
+
return
|
|
508
|
+
}
|
|
509
|
+
writeJson(response, drifted || draining ? 503 : 200, {
|
|
510
|
+
protocolVersion: HOST_PROTOCOL,
|
|
511
|
+
healthy: !drifted && !draining,
|
|
512
|
+
profile,
|
|
513
|
+
profileDigest,
|
|
514
|
+
inventoryDigest,
|
|
515
|
+
toolCount: tools.length,
|
|
516
|
+
inFlight: pending.size,
|
|
517
|
+
drifted,
|
|
518
|
+
draining,
|
|
519
|
+
})
|
|
520
|
+
return
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (request.method !== 'POST' || parsedUrl.pathname !== '/mcp' || parsedUrl.search !== '') {
|
|
524
|
+
writeJson(response, 404, { error: 'not_found' })
|
|
525
|
+
return
|
|
526
|
+
}
|
|
527
|
+
if (authorization === null) {
|
|
528
|
+
response.setHeader('WWW-Authenticate', 'Bearer')
|
|
529
|
+
writeJson(response, 401, { error: 'unauthorized' })
|
|
530
|
+
return
|
|
531
|
+
}
|
|
532
|
+
if (!(request.headers['content-type'] ?? '').toLowerCase().startsWith('application/json')) {
|
|
533
|
+
writeJson(response, 415, { error: 'content_type_required' })
|
|
534
|
+
return
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
let message
|
|
538
|
+
try {
|
|
539
|
+
const body = await readBody(request, maxRequestBytes)
|
|
540
|
+
message = JSON.parse(body)
|
|
541
|
+
} catch (error) {
|
|
542
|
+
if (error instanceof RequestTooLargeError) {
|
|
543
|
+
writeJson(response, 413, { error: 'request_too_large' })
|
|
544
|
+
} else {
|
|
545
|
+
writeJson(response, 400, jsonRpcError(null, -32700, 'Parse error'))
|
|
546
|
+
}
|
|
547
|
+
return
|
|
548
|
+
}
|
|
549
|
+
if (!validateRequestEnvelope(message)) {
|
|
550
|
+
writeJson(response, 400, jsonRpcError(message?.id, -32600, 'Invalid Request'))
|
|
551
|
+
return
|
|
552
|
+
}
|
|
553
|
+
// A scoped request may have been authorized before a slow body finished
|
|
554
|
+
// while its activation was revoked by a concurrent root request.
|
|
555
|
+
if (!authorization.root && revokedScopes.has(authorization.scopeId)) {
|
|
556
|
+
response.setHeader('WWW-Authenticate', 'Bearer')
|
|
557
|
+
writeJson(response, 401, { error: 'unauthorized' })
|
|
558
|
+
return
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const isNotification = message.id === undefined
|
|
562
|
+
const params = message.params ?? {}
|
|
563
|
+
if (params === null || typeof params !== 'object' || Array.isArray(params)) {
|
|
564
|
+
if (isNotification) writeEmpty(response, 202)
|
|
565
|
+
else writeJson(response, 200, jsonRpcError(message.id, -32602, 'Invalid params'))
|
|
566
|
+
return
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (message.method === 'notifications/initialized') {
|
|
570
|
+
writeEmpty(response, 202)
|
|
571
|
+
return
|
|
572
|
+
}
|
|
573
|
+
if (message.method === 'notifications/cancelled') {
|
|
574
|
+
const error = new Error('MCP client cancelled the request')
|
|
575
|
+
error.code = 'ABORTED'
|
|
576
|
+
if (authorization.root) {
|
|
577
|
+
for (const active of pending.values()) {
|
|
578
|
+
if (active.requestIdKey === requestKey('', params.requestId)) {
|
|
579
|
+
active.controller.abort(error)
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
} else {
|
|
583
|
+
const active = pending.get(requestKey(authorization.scopeId, params.requestId))
|
|
584
|
+
if (active) active.controller.abort(error)
|
|
585
|
+
}
|
|
586
|
+
writeEmpty(response, 202)
|
|
587
|
+
return
|
|
588
|
+
}
|
|
589
|
+
if (isNotification) {
|
|
590
|
+
writeEmpty(response, 202)
|
|
591
|
+
return
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (message.method === 'initialize') {
|
|
595
|
+
if (typeof params.protocolVersion !== 'string') {
|
|
596
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'protocolVersion is required'))
|
|
597
|
+
return
|
|
598
|
+
}
|
|
599
|
+
writeJson(response, 200, {
|
|
600
|
+
jsonrpc: '2.0',
|
|
601
|
+
id: message.id,
|
|
602
|
+
result: {
|
|
603
|
+
protocolVersion: normalizedProtocol(params.protocolVersion),
|
|
604
|
+
capabilities: { tools: {} },
|
|
605
|
+
serverInfo: { name: '@kingsoftcloud/ksadk-dsh-capability-host', version: HOST_VERSION },
|
|
606
|
+
},
|
|
607
|
+
})
|
|
608
|
+
return
|
|
609
|
+
}
|
|
610
|
+
if (message.method === 'ping') {
|
|
611
|
+
writeJson(response, 200, { jsonrpc: '2.0', id: message.id, result: {} })
|
|
612
|
+
return
|
|
613
|
+
}
|
|
614
|
+
if (message.method === 'io.ksadk/scopes/revoke') {
|
|
615
|
+
if (!authorization.root || typeof params.token !== 'string' || params.token.length > 12 * 1024) {
|
|
616
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'valid scoped token is required'))
|
|
617
|
+
return
|
|
618
|
+
}
|
|
619
|
+
const scoped = parseScopedToken(params.token, token, profileDigest, tools, true)
|
|
620
|
+
if (scoped === null) {
|
|
621
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'valid scoped token is required'))
|
|
622
|
+
return
|
|
623
|
+
}
|
|
624
|
+
if (!revokedScopes.has(scoped.scopeId) && revokedScopes.size >= 4096) {
|
|
625
|
+
writeJson(response, 200, jsonRpcError(message.id, -32001, 'revocation capacity reached'))
|
|
626
|
+
return
|
|
627
|
+
}
|
|
628
|
+
revokedScopes.set(scoped.scopeId, scoped.expiresAt)
|
|
629
|
+
const error = new Error('MCP credential scope was revoked')
|
|
630
|
+
error.code = 'ABORTED'
|
|
631
|
+
for (const active of pending.values()) {
|
|
632
|
+
if (active.scopeId === scoped.scopeId) active.controller.abort(error)
|
|
633
|
+
}
|
|
634
|
+
writeJson(response, 200, {
|
|
635
|
+
jsonrpc: '2.0',
|
|
636
|
+
id: message.id,
|
|
637
|
+
result: { revoked: true },
|
|
638
|
+
})
|
|
639
|
+
return
|
|
640
|
+
}
|
|
641
|
+
if (draining || drifted) {
|
|
642
|
+
writeJson(response, 200, jsonRpcError(message.id, -32002, 'DSH capability inventory is unavailable'))
|
|
643
|
+
return
|
|
644
|
+
}
|
|
645
|
+
if (message.method === 'tools/list') {
|
|
646
|
+
if (params.cursor !== undefined && params.cursor !== null && params.cursor !== '') {
|
|
647
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'cursor is not supported'))
|
|
648
|
+
return
|
|
649
|
+
}
|
|
650
|
+
const candidates = authorization.aliases === null
|
|
651
|
+
? tools
|
|
652
|
+
: [...authorization.aliases].filter(([, source]) =>
|
|
653
|
+
!resourceBridge?.operationForTool(source) || authorization.resources?.has(source)
|
|
654
|
+
).map(([alias, source]) => {
|
|
655
|
+
const tool = tools.find((item) => item.name === source)
|
|
656
|
+
return { ...tool, name: alias }
|
|
657
|
+
})
|
|
658
|
+
const checked = await Promise.all(candidates.map(async tool => {
|
|
659
|
+
const source = authorization.aliases?.get(tool.name)
|
|
660
|
+
const resource = authorization.resources?.get(source)
|
|
661
|
+
if (!resource) return tool
|
|
662
|
+
if (!resourceBridge || resourceBridge.operationForTool(source) !== resource.operation) return null
|
|
663
|
+
try {
|
|
664
|
+
const result = await resourceBridge.withInvocation({
|
|
665
|
+
handle: resource.handle,
|
|
666
|
+
deadline: Math.min(Date.now() + 3000, authorization.expiresAt * 1000),
|
|
667
|
+
}, () => resourceBridge.check(resource.operation))
|
|
668
|
+
return result.available === true ? tool : null
|
|
669
|
+
} catch { return null }
|
|
670
|
+
}))
|
|
671
|
+
if (!authorization.root && (revokedScopes.has(authorization.scopeId) ||
|
|
672
|
+
authorization.expiresAt * 1000 <= Date.now())) {
|
|
673
|
+
response.setHeader('WWW-Authenticate', 'Bearer')
|
|
674
|
+
writeJson(response, 401, { error: 'unauthorized' })
|
|
675
|
+
return
|
|
676
|
+
}
|
|
677
|
+
const visibleTools = checked.filter(Boolean)
|
|
678
|
+
writeJson(response, 200, { jsonrpc: '2.0', id: message.id, result: { tools: visibleTools } })
|
|
679
|
+
return
|
|
680
|
+
}
|
|
681
|
+
if (message.method !== 'tools/call') {
|
|
682
|
+
writeJson(response, 200, jsonRpcError(message.id, -32601, 'Method not found'))
|
|
683
|
+
return
|
|
684
|
+
}
|
|
685
|
+
if (typeof params.name !== 'string') {
|
|
686
|
+
writeJson(response, 200, {
|
|
687
|
+
jsonrpc: '2.0',
|
|
688
|
+
id: message.id,
|
|
689
|
+
result: toolFailure('unknown DSH tool', 'UNKNOWN_TOOL'),
|
|
690
|
+
})
|
|
691
|
+
return
|
|
692
|
+
}
|
|
693
|
+
const sourceToolName = authorization.aliases === null
|
|
694
|
+
? params.name
|
|
695
|
+
: authorization.aliases.get(params.name)
|
|
696
|
+
if (sourceToolName === undefined) {
|
|
697
|
+
writeJson(response, 200, jsonRpcError(message.id, -32003, 'Tool is outside credential scope'))
|
|
698
|
+
return
|
|
699
|
+
}
|
|
700
|
+
if (!tools.some((tool) => tool.name === sourceToolName)) {
|
|
701
|
+
writeJson(response, 200, {
|
|
702
|
+
jsonrpc: '2.0',
|
|
703
|
+
id: message.id,
|
|
704
|
+
result: toolFailure('unknown DSH tool', 'UNKNOWN_TOOL'),
|
|
705
|
+
})
|
|
706
|
+
return
|
|
707
|
+
}
|
|
708
|
+
const resourceOperation = resourceBridge?.operationForTool(sourceToolName)
|
|
709
|
+
const resourceScope = authorization.resources?.get(sourceToolName)
|
|
710
|
+
if ((resourceOperation || resourceScope) &&
|
|
711
|
+
(!resourceBridge || !resourceScope || resourceScope.operation !== resourceOperation)) {
|
|
712
|
+
writeJson(response, 200, { jsonrpc: '2.0', id: message.id,
|
|
713
|
+
result: toolFailure('Resource invocation context is required', 'RESOURCE_CONTEXT_REQUIRED') })
|
|
714
|
+
return
|
|
715
|
+
}
|
|
716
|
+
const argumentsValue = params.arguments ?? {}
|
|
717
|
+
if (argumentsValue === null || typeof argumentsValue !== 'object' || Array.isArray(argumentsValue)) {
|
|
718
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments must be an object'))
|
|
719
|
+
return
|
|
720
|
+
}
|
|
721
|
+
try {
|
|
722
|
+
if (byteLength(argumentsValue) > maxArgumentBytes) {
|
|
723
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments exceed the configured limit'))
|
|
724
|
+
return
|
|
725
|
+
}
|
|
726
|
+
} catch {
|
|
727
|
+
writeJson(response, 200, jsonRpcError(message.id, -32602, 'tool arguments must be JSON'))
|
|
728
|
+
return
|
|
729
|
+
}
|
|
730
|
+
if (pending.size >= maxInFlight) {
|
|
731
|
+
writeJson(response, 200, jsonRpcError(message.id, -32001, 'too many in-flight tool calls'))
|
|
732
|
+
return
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
const key = requestKey(authorization.scopeId, message.id)
|
|
736
|
+
if (pending.has(key)) {
|
|
737
|
+
writeJson(response, 200, jsonRpcError(message.id, -32600, 'duplicate in-flight request id'))
|
|
738
|
+
return
|
|
739
|
+
}
|
|
740
|
+
const controller = new AbortController()
|
|
741
|
+
const timeout = setTimeout(() => {
|
|
742
|
+
const error = new Error('DSH tool call deadline exceeded')
|
|
743
|
+
error.code = 'DEADLINE_EXCEEDED'
|
|
744
|
+
controller.abort(error)
|
|
745
|
+
}, callTimeoutMs)
|
|
746
|
+
const completion = Promise.resolve()
|
|
747
|
+
.then(() => {
|
|
748
|
+
const invoke = () => ctx.tools.execute({
|
|
749
|
+
callId: `mcp-${randomUUID()}`, name: sourceToolName,
|
|
750
|
+
arguments: argumentsValue, signal: controller.signal,
|
|
751
|
+
})
|
|
752
|
+
return resourceScope ? resourceBridge.withInvocation({
|
|
753
|
+
handle: resourceScope.handle,
|
|
754
|
+
deadline: Math.min(Date.now() + callTimeoutMs, authorization.expiresAt * 1000),
|
|
755
|
+
signal: controller.signal,
|
|
756
|
+
}, invoke) : invoke()
|
|
757
|
+
})
|
|
758
|
+
.then(
|
|
759
|
+
(result) => ({ kind: 'result', result }),
|
|
760
|
+
(error) => ({ kind: 'error', error }),
|
|
761
|
+
)
|
|
762
|
+
pending.set(key, {
|
|
763
|
+
controller,
|
|
764
|
+
completion,
|
|
765
|
+
scopeId: authorization.scopeId,
|
|
766
|
+
requestIdKey: requestKey('', message.id),
|
|
767
|
+
})
|
|
768
|
+
response.on('close', () => {
|
|
769
|
+
if (!response.writableEnded) {
|
|
770
|
+
const error = new Error('MCP client disconnected')
|
|
771
|
+
error.code = 'ABORTED'
|
|
772
|
+
controller.abort(error)
|
|
773
|
+
}
|
|
774
|
+
})
|
|
775
|
+
let completed = false
|
|
776
|
+
try {
|
|
777
|
+
const outcome = await Promise.race([completion, abortOutcome(controller)])
|
|
778
|
+
completed = outcome.kind !== 'aborted'
|
|
779
|
+
if (outcome.kind === 'result') {
|
|
780
|
+
writeJson(response, 200, {
|
|
781
|
+
jsonrpc: '2.0',
|
|
782
|
+
id: message.id,
|
|
783
|
+
result: projectToolResult(outcome.result, maxResultBytes, Boolean(resourceScope)),
|
|
784
|
+
})
|
|
785
|
+
} else if (outcome.kind === 'aborted') {
|
|
786
|
+
const messageText = outcome.code === 'DEADLINE_EXCEEDED'
|
|
787
|
+
? 'DSH tool call deadline exceeded'
|
|
788
|
+
: 'DSH tool call was cancelled'
|
|
789
|
+
writeJson(response, 200, {
|
|
790
|
+
jsonrpc: '2.0',
|
|
791
|
+
id: message.id,
|
|
792
|
+
result: toolFailure(messageText, outcome.code),
|
|
793
|
+
})
|
|
794
|
+
} else {
|
|
795
|
+
writeJson(response, 200, jsonRpcError(message.id, -32603, 'DSH tool pipeline failed'))
|
|
796
|
+
}
|
|
797
|
+
} finally {
|
|
798
|
+
clearTimeout(timeout)
|
|
799
|
+
if (completed) pending.delete(key)
|
|
800
|
+
else {
|
|
801
|
+
void completion.then(() => pending.delete(key))
|
|
802
|
+
// AbortSignal is cooperative. A third-party Cordis tool may ignore it
|
|
803
|
+
// forever, so an aborted call cannot be allowed to retain one in-flight
|
|
804
|
+
// slot indefinitely. Give a cooperative tool a short unwind window;
|
|
805
|
+
// otherwise crash this isolated generation and let the Python
|
|
806
|
+
// supervisor reap the process group and start a clean generation.
|
|
807
|
+
const abortGrace = setTimeout(() => {
|
|
808
|
+
if (!pending.has(key)) return
|
|
809
|
+
draining = true
|
|
810
|
+
process.exit(70)
|
|
811
|
+
}, 250)
|
|
812
|
+
abortGrace.unref()
|
|
813
|
+
void completion.then(() => clearTimeout(abortGrace))
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
const disposeMcp = ctx.webServer.register({ kind: 'exact', path: '/mcp', handler: handleRequest })
|
|
818
|
+
const disposeHealth = ctx.webServer.register({ kind: 'exact', path: '/health', handler: handleRequest })
|
|
819
|
+
ctx.effect(() => () => {
|
|
820
|
+
draining = true
|
|
821
|
+
for (const entry of pending.values()) {
|
|
822
|
+
entry.controller.abort(new Error('DSH capability host is stopping'))
|
|
823
|
+
}
|
|
824
|
+
disposeHealth()
|
|
825
|
+
disposeMcp()
|
|
826
|
+
})
|
|
827
|
+
|
|
828
|
+
// Reset the quiet baseline after the official Core server has activated:
|
|
829
|
+
// plugins may still be registering tools while the overlay starts.
|
|
830
|
+
lastToolChange = Date.now()
|
|
831
|
+
while (Date.now() - lastToolChange < inventoryQuietMs) {
|
|
832
|
+
await new Promise((resolve) => setTimeout(resolve, inventoryQuietMs))
|
|
833
|
+
}
|
|
834
|
+
tools = snapshotTools(ctx.tools, maxRequestBytes)
|
|
835
|
+
inventoryDigest = digest(tools)
|
|
836
|
+
const port = ctx.webServer.port
|
|
837
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65535 || ctx.webServer.host !== '127.0.0.1') {
|
|
838
|
+
throw new Error('DSH Core webServer must bind a loopback TCP port')
|
|
839
|
+
}
|
|
840
|
+
const coreUrl = new URL(ctx.connection.authenticatedUrl(`http://127.0.0.1:${port}`))
|
|
841
|
+
const browserTokens = coreUrl.searchParams.getAll('token')
|
|
842
|
+
if (
|
|
843
|
+
coreUrl.protocol !== 'http:' ||
|
|
844
|
+
coreUrl.hostname !== '127.0.0.1' ||
|
|
845
|
+
coreUrl.port !== String(port) ||
|
|
846
|
+
coreUrl.pathname !== '/' ||
|
|
847
|
+
coreUrl.hash !== '' ||
|
|
848
|
+
[...coreUrl.searchParams.keys()].some((key) => key !== 'token') ||
|
|
849
|
+
browserTokens.length !== 1 ||
|
|
850
|
+
!/^[A-Za-z0-9_-]{32,128}$/.test(browserTokens[0])
|
|
851
|
+
) {
|
|
852
|
+
throw new Error('DSH Core connection did not provide an authenticated browser URL')
|
|
853
|
+
}
|
|
854
|
+
readyWritten = true
|
|
855
|
+
emitRuntimeToken(token)
|
|
856
|
+
emitBrowserToken(browserTokens[0])
|
|
857
|
+
emitReadyRecord({
|
|
858
|
+
protocolVersion: HOST_PROTOCOL,
|
|
859
|
+
hostVersion: HOST_VERSION,
|
|
860
|
+
dshVersion,
|
|
861
|
+
profile,
|
|
862
|
+
profileDigest,
|
|
863
|
+
definition: 'mcp.connector/v1',
|
|
864
|
+
transport: 'streamable-http',
|
|
865
|
+
endpoint: `http://127.0.0.1:${port}/mcp`,
|
|
866
|
+
inventoryDigest,
|
|
867
|
+
tools,
|
|
868
|
+
webRouteCount: 2,
|
|
869
|
+
})
|
|
870
|
+
}
|