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,1075 @@
|
|
|
1
|
+
"""Managed DSH AgentProvider registration for the normal Studio lifecycle.
|
|
2
|
+
|
|
3
|
+
Studio treats the selected DSH Profile as the installed/enabled source of
|
|
4
|
+
truth, then starts each AgentProvider contribution in its own fixed-command
|
|
5
|
+
sidecar. Only descriptor-fenced, ready registrations enter Studio's selector;
|
|
6
|
+
ordinary client-only DSH bundles remain visible to plugin management without
|
|
7
|
+
being mistaken for AgentProviders.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import json
|
|
14
|
+
import os
|
|
15
|
+
import shutil
|
|
16
|
+
import tempfile
|
|
17
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any, Literal
|
|
21
|
+
|
|
22
|
+
import yaml
|
|
23
|
+
from pydantic import BaseModel, ConfigDict
|
|
24
|
+
|
|
25
|
+
from ksadk.plugins.bridges.dsh import (
|
|
26
|
+
DshPluginInventory,
|
|
27
|
+
DshProfilePluginBridge,
|
|
28
|
+
DshProfileProjection,
|
|
29
|
+
)
|
|
30
|
+
from ksadk.plugins.contracts import CompositionProfile, PluginManifest
|
|
31
|
+
from ksadk.plugins.dsh_toolchain import DSH_CORE_PACKAGES, DshToolchainManager
|
|
32
|
+
from ksadk.plugins.host import ManagedPlugin, PluginHostError
|
|
33
|
+
from ksadk.plugins.providers.codex_dsh import (
|
|
34
|
+
SHIPPED_CODEX_DSH_PACKAGE,
|
|
35
|
+
SHIPPED_CODEX_PROVIDER_VERSION,
|
|
36
|
+
KsADKCodexDshBridgeFactory,
|
|
37
|
+
shipped_codex_dsh_bundle,
|
|
38
|
+
shipped_codex_dsh_host_command,
|
|
39
|
+
)
|
|
40
|
+
from ksadk.plugins.providers.dsh import (
|
|
41
|
+
DshAgentProviderFactory,
|
|
42
|
+
DshAgentProviderHost,
|
|
43
|
+
DshAgentProviderRegistration,
|
|
44
|
+
)
|
|
45
|
+
from ksadk.plugins.providers.harness_dsh import (
|
|
46
|
+
SHIPPED_HARNESS_DSH_PACKAGE,
|
|
47
|
+
SHIPPED_HARNESS_PROVIDER_VERSION,
|
|
48
|
+
KsADKHarnessDshBridgeFactory,
|
|
49
|
+
shipped_harness_dsh_bundle,
|
|
50
|
+
shipped_harness_dsh_host_command,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
_PROFILE_FILES = ("package.json", "cordis.patch.yml", "index.mjs")
|
|
54
|
+
_MAX_PACKAGE_JSON_BYTES = 2 * 1024 * 1024
|
|
55
|
+
_DSH_PLATFORM_BUNDLES = frozenset(DSH_CORE_PACKAGES)
|
|
56
|
+
_SHIPPED_PROVIDER_PACKAGES = frozenset({SHIPPED_CODEX_DSH_PACKAGE, SHIPPED_HARNESS_DSH_PACKAGE})
|
|
57
|
+
_SHIPPED_RESOURCE_PACKAGES = (
|
|
58
|
+
("@kingsoftcloud/dsh-platform-resources", "dsh-platform-resources"),
|
|
59
|
+
("@kingsoftcloud/dsh-knowledge", "dsh-knowledge"),
|
|
60
|
+
("@kingsoftcloud/dsh-memory", "dsh-memory"),
|
|
61
|
+
("@kingsoftcloud/dsh-skill-center", "dsh-skill-center"),
|
|
62
|
+
)
|
|
63
|
+
_SHIPPED_RESOURCE_VERSION = "0.1.0"
|
|
64
|
+
_RESOURCE_RUNTIME_BUNDLE = "@deepseek-ai/dsh-web-app"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class StudioDshProviderRegistrationError(RuntimeError):
|
|
68
|
+
"""A selected DSH Profile could not produce trustworthy registrations."""
|
|
69
|
+
|
|
70
|
+
def __init__(self, code: str, message: str) -> None:
|
|
71
|
+
super().__init__(message)
|
|
72
|
+
self.code = code
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class StudioDshProviderStatus(BaseModel):
|
|
76
|
+
"""Lifecycle evidence for one installed DSH Profile package."""
|
|
77
|
+
|
|
78
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
79
|
+
|
|
80
|
+
package_name: str
|
|
81
|
+
package_version: str
|
|
82
|
+
display_name: str = ""
|
|
83
|
+
state: Literal["installed", "enabled", "ready", "bound", "failed", "disposed"]
|
|
84
|
+
provider_ref: str | None = None
|
|
85
|
+
error_code: str | None = None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class StudioDshProviderInventory(BaseModel):
|
|
89
|
+
model_config = ConfigDict(extra="forbid", frozen=True)
|
|
90
|
+
|
|
91
|
+
state: Literal["stopped", "starting", "ready", "bound", "failed", "disposed"]
|
|
92
|
+
profile: str
|
|
93
|
+
profile_digest: str | None = None
|
|
94
|
+
providers: tuple[str, ...] = ()
|
|
95
|
+
packages: tuple[StudioDshProviderStatus, ...] = ()
|
|
96
|
+
error_code: str | None = None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@dataclass(frozen=True)
|
|
100
|
+
class StudioDshProviderRegistrations:
|
|
101
|
+
manifests: Mapping[str, PluginManifest]
|
|
102
|
+
factories: Mapping[str, Any]
|
|
103
|
+
inventory: StudioDshProviderInventory
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class _ProfileSnapshot:
|
|
108
|
+
projection: DshProfileProjection
|
|
109
|
+
packages: tuple[DshPluginInventory, ...]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
BridgeFactory = Callable[..., DshProfilePluginBridge]
|
|
113
|
+
HostFactory = Callable[..., DshAgentProviderHost]
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class _FreshDshAgentProviderFactory:
|
|
117
|
+
"""Give every PluginHost graph an independently owned provider process."""
|
|
118
|
+
|
|
119
|
+
def __init__(
|
|
120
|
+
self,
|
|
121
|
+
command: Sequence[str],
|
|
122
|
+
*,
|
|
123
|
+
projection: DshProfileProjection,
|
|
124
|
+
cwd: Path,
|
|
125
|
+
environment: Mapping[str, str],
|
|
126
|
+
registration: DshAgentProviderRegistration,
|
|
127
|
+
host_factory: HostFactory,
|
|
128
|
+
) -> None:
|
|
129
|
+
self._command = tuple(command)
|
|
130
|
+
self._projection = projection
|
|
131
|
+
self._cwd = cwd
|
|
132
|
+
self._environment = dict(environment)
|
|
133
|
+
self._registration = registration
|
|
134
|
+
self._host_factory = host_factory
|
|
135
|
+
|
|
136
|
+
async def stage(
|
|
137
|
+
self,
|
|
138
|
+
manifest: PluginManifest,
|
|
139
|
+
*,
|
|
140
|
+
profile: CompositionProfile,
|
|
141
|
+
services: Mapping[str, Any],
|
|
142
|
+
) -> ManagedPlugin:
|
|
143
|
+
host = self._host_factory(
|
|
144
|
+
self._command,
|
|
145
|
+
projection=self._projection,
|
|
146
|
+
cwd=self._cwd,
|
|
147
|
+
environment=self._environment,
|
|
148
|
+
)
|
|
149
|
+
try:
|
|
150
|
+
current = await host.registration()
|
|
151
|
+
if current != self._registration:
|
|
152
|
+
raise PluginHostError(
|
|
153
|
+
"dsh_provider_registration_changed",
|
|
154
|
+
"DSH provider registration changed after Studio discovery",
|
|
155
|
+
)
|
|
156
|
+
return await DshAgentProviderFactory(host, current).stage(
|
|
157
|
+
manifest,
|
|
158
|
+
profile=profile,
|
|
159
|
+
services=services,
|
|
160
|
+
)
|
|
161
|
+
except BaseException:
|
|
162
|
+
await host.dispose()
|
|
163
|
+
raise
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class _FreshShippedDshBridgeFactory:
|
|
167
|
+
"""Bind a shipped provider to a host owned by the consuming PluginHost loop."""
|
|
168
|
+
|
|
169
|
+
def __init__(
|
|
170
|
+
self,
|
|
171
|
+
command: Sequence[str],
|
|
172
|
+
*,
|
|
173
|
+
projection: DshProfileProjection,
|
|
174
|
+
cwd: Path,
|
|
175
|
+
environment: Mapping[str, str],
|
|
176
|
+
registration: DshAgentProviderRegistration,
|
|
177
|
+
package_name: str,
|
|
178
|
+
host_factory: HostFactory,
|
|
179
|
+
) -> None:
|
|
180
|
+
self._command = tuple(command)
|
|
181
|
+
self._projection = projection
|
|
182
|
+
self._cwd = cwd
|
|
183
|
+
self._environment = dict(environment)
|
|
184
|
+
self._registration = registration
|
|
185
|
+
self._package_name = package_name
|
|
186
|
+
self._host_factory = host_factory
|
|
187
|
+
|
|
188
|
+
async def stage(
|
|
189
|
+
self,
|
|
190
|
+
manifest: PluginManifest,
|
|
191
|
+
*,
|
|
192
|
+
profile: CompositionProfile,
|
|
193
|
+
services: Mapping[str, Any],
|
|
194
|
+
) -> ManagedPlugin:
|
|
195
|
+
host = self._host_factory(
|
|
196
|
+
self._command,
|
|
197
|
+
projection=self._projection,
|
|
198
|
+
cwd=self._cwd,
|
|
199
|
+
environment=self._environment,
|
|
200
|
+
)
|
|
201
|
+
try:
|
|
202
|
+
current = await host.registration()
|
|
203
|
+
if current != self._registration:
|
|
204
|
+
raise PluginHostError(
|
|
205
|
+
"dsh_provider_registration_changed",
|
|
206
|
+
"DSH provider registration changed after Studio discovery",
|
|
207
|
+
)
|
|
208
|
+
if self._package_name == SHIPPED_CODEX_DSH_PACKAGE:
|
|
209
|
+
factory: Any = KsADKCodexDshBridgeFactory(host, current, owns_host=True)
|
|
210
|
+
elif self._package_name == SHIPPED_HARNESS_DSH_PACKAGE:
|
|
211
|
+
factory = KsADKHarnessDshBridgeFactory(host, current, owns_host=True)
|
|
212
|
+
else: # guarded by _register_package
|
|
213
|
+
raise PluginHostError(
|
|
214
|
+
"dsh_provider_package_unsupported",
|
|
215
|
+
"shipped DSH provider package is unsupported",
|
|
216
|
+
)
|
|
217
|
+
return await factory.stage(manifest, profile=profile, services=services)
|
|
218
|
+
except BaseException:
|
|
219
|
+
await host.dispose()
|
|
220
|
+
raise
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class StudioDshProviderRegistrationManager:
|
|
224
|
+
"""Own Profile discovery, provider preflight, registration, and disposal."""
|
|
225
|
+
|
|
226
|
+
def __init__(
|
|
227
|
+
self,
|
|
228
|
+
workspace: Path,
|
|
229
|
+
*,
|
|
230
|
+
dsh_home: Path,
|
|
231
|
+
profile: str = "web",
|
|
232
|
+
dsh_command: Sequence[str] | None = None,
|
|
233
|
+
node_command: Sequence[str] | None = None,
|
|
234
|
+
cordis_module: Path | None = None,
|
|
235
|
+
bridge_factory: BridgeFactory = DshProfilePluginBridge,
|
|
236
|
+
host_factory: HostFactory = DshAgentProviderHost,
|
|
237
|
+
) -> None:
|
|
238
|
+
self._workspace = workspace.resolve()
|
|
239
|
+
self._dsh_home = dsh_home.expanduser().resolve()
|
|
240
|
+
self._profile = profile
|
|
241
|
+
self._dsh_command = tuple(dsh_command) if dsh_command is not None else None
|
|
242
|
+
self._node_command = tuple(node_command) if node_command is not None else None
|
|
243
|
+
self._cordis_module = cordis_module.resolve() if cordis_module is not None else None
|
|
244
|
+
self._bridge_factory = bridge_factory
|
|
245
|
+
self._host_factory = host_factory
|
|
246
|
+
self._lock = asyncio.Lock()
|
|
247
|
+
self._hosts: dict[str, DshAgentProviderHost] = {}
|
|
248
|
+
self._registrations: StudioDshProviderRegistrations | None = None
|
|
249
|
+
self._inventory = StudioDshProviderInventory(state="stopped", profile=profile)
|
|
250
|
+
|
|
251
|
+
@classmethod
|
|
252
|
+
def discover(cls, workspace: Path) -> "StudioDshProviderRegistrationManager | None":
|
|
253
|
+
"""Discover an initialized managed Profile without downloading tools."""
|
|
254
|
+
|
|
255
|
+
configured_home = os.environ.get("KSADK_DSH_HOME", "").strip()
|
|
256
|
+
home = (
|
|
257
|
+
Path(configured_home).expanduser()
|
|
258
|
+
if configured_home
|
|
259
|
+
else workspace / ".agentkit" / "dsh-home"
|
|
260
|
+
)
|
|
261
|
+
profile = os.environ.get("KSADK_DSH_PROFILE", "").strip() or "web"
|
|
262
|
+
configured_bin = os.environ.get("KSADK_DSH_BIN", "").strip()
|
|
263
|
+
manifest = home / "profiles" / profile / "package.json"
|
|
264
|
+
if not manifest.is_file():
|
|
265
|
+
return None
|
|
266
|
+
try:
|
|
267
|
+
payload = json.loads(manifest.read_text(encoding="utf-8"))
|
|
268
|
+
except (OSError, UnicodeError, json.JSONDecodeError):
|
|
269
|
+
return None
|
|
270
|
+
dsh = payload.get("dsh") if isinstance(payload, dict) else None
|
|
271
|
+
profile_payload = dsh.get("profile") if isinstance(dsh, dict) else None
|
|
272
|
+
bundles = profile_payload.get("bundles") if isinstance(profile_payload, dict) else None
|
|
273
|
+
if not isinstance(bundles, list) or any(not isinstance(item, str) for item in bundles):
|
|
274
|
+
return None
|
|
275
|
+
command = (str(Path(configured_bin).expanduser()),) if configured_bin else None
|
|
276
|
+
return cls(workspace, dsh_home=home, profile=profile, dsh_command=command)
|
|
277
|
+
|
|
278
|
+
@classmethod
|
|
279
|
+
def discover_or_create_workspace_default(
|
|
280
|
+
cls, workspace: Path
|
|
281
|
+
) -> "StudioDshProviderRegistrationManager | None":
|
|
282
|
+
"""Discover DSH or prepare the isolated first-run Studio Profile.
|
|
283
|
+
|
|
284
|
+
The default is deliberately narrower than :meth:`discover`: only the
|
|
285
|
+
Studio-owned ``.agentkit/dsh-home`` and official ``web`` Profile qualify for
|
|
286
|
+
automatic official-provider bootstrap. Explicit DSH homes/profiles
|
|
287
|
+
are user-owned and are never mutated by Studio startup.
|
|
288
|
+
"""
|
|
289
|
+
|
|
290
|
+
configured_home = os.environ.get("KSADK_DSH_HOME", "").strip()
|
|
291
|
+
configured_profile = os.environ.get("KSADK_DSH_PROFILE", "").strip()
|
|
292
|
+
if configured_home or configured_profile:
|
|
293
|
+
return cls.discover(workspace)
|
|
294
|
+
root = workspace.resolve()
|
|
295
|
+
home = root / ".agentkit" / "dsh-home"
|
|
296
|
+
configured_bin = os.environ.get("KSADK_DSH_BIN", "").strip()
|
|
297
|
+
if configured_bin:
|
|
298
|
+
command: Sequence[str] | None = (str(Path(configured_bin).expanduser()),)
|
|
299
|
+
else:
|
|
300
|
+
try:
|
|
301
|
+
command = DshToolchainManager().require_command()
|
|
302
|
+
except Exception:
|
|
303
|
+
# DSH is optional. A missing toolchain must not make the
|
|
304
|
+
# normal Studio/legacy Codex path unavailable.
|
|
305
|
+
return None
|
|
306
|
+
return cls(root, dsh_home=home, profile="web", dsh_command=command)
|
|
307
|
+
|
|
308
|
+
@classmethod
|
|
309
|
+
def create_workspace_resource_default(
|
|
310
|
+
cls, workspace: Path
|
|
311
|
+
) -> "StudioDshProviderRegistrationManager | None":
|
|
312
|
+
"""Own the official-only Profile frozen into resource Builds."""
|
|
313
|
+
|
|
314
|
+
if os.environ.get("KSADK_DSH_HOME", "").strip() or os.environ.get(
|
|
315
|
+
"KSADK_DSH_PROFILE", ""
|
|
316
|
+
).strip():
|
|
317
|
+
return None
|
|
318
|
+
root = workspace.resolve()
|
|
319
|
+
configured_bin = os.environ.get("KSADK_DSH_BIN", "").strip()
|
|
320
|
+
if configured_bin:
|
|
321
|
+
command: Sequence[str] | None = (str(Path(configured_bin).expanduser()),)
|
|
322
|
+
else:
|
|
323
|
+
try:
|
|
324
|
+
command = DshToolchainManager().require_command()
|
|
325
|
+
except Exception:
|
|
326
|
+
return None
|
|
327
|
+
return cls(
|
|
328
|
+
root,
|
|
329
|
+
dsh_home=root / ".agentkit" / "dsh-home",
|
|
330
|
+
profile="agentkit-resources",
|
|
331
|
+
dsh_command=command,
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
@property
|
|
335
|
+
def inventory(self) -> StudioDshProviderInventory:
|
|
336
|
+
return self._inventory
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def _owns_workspace_default_profile(self) -> bool:
|
|
340
|
+
configured_home = os.environ.get("KSADK_DSH_HOME", "").strip()
|
|
341
|
+
configured_profile = os.environ.get("KSADK_DSH_PROFILE", "").strip()
|
|
342
|
+
expected_home = (self._workspace / ".agentkit" / "dsh-home").resolve()
|
|
343
|
+
return (
|
|
344
|
+
not configured_home
|
|
345
|
+
and not configured_profile
|
|
346
|
+
and self._profile in {"web", "agentkit-resources"}
|
|
347
|
+
and self._dsh_home == expected_home
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
async def bootstrap_official_codex_provider(
|
|
351
|
+
self,
|
|
352
|
+
) -> Literal["installed", "already_enabled", "disabled", "skipped"]:
|
|
353
|
+
"""Apply the wheel-owned Codex default once for the Studio Profile.
|
|
354
|
+
|
|
355
|
+
This method never enables an existing disabled package and never
|
|
356
|
+
mutates an explicit/user-owned DSH Profile. The marker also preserves
|
|
357
|
+
an explicit uninstall across future Studio starts.
|
|
358
|
+
"""
|
|
359
|
+
|
|
360
|
+
if not self._owns_workspace_default_profile:
|
|
361
|
+
return "skipped"
|
|
362
|
+
async with self._lock:
|
|
363
|
+
return await asyncio.to_thread(self._bootstrap_official_codex_provider_sync)
|
|
364
|
+
|
|
365
|
+
def _bootstrap_official_codex_provider_sync(
|
|
366
|
+
self,
|
|
367
|
+
) -> Literal["installed", "already_enabled", "disabled", "skipped"]:
|
|
368
|
+
"""Perform the blocking DSH package mutation outside the event loop."""
|
|
369
|
+
|
|
370
|
+
if not self._owns_workspace_default_profile:
|
|
371
|
+
return "skipped"
|
|
372
|
+
marker = self._default_marker_path
|
|
373
|
+
marker_payload = self._read_default_marker(marker)
|
|
374
|
+
command = self._dsh_command or DshToolchainManager().require_command()
|
|
375
|
+
shipped = shipped_codex_dsh_bundle()
|
|
376
|
+
with self._bridge_factory(
|
|
377
|
+
dsh_home=self._dsh_home,
|
|
378
|
+
profile=self._profile,
|
|
379
|
+
dsh_command=command,
|
|
380
|
+
cwd=self._workspace,
|
|
381
|
+
) as bridge:
|
|
382
|
+
self._repair_owned_profile_layout(bridge)
|
|
383
|
+
installed = {item.name: item for item in bridge.list_plugins()}
|
|
384
|
+
current = installed.get(SHIPPED_CODEX_DSH_PACKAGE)
|
|
385
|
+
if current is None:
|
|
386
|
+
if marker_payload.get("codexProviderApplied") is True:
|
|
387
|
+
return "skipped"
|
|
388
|
+
current = bridge.install_plugin(str(shipped.root), accept_host_permissions=True)
|
|
389
|
+
if current.name != SHIPPED_CODEX_DSH_PACKAGE:
|
|
390
|
+
raise StudioDshProviderRegistrationError(
|
|
391
|
+
"codex_dsh_package_mismatch",
|
|
392
|
+
"the official Codex install returned a different package",
|
|
393
|
+
)
|
|
394
|
+
result: Literal["installed", "already_enabled", "disabled"] = "installed"
|
|
395
|
+
else:
|
|
396
|
+
result = "already_enabled" if current.enabled else "disabled"
|
|
397
|
+
if current.version != SHIPPED_CODEX_PROVIDER_VERSION:
|
|
398
|
+
raise StudioDshProviderRegistrationError(
|
|
399
|
+
"codex_dsh_bundle_not_active",
|
|
400
|
+
"the official Codex DSH Bundle version is not supported",
|
|
401
|
+
)
|
|
402
|
+
if not current.enabled and result == "installed":
|
|
403
|
+
current = bridge.set_enabled(SHIPPED_CODEX_DSH_PACKAGE, enabled=True)
|
|
404
|
+
if not current.enabled:
|
|
405
|
+
raise StudioDshProviderRegistrationError(
|
|
406
|
+
"codex_dsh_enable_failed",
|
|
407
|
+
"the official Codex DSH Bundle did not become enabled",
|
|
408
|
+
)
|
|
409
|
+
self._verify_shipped_bundle_bytes(SHIPPED_CODEX_DSH_PACKAGE)
|
|
410
|
+
if marker_payload.get("codexProviderApplied") is not True:
|
|
411
|
+
self._write_default_marker(
|
|
412
|
+
marker,
|
|
413
|
+
{
|
|
414
|
+
**marker_payload,
|
|
415
|
+
"version": 1,
|
|
416
|
+
"codexProviderApplied": True,
|
|
417
|
+
"codexProviderVersion": SHIPPED_CODEX_PROVIDER_VERSION,
|
|
418
|
+
},
|
|
419
|
+
)
|
|
420
|
+
return result
|
|
421
|
+
|
|
422
|
+
async def bootstrap_official_resource_plugins(
|
|
423
|
+
self,
|
|
424
|
+
) -> Literal["installed", "already_enabled", "disabled", "skipped"]:
|
|
425
|
+
"""Apply the wheel-owned platform-resource stack once to Studio's Profile."""
|
|
426
|
+
|
|
427
|
+
if not self._owns_workspace_default_profile:
|
|
428
|
+
return "skipped"
|
|
429
|
+
async with self._lock:
|
|
430
|
+
return await asyncio.to_thread(self._bootstrap_official_resource_plugins_sync)
|
|
431
|
+
|
|
432
|
+
def _bootstrap_official_resource_plugins_sync(
|
|
433
|
+
self,
|
|
434
|
+
) -> Literal["installed", "already_enabled", "disabled", "skipped"]:
|
|
435
|
+
if not self._owns_workspace_default_profile:
|
|
436
|
+
return "skipped"
|
|
437
|
+
marker = self._default_marker_path
|
|
438
|
+
marker_payload = self._read_default_marker(marker)
|
|
439
|
+
command = self._dsh_command or DshToolchainManager().require_command()
|
|
440
|
+
installed_any = False
|
|
441
|
+
disabled = False
|
|
442
|
+
enable_defaults = marker_payload.get("platformResourcesEnabled") is not True
|
|
443
|
+
with self._bridge_factory(
|
|
444
|
+
dsh_home=self._dsh_home,
|
|
445
|
+
profile=self._profile,
|
|
446
|
+
dsh_command=command,
|
|
447
|
+
cwd=self._workspace,
|
|
448
|
+
) as bridge:
|
|
449
|
+
self._repair_owned_profile_layout(bridge)
|
|
450
|
+
inventory = {item.name: item for item in bridge.list_plugins()}
|
|
451
|
+
for package_name, directory_name in _SHIPPED_RESOURCE_PACKAGES:
|
|
452
|
+
current = inventory.get(package_name)
|
|
453
|
+
if current is None:
|
|
454
|
+
# A completed marker plus a missing package records a later,
|
|
455
|
+
# explicit uninstall. Startup must preserve that choice.
|
|
456
|
+
if marker_payload.get("platformResourcesApplied") is True:
|
|
457
|
+
continue
|
|
458
|
+
root = (
|
|
459
|
+
Path(__file__).parents[1]
|
|
460
|
+
/ "plugins"
|
|
461
|
+
/ "providers"
|
|
462
|
+
/ "bundles"
|
|
463
|
+
/ directory_name
|
|
464
|
+
)
|
|
465
|
+
current = bridge.install_plugin(
|
|
466
|
+
str(root), accept_host_permissions=True
|
|
467
|
+
)
|
|
468
|
+
if current.name != package_name:
|
|
469
|
+
raise StudioDshProviderRegistrationError(
|
|
470
|
+
"resource_dsh_package_mismatch",
|
|
471
|
+
"an official resource install returned a different package",
|
|
472
|
+
)
|
|
473
|
+
installed_any = True
|
|
474
|
+
if current.version != _SHIPPED_RESOURCE_VERSION:
|
|
475
|
+
raise StudioDshProviderRegistrationError(
|
|
476
|
+
"resource_dsh_bundle_not_active",
|
|
477
|
+
"an official platform resource Bundle version is not supported",
|
|
478
|
+
)
|
|
479
|
+
if not current.enabled and enable_defaults:
|
|
480
|
+
current = bridge.set_enabled(package_name, enabled=True)
|
|
481
|
+
if not current.enabled:
|
|
482
|
+
raise StudioDshProviderRegistrationError(
|
|
483
|
+
"resource_dsh_enable_failed",
|
|
484
|
+
"an official platform resource Bundle did not become enabled",
|
|
485
|
+
)
|
|
486
|
+
disabled = disabled or not current.enabled
|
|
487
|
+
self._verify_shipped_resource_bundle_bytes(package_name, directory_name)
|
|
488
|
+
if self._profile == "agentkit-resources":
|
|
489
|
+
self._ensure_resource_runtime_bundle()
|
|
490
|
+
if marker_payload.get("platformResourcesApplied") is not True:
|
|
491
|
+
self._write_default_marker(
|
|
492
|
+
marker,
|
|
493
|
+
{
|
|
494
|
+
**marker_payload,
|
|
495
|
+
"version": 1,
|
|
496
|
+
"platformResourcesApplied": True,
|
|
497
|
+
"platformResourcesEnabled": True,
|
|
498
|
+
"platformResourcesVersion": _SHIPPED_RESOURCE_VERSION,
|
|
499
|
+
},
|
|
500
|
+
)
|
|
501
|
+
elif enable_defaults:
|
|
502
|
+
self._write_default_marker(
|
|
503
|
+
marker,
|
|
504
|
+
{**marker_payload, "platformResourcesEnabled": True},
|
|
505
|
+
)
|
|
506
|
+
if disabled:
|
|
507
|
+
return "disabled"
|
|
508
|
+
return "installed" if installed_any else "already_enabled"
|
|
509
|
+
|
|
510
|
+
def _ensure_resource_runtime_bundle(self) -> None:
|
|
511
|
+
"""Give the private resource Profile the official loopback transport.
|
|
512
|
+
|
|
513
|
+
The capability exporter uses DSH's authenticated ``webServer`` and
|
|
514
|
+
``connection`` services even when no browser UI is mounted. Custom
|
|
515
|
+
Profiles start with only ``dsh-base``, so the Studio-owned execution
|
|
516
|
+
Profile must explicitly include DSH's official web runtime layer.
|
|
517
|
+
"""
|
|
518
|
+
|
|
519
|
+
manifest_path = self._profile_root / "package.json"
|
|
520
|
+
try:
|
|
521
|
+
if manifest_path.stat().st_size > _MAX_PACKAGE_JSON_BYTES:
|
|
522
|
+
raise ValueError("package.json is too large")
|
|
523
|
+
payload = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
524
|
+
dsh = payload.get("dsh")
|
|
525
|
+
profile = dsh.get("profile") if isinstance(dsh, dict) else None
|
|
526
|
+
bundles = profile.get("bundles") if isinstance(profile, dict) else None
|
|
527
|
+
if not isinstance(bundles, list) or any(
|
|
528
|
+
not isinstance(item, str) for item in bundles
|
|
529
|
+
):
|
|
530
|
+
raise ValueError("bundle order is invalid")
|
|
531
|
+
except (OSError, UnicodeError, json.JSONDecodeError, ValueError) as error:
|
|
532
|
+
raise StudioDshProviderRegistrationError(
|
|
533
|
+
"resource_dsh_profile_invalid",
|
|
534
|
+
"the official resource execution Profile is invalid",
|
|
535
|
+
) from error
|
|
536
|
+
if _RESOURCE_RUNTIME_BUNDLE in bundles:
|
|
537
|
+
return
|
|
538
|
+
try:
|
|
539
|
+
base_index = bundles.index("@deepseek-ai/dsh-base")
|
|
540
|
+
except ValueError as error:
|
|
541
|
+
raise StudioDshProviderRegistrationError(
|
|
542
|
+
"resource_dsh_profile_invalid",
|
|
543
|
+
"the official resource execution Profile has no DSH base Bundle",
|
|
544
|
+
) from error
|
|
545
|
+
bundles.insert(base_index + 1, _RESOURCE_RUNTIME_BUNDLE)
|
|
546
|
+
self._write_default_marker(manifest_path, payload)
|
|
547
|
+
|
|
548
|
+
def _repair_owned_profile_layout(self, bridge: DshProfilePluginBridge) -> None:
|
|
549
|
+
"""Repair only Studio's default legacy Profile before projecting it.
|
|
550
|
+
|
|
551
|
+
Older Studio versions created the ``web`` Profile with pnpm's hoisted
|
|
552
|
+
linker. Some community dependency graphs then contained links to the
|
|
553
|
+
ambient pnpm store and could not form a closed Build snapshot. The
|
|
554
|
+
frozen lock remains the authority; the bridge keeps the original tree
|
|
555
|
+
as an atomic rollback point while reinstalling the isolated layout.
|
|
556
|
+
"""
|
|
557
|
+
|
|
558
|
+
if not self._owns_workspace_default_profile:
|
|
559
|
+
return
|
|
560
|
+
settings_path = self._dsh_home / "profiles" / self._profile / "pnpm-workspace.yaml"
|
|
561
|
+
if not settings_path.is_file():
|
|
562
|
+
return
|
|
563
|
+
try:
|
|
564
|
+
settings = yaml.safe_load(settings_path.read_text(encoding="utf-8"))
|
|
565
|
+
except (OSError, UnicodeError, yaml.YAMLError) as error:
|
|
566
|
+
raise StudioDshProviderRegistrationError(
|
|
567
|
+
"dsh_profile_layout_invalid",
|
|
568
|
+
"the Studio-owned DSH Profile layout settings are unreadable",
|
|
569
|
+
) from error
|
|
570
|
+
if not isinstance(settings, dict):
|
|
571
|
+
raise StudioDshProviderRegistrationError(
|
|
572
|
+
"dsh_profile_layout_invalid",
|
|
573
|
+
"the Studio-owned DSH Profile layout settings are invalid",
|
|
574
|
+
)
|
|
575
|
+
if settings.get("nodeLinker") not in {"hoisted", "isolated"}:
|
|
576
|
+
return
|
|
577
|
+
bridge.migrate_to_isolated_layout(
|
|
578
|
+
accept_host_permissions=True,
|
|
579
|
+
recover_external_dependency_links=True,
|
|
580
|
+
)
|
|
581
|
+
|
|
582
|
+
@property
|
|
583
|
+
def _default_marker_path(self) -> Path:
|
|
584
|
+
# Scope the bootstrap receipt to the owned Profile. Older Studio
|
|
585
|
+
# builds used one workspace-wide marker while their default Profile
|
|
586
|
+
# was ``studio``. Reusing that marker after the default moved to
|
|
587
|
+
# official Core's ``web`` Profile incorrectly skipped first-run
|
|
588
|
+
# installation and left Studio with no runnable DSH Profile.
|
|
589
|
+
return self._workspace / ".agentkit" / f"official-dsh-defaults-{self._profile}.json"
|
|
590
|
+
|
|
591
|
+
@staticmethod
|
|
592
|
+
def _read_default_marker(path: Path) -> dict[str, object]:
|
|
593
|
+
try:
|
|
594
|
+
payload = json.loads(path.read_text(encoding="utf-8")) if path.is_file() else {}
|
|
595
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as error:
|
|
596
|
+
raise StudioDshProviderRegistrationError(
|
|
597
|
+
"dsh_default_marker_invalid",
|
|
598
|
+
"the Studio official DSH defaults marker is unreadable",
|
|
599
|
+
) from error
|
|
600
|
+
if not isinstance(payload, dict):
|
|
601
|
+
raise StudioDshProviderRegistrationError(
|
|
602
|
+
"dsh_default_marker_invalid",
|
|
603
|
+
"the Studio official DSH defaults marker is invalid",
|
|
604
|
+
)
|
|
605
|
+
return payload
|
|
606
|
+
|
|
607
|
+
@staticmethod
|
|
608
|
+
def _write_default_marker(path: Path, payload: Mapping[str, object]) -> None:
|
|
609
|
+
path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
610
|
+
descriptor, temporary = tempfile.mkstemp(prefix=f".{path.name}.", dir=path.parent)
|
|
611
|
+
try:
|
|
612
|
+
with os.fdopen(descriptor, "w", encoding="utf-8") as handle:
|
|
613
|
+
json.dump(payload, handle, ensure_ascii=False, sort_keys=True)
|
|
614
|
+
handle.write("\n")
|
|
615
|
+
handle.flush()
|
|
616
|
+
os.fsync(handle.fileno())
|
|
617
|
+
os.chmod(temporary, 0o600)
|
|
618
|
+
os.replace(temporary, path)
|
|
619
|
+
finally:
|
|
620
|
+
try:
|
|
621
|
+
os.unlink(temporary)
|
|
622
|
+
except FileNotFoundError:
|
|
623
|
+
pass
|
|
624
|
+
|
|
625
|
+
@property
|
|
626
|
+
def host_pid(self) -> int | None:
|
|
627
|
+
return next(iter(self.host_pids), None)
|
|
628
|
+
|
|
629
|
+
@property
|
|
630
|
+
def host_pids(self) -> tuple[int, ...]:
|
|
631
|
+
return tuple(host.pid for host in self._hosts.values() if host.pid is not None)
|
|
632
|
+
|
|
633
|
+
async def start(self) -> StudioDshProviderRegistrations:
|
|
634
|
+
async with self._lock:
|
|
635
|
+
if self._registrations is not None:
|
|
636
|
+
return self._registrations
|
|
637
|
+
if self._inventory.state == "disposed":
|
|
638
|
+
raise StudioDshProviderRegistrationError(
|
|
639
|
+
"dsh_provider_manager_disposed",
|
|
640
|
+
"Studio DSH provider registration manager is disposed",
|
|
641
|
+
)
|
|
642
|
+
self._inventory = StudioDshProviderInventory(state="starting", profile=self._profile)
|
|
643
|
+
try:
|
|
644
|
+
snapshot = await asyncio.to_thread(self._discover_profile)
|
|
645
|
+
result = await self._register_snapshot(snapshot)
|
|
646
|
+
except BaseException as error:
|
|
647
|
+
await self._dispose_hosts()
|
|
648
|
+
code = str(getattr(error, "code", "dsh_provider_registration_failed"))
|
|
649
|
+
self._inventory = StudioDshProviderInventory(
|
|
650
|
+
state="failed", profile=self._profile, error_code=code
|
|
651
|
+
)
|
|
652
|
+
if isinstance(error, (asyncio.CancelledError, KeyboardInterrupt, SystemExit)):
|
|
653
|
+
raise
|
|
654
|
+
raise StudioDshProviderRegistrationError(
|
|
655
|
+
code,
|
|
656
|
+
"managed DSH Profile could not be projected safely",
|
|
657
|
+
) from error
|
|
658
|
+
self._registrations = result
|
|
659
|
+
self._inventory = result.inventory
|
|
660
|
+
return result
|
|
661
|
+
|
|
662
|
+
async def refresh(self) -> StudioDshProviderRegistrations:
|
|
663
|
+
async with self._lock:
|
|
664
|
+
if self._inventory.state == "disposed":
|
|
665
|
+
raise StudioDshProviderRegistrationError(
|
|
666
|
+
"dsh_provider_manager_disposed",
|
|
667
|
+
"Studio DSH provider registration manager is disposed",
|
|
668
|
+
)
|
|
669
|
+
self._registrations = None
|
|
670
|
+
await self._dispose_hosts()
|
|
671
|
+
self._inventory = StudioDshProviderInventory(state="stopped", profile=self._profile)
|
|
672
|
+
return await self.start()
|
|
673
|
+
|
|
674
|
+
def mark_bound(self, provider_refs: Sequence[str]) -> None:
|
|
675
|
+
if self._registrations is None or self._inventory.state != "ready":
|
|
676
|
+
raise StudioDshProviderRegistrationError(
|
|
677
|
+
"dsh_provider_registration_not_ready",
|
|
678
|
+
"DSH provider registrations cannot be bound before preflight",
|
|
679
|
+
)
|
|
680
|
+
expected = tuple(self._registrations.manifests)
|
|
681
|
+
if tuple(provider_refs) != expected:
|
|
682
|
+
raise StudioDshProviderRegistrationError(
|
|
683
|
+
"dsh_provider_registration_mismatch",
|
|
684
|
+
"Studio did not bind the exact ready DSH provider registration set",
|
|
685
|
+
)
|
|
686
|
+
packages = tuple(
|
|
687
|
+
item.model_copy(update={"state": "bound"})
|
|
688
|
+
if item.state == "ready" and item.provider_ref in expected
|
|
689
|
+
else item
|
|
690
|
+
for item in self._inventory.packages
|
|
691
|
+
)
|
|
692
|
+
self._inventory = self._inventory.model_copy(
|
|
693
|
+
update={"state": "bound", "packages": packages}
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
async def aclose(self) -> None:
|
|
697
|
+
async with self._lock:
|
|
698
|
+
self._registrations = None
|
|
699
|
+
await self._dispose_hosts()
|
|
700
|
+
packages = tuple(
|
|
701
|
+
item.model_copy(update={"state": "disposed"})
|
|
702
|
+
if item.state in {"ready", "bound"}
|
|
703
|
+
else item
|
|
704
|
+
for item in self._inventory.packages
|
|
705
|
+
)
|
|
706
|
+
self._inventory = StudioDshProviderInventory(
|
|
707
|
+
state="disposed",
|
|
708
|
+
profile=self._profile,
|
|
709
|
+
profile_digest=self._inventory.profile_digest,
|
|
710
|
+
packages=packages,
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
def _discover_profile(self) -> _ProfileSnapshot:
|
|
714
|
+
command = self._dsh_command or DshToolchainManager().require_command()
|
|
715
|
+
with self._bridge_factory(
|
|
716
|
+
dsh_home=self._dsh_home,
|
|
717
|
+
profile=self._profile,
|
|
718
|
+
dsh_command=command,
|
|
719
|
+
cwd=self._workspace,
|
|
720
|
+
) as bridge:
|
|
721
|
+
packages = bridge.list_plugins()
|
|
722
|
+
projection = bridge.project_profile()
|
|
723
|
+
enabled = {item.name for item in packages if item.enabled}
|
|
724
|
+
projected = set(projection.bundles)
|
|
725
|
+
if not enabled.issubset(projected) or projected - enabled - _DSH_PLATFORM_BUNDLES:
|
|
726
|
+
raise StudioDshProviderRegistrationError(
|
|
727
|
+
"dsh_provider_profile_inventory_mismatch",
|
|
728
|
+
"DSH installed inventory and projected Profile disagree",
|
|
729
|
+
)
|
|
730
|
+
return _ProfileSnapshot(projection=projection, packages=packages)
|
|
731
|
+
|
|
732
|
+
async def _register_snapshot(
|
|
733
|
+
self, snapshot: _ProfileSnapshot
|
|
734
|
+
) -> StudioDshProviderRegistrations:
|
|
735
|
+
manifests: dict[str, PluginManifest] = {}
|
|
736
|
+
factories: dict[str, Any] = {}
|
|
737
|
+
statuses = [
|
|
738
|
+
StudioDshProviderStatus(
|
|
739
|
+
package_name=item.name,
|
|
740
|
+
package_version=item.version,
|
|
741
|
+
display_name=item.display_name,
|
|
742
|
+
state="enabled" if item.enabled else "installed",
|
|
743
|
+
)
|
|
744
|
+
for item in snapshot.packages
|
|
745
|
+
]
|
|
746
|
+
provider_packages: dict[str, str] = {}
|
|
747
|
+
for index, package in enumerate(snapshot.packages):
|
|
748
|
+
if not package.enabled:
|
|
749
|
+
continue
|
|
750
|
+
host: DshAgentProviderHost | None = None
|
|
751
|
+
try:
|
|
752
|
+
registration, factory, host = await self._register_package(
|
|
753
|
+
package, snapshot.projection
|
|
754
|
+
)
|
|
755
|
+
if registration is None or factory is None or host is None:
|
|
756
|
+
continue
|
|
757
|
+
descriptor = registration.descriptor
|
|
758
|
+
provider_ref = f"plugin://{descriptor.provider_id}@{descriptor.provider_version}"
|
|
759
|
+
prior_package = provider_packages.get(provider_ref)
|
|
760
|
+
if prior_package is not None:
|
|
761
|
+
await host.dispose()
|
|
762
|
+
prior_host = self._hosts.pop(prior_package, None)
|
|
763
|
+
if prior_host is not None:
|
|
764
|
+
await prior_host.dispose()
|
|
765
|
+
manifests.pop(provider_ref, None)
|
|
766
|
+
factories.pop(provider_ref, None)
|
|
767
|
+
statuses[index] = statuses[index].model_copy(
|
|
768
|
+
update={
|
|
769
|
+
"state": "failed",
|
|
770
|
+
"provider_ref": provider_ref,
|
|
771
|
+
"error_code": "dsh_provider_registration_conflict",
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
for prior_index, status in enumerate(statuses):
|
|
775
|
+
if status.package_name == prior_package:
|
|
776
|
+
statuses[prior_index] = status.model_copy(
|
|
777
|
+
update={
|
|
778
|
+
"state": "failed",
|
|
779
|
+
"error_code": "dsh_provider_registration_conflict",
|
|
780
|
+
}
|
|
781
|
+
)
|
|
782
|
+
break
|
|
783
|
+
continue
|
|
784
|
+
provider_packages[provider_ref] = package.name
|
|
785
|
+
manifests[provider_ref] = registration.manifest
|
|
786
|
+
factories[provider_ref] = factory
|
|
787
|
+
# Discovery is a bounded admission probe. Keeping its process
|
|
788
|
+
# alive would bind Studio construction to that event loop and
|
|
789
|
+
# make later API or Scheduler loops reuse foreign transports.
|
|
790
|
+
# The fresh factory repeats the exact registration fence and
|
|
791
|
+
# owns its execution host in the consuming PluginHost loop.
|
|
792
|
+
await host.dispose()
|
|
793
|
+
statuses[index] = statuses[index].model_copy(
|
|
794
|
+
update={
|
|
795
|
+
"state": "ready",
|
|
796
|
+
"provider_ref": provider_ref,
|
|
797
|
+
"display_name": descriptor.display_name,
|
|
798
|
+
}
|
|
799
|
+
)
|
|
800
|
+
except BaseException as error:
|
|
801
|
+
if host is not None:
|
|
802
|
+
try:
|
|
803
|
+
await host.dispose()
|
|
804
|
+
except BaseException:
|
|
805
|
+
pass
|
|
806
|
+
if isinstance(error, (asyncio.CancelledError, KeyboardInterrupt, SystemExit)):
|
|
807
|
+
raise
|
|
808
|
+
statuses[index] = statuses[index].model_copy(
|
|
809
|
+
update={
|
|
810
|
+
"state": "failed",
|
|
811
|
+
"error_code": str(
|
|
812
|
+
getattr(error, "code", "dsh_provider_registration_failed")
|
|
813
|
+
),
|
|
814
|
+
}
|
|
815
|
+
)
|
|
816
|
+
inventory = StudioDshProviderInventory(
|
|
817
|
+
state="ready",
|
|
818
|
+
profile=self._profile,
|
|
819
|
+
profile_digest=snapshot.projection.config_digest,
|
|
820
|
+
providers=tuple(manifests),
|
|
821
|
+
packages=tuple(statuses),
|
|
822
|
+
)
|
|
823
|
+
return StudioDshProviderRegistrations(
|
|
824
|
+
manifests=manifests, factories=factories, inventory=inventory
|
|
825
|
+
)
|
|
826
|
+
|
|
827
|
+
async def _register_package(
|
|
828
|
+
self,
|
|
829
|
+
package: DshPluginInventory,
|
|
830
|
+
projection: DshProfileProjection,
|
|
831
|
+
) -> tuple[
|
|
832
|
+
DshAgentProviderRegistration | None,
|
|
833
|
+
Any | None,
|
|
834
|
+
DshAgentProviderHost | None,
|
|
835
|
+
]:
|
|
836
|
+
if package.name in _SHIPPED_PROVIDER_PACKAGES:
|
|
837
|
+
error_prefix = (
|
|
838
|
+
"codex_dsh" if package.name == SHIPPED_CODEX_DSH_PACKAGE else "harness_dsh"
|
|
839
|
+
)
|
|
840
|
+
expected_version = (
|
|
841
|
+
SHIPPED_CODEX_PROVIDER_VERSION
|
|
842
|
+
if package.name == SHIPPED_CODEX_DSH_PACKAGE
|
|
843
|
+
else SHIPPED_HARNESS_PROVIDER_VERSION
|
|
844
|
+
)
|
|
845
|
+
if package.version != expected_version:
|
|
846
|
+
raise StudioDshProviderRegistrationError(
|
|
847
|
+
f"{error_prefix}_bundle_not_active",
|
|
848
|
+
"the exact shipped DSH AgentProvider Bundle is not active",
|
|
849
|
+
)
|
|
850
|
+
self._verify_shipped_bundle_bytes(package.name)
|
|
851
|
+
command = (
|
|
852
|
+
shipped_codex_dsh_host_command()
|
|
853
|
+
if package.name == SHIPPED_CODEX_DSH_PACKAGE
|
|
854
|
+
else shipped_harness_dsh_host_command()
|
|
855
|
+
)
|
|
856
|
+
cwd = self._workspace
|
|
857
|
+
environment: dict[str, str] = {}
|
|
858
|
+
else:
|
|
859
|
+
entry = self._provider_host_entry(package.name)
|
|
860
|
+
if entry is None:
|
|
861
|
+
return None, None, None
|
|
862
|
+
command = (*self._resolve_node_command(), str(entry))
|
|
863
|
+
cwd = self._profile_root
|
|
864
|
+
environment = {"KSADK_DSH_CORDIS_MODULE": str(self._resolve_cordis_module())}
|
|
865
|
+
host = self._host_factory(
|
|
866
|
+
command,
|
|
867
|
+
projection=projection,
|
|
868
|
+
cwd=cwd,
|
|
869
|
+
environment=environment,
|
|
870
|
+
)
|
|
871
|
+
try:
|
|
872
|
+
registration = await host.registration()
|
|
873
|
+
if registration.descriptor.plugin_name != package.name:
|
|
874
|
+
raise PluginHostError(
|
|
875
|
+
"dsh_provider_package_mismatch",
|
|
876
|
+
"DSH provider descriptor does not match its installed package",
|
|
877
|
+
)
|
|
878
|
+
provider_inventory = await host.inventory()
|
|
879
|
+
if provider_inventory.state != "ready":
|
|
880
|
+
raise PluginHostError(
|
|
881
|
+
"dsh_provider_inventory_not_ready",
|
|
882
|
+
"DSH AgentProvider inventory is not ready",
|
|
883
|
+
)
|
|
884
|
+
if package.name in _SHIPPED_PROVIDER_PACKAGES:
|
|
885
|
+
factory: Any = _FreshShippedDshBridgeFactory(
|
|
886
|
+
command,
|
|
887
|
+
projection=projection,
|
|
888
|
+
cwd=cwd,
|
|
889
|
+
environment=environment,
|
|
890
|
+
registration=registration,
|
|
891
|
+
package_name=package.name,
|
|
892
|
+
host_factory=self._host_factory,
|
|
893
|
+
)
|
|
894
|
+
else:
|
|
895
|
+
factory = _FreshDshAgentProviderFactory(
|
|
896
|
+
command,
|
|
897
|
+
projection=projection,
|
|
898
|
+
cwd=cwd,
|
|
899
|
+
environment=environment,
|
|
900
|
+
registration=registration,
|
|
901
|
+
host_factory=self._host_factory,
|
|
902
|
+
)
|
|
903
|
+
return registration, factory, host
|
|
904
|
+
except BaseException:
|
|
905
|
+
await host.dispose()
|
|
906
|
+
raise
|
|
907
|
+
|
|
908
|
+
@property
|
|
909
|
+
def _profile_root(self) -> Path:
|
|
910
|
+
return self._dsh_home / "profiles" / self._profile
|
|
911
|
+
|
|
912
|
+
def _provider_host_entry(self, package_name: str) -> Path | None:
|
|
913
|
+
package_root = self._profile_root / "node_modules"
|
|
914
|
+
for segment in package_name.split("/"):
|
|
915
|
+
package_root /= segment
|
|
916
|
+
manifest_path = package_root / "package.json"
|
|
917
|
+
try:
|
|
918
|
+
if manifest_path.stat().st_size > _MAX_PACKAGE_JSON_BYTES:
|
|
919
|
+
raise ValueError("package.json is too large")
|
|
920
|
+
payload = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
921
|
+
except (OSError, UnicodeError, json.JSONDecodeError, ValueError) as error:
|
|
922
|
+
raise PluginHostError(
|
|
923
|
+
"dsh_provider_package_invalid",
|
|
924
|
+
"installed DSH provider package.json is invalid",
|
|
925
|
+
) from error
|
|
926
|
+
exports = payload.get("exports") if isinstance(payload, dict) else None
|
|
927
|
+
if not isinstance(exports, dict) or "./provider-host" not in exports:
|
|
928
|
+
return None
|
|
929
|
+
relative = exports.get("./provider-host")
|
|
930
|
+
if not isinstance(relative, str) or not relative.startswith("./"):
|
|
931
|
+
raise PluginHostError(
|
|
932
|
+
"dsh_provider_host_export_invalid",
|
|
933
|
+
"DSH provider-host export must be one relative file",
|
|
934
|
+
)
|
|
935
|
+
try:
|
|
936
|
+
resolved_root = package_root.resolve(strict=True)
|
|
937
|
+
entry = (resolved_root / relative).resolve(strict=True)
|
|
938
|
+
except (OSError, RuntimeError) as error:
|
|
939
|
+
raise PluginHostError(
|
|
940
|
+
"dsh_provider_host_unavailable",
|
|
941
|
+
"DSH provider-host export is unavailable",
|
|
942
|
+
) from error
|
|
943
|
+
if not entry.is_relative_to(resolved_root) or not entry.is_file():
|
|
944
|
+
raise PluginHostError(
|
|
945
|
+
"dsh_provider_host_export_invalid",
|
|
946
|
+
"DSH provider-host export escapes its installed package",
|
|
947
|
+
)
|
|
948
|
+
return entry
|
|
949
|
+
|
|
950
|
+
def _resolve_node_command(self) -> tuple[str, ...]:
|
|
951
|
+
if self._node_command is not None:
|
|
952
|
+
if not self._node_command:
|
|
953
|
+
raise PluginHostError("dsh_provider_node_unavailable", "Node command is empty")
|
|
954
|
+
return self._node_command
|
|
955
|
+
configured = os.environ.get("NODE", "").strip() or "node"
|
|
956
|
+
resolved = shutil.which(configured)
|
|
957
|
+
if resolved is None:
|
|
958
|
+
raise PluginHostError("dsh_provider_node_unavailable", "Node executable is unavailable")
|
|
959
|
+
return (str(Path(resolved).resolve()),)
|
|
960
|
+
|
|
961
|
+
def _resolve_cordis_module(self) -> Path:
|
|
962
|
+
if self._cordis_module is not None:
|
|
963
|
+
return self._cordis_module
|
|
964
|
+
return DshToolchainManager().resolve_module_entry("@deepseek-ai/cordis")
|
|
965
|
+
|
|
966
|
+
async def _dispose_hosts(self) -> None:
|
|
967
|
+
hosts = tuple(self._hosts.values())
|
|
968
|
+
self._hosts.clear()
|
|
969
|
+
for host in hosts:
|
|
970
|
+
try:
|
|
971
|
+
await host.dispose()
|
|
972
|
+
except BaseException:
|
|
973
|
+
pass
|
|
974
|
+
|
|
975
|
+
def _verify_shipped_bundle_bytes(self, package_name: str) -> None:
|
|
976
|
+
if package_name == SHIPPED_CODEX_DSH_PACKAGE:
|
|
977
|
+
shipped = shipped_codex_dsh_bundle().root
|
|
978
|
+
error_prefix = "codex_dsh"
|
|
979
|
+
elif package_name == SHIPPED_HARNESS_DSH_PACKAGE:
|
|
980
|
+
shipped = shipped_harness_dsh_bundle().root
|
|
981
|
+
error_prefix = "harness_dsh"
|
|
982
|
+
else: # pragma: no cover - callers use the closed official allowlist
|
|
983
|
+
raise ValueError(f"unsupported shipped DSH package {package_name!r}")
|
|
984
|
+
installed = self._profile_root / "node_modules"
|
|
985
|
+
for segment in package_name.split("/"):
|
|
986
|
+
installed /= segment
|
|
987
|
+
try:
|
|
988
|
+
matches = all(
|
|
989
|
+
(installed / name).read_bytes().rstrip() == (shipped / name).read_bytes().rstrip()
|
|
990
|
+
for name in _PROFILE_FILES
|
|
991
|
+
)
|
|
992
|
+
except OSError as error:
|
|
993
|
+
raise StudioDshProviderRegistrationError(
|
|
994
|
+
f"{error_prefix}_bundle_unreadable",
|
|
995
|
+
"the installed DSH AgentProvider Bundle cannot be verified",
|
|
996
|
+
) from error
|
|
997
|
+
if not matches:
|
|
998
|
+
raise StudioDshProviderRegistrationError(
|
|
999
|
+
f"{error_prefix}_bundle_digest_mismatch",
|
|
1000
|
+
"the installed DSH AgentProvider Bundle differs from the wheel-owned Bundle",
|
|
1001
|
+
)
|
|
1002
|
+
|
|
1003
|
+
def _verify_shipped_resource_bundle_bytes(
|
|
1004
|
+
self, package_name: str, directory_name: str
|
|
1005
|
+
) -> None:
|
|
1006
|
+
shipped = (
|
|
1007
|
+
Path(__file__).parents[1]
|
|
1008
|
+
/ "plugins"
|
|
1009
|
+
/ "providers"
|
|
1010
|
+
/ "bundles"
|
|
1011
|
+
/ directory_name
|
|
1012
|
+
)
|
|
1013
|
+
installed = self._profile_root / "node_modules"
|
|
1014
|
+
for segment in package_name.split("/"):
|
|
1015
|
+
installed /= segment
|
|
1016
|
+
names = ["package.json", "cordis.patch.yml", "index.mjs"]
|
|
1017
|
+
if directory_name == "dsh-platform-resources":
|
|
1018
|
+
names.append("client.mjs")
|
|
1019
|
+
try:
|
|
1020
|
+
package_matches = json.loads(
|
|
1021
|
+
(installed / "package.json").read_text(encoding="utf-8")
|
|
1022
|
+
) == json.loads((shipped / "package.json").read_text(encoding="utf-8"))
|
|
1023
|
+
matches = package_matches and all(
|
|
1024
|
+
(installed / name).read_bytes().rstrip()
|
|
1025
|
+
== (shipped / name).read_bytes().rstrip()
|
|
1026
|
+
for name in names
|
|
1027
|
+
if name != "package.json"
|
|
1028
|
+
)
|
|
1029
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as error:
|
|
1030
|
+
raise StudioDshProviderRegistrationError(
|
|
1031
|
+
"resource_dsh_bundle_unreadable",
|
|
1032
|
+
"an installed platform resource Bundle cannot be verified",
|
|
1033
|
+
) from error
|
|
1034
|
+
if not matches:
|
|
1035
|
+
raise StudioDshProviderRegistrationError(
|
|
1036
|
+
"resource_dsh_bundle_digest_mismatch",
|
|
1037
|
+
"an installed platform resource Bundle differs from the wheel-owned Bundle",
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
def merge_provider_registrations(
|
|
1042
|
+
*registrations: StudioDshProviderRegistrations,
|
|
1043
|
+
) -> tuple[dict[str, PluginManifest], dict[str, Any]]:
|
|
1044
|
+
"""Merge registration sources without last-writer-wins ambiguity."""
|
|
1045
|
+
|
|
1046
|
+
manifests: dict[str, PluginManifest] = {}
|
|
1047
|
+
factories: dict[str, Any] = {}
|
|
1048
|
+
for item in registrations:
|
|
1049
|
+
if item.manifests.keys() != item.factories.keys():
|
|
1050
|
+
raise StudioDshProviderRegistrationError(
|
|
1051
|
+
"dsh_provider_registration_partial",
|
|
1052
|
+
"provider manifests and factories must have identical exact references",
|
|
1053
|
+
)
|
|
1054
|
+
for provider_ref, manifest in item.manifests.items():
|
|
1055
|
+
if provider_ref in manifests and (
|
|
1056
|
+
manifests[provider_ref] != manifest
|
|
1057
|
+
or factories[provider_ref] is not item.factories[provider_ref]
|
|
1058
|
+
):
|
|
1059
|
+
raise StudioDshProviderRegistrationError(
|
|
1060
|
+
"dsh_provider_registration_conflict",
|
|
1061
|
+
"multiple DSH registrations disagree for one exact provider reference",
|
|
1062
|
+
)
|
|
1063
|
+
manifests[provider_ref] = manifest
|
|
1064
|
+
factories[provider_ref] = item.factories[provider_ref]
|
|
1065
|
+
return manifests, factories
|
|
1066
|
+
|
|
1067
|
+
|
|
1068
|
+
__all__ = [
|
|
1069
|
+
"StudioDshProviderInventory",
|
|
1070
|
+
"StudioDshProviderRegistrationError",
|
|
1071
|
+
"StudioDshProviderRegistrationManager",
|
|
1072
|
+
"StudioDshProviderRegistrations",
|
|
1073
|
+
"StudioDshProviderStatus",
|
|
1074
|
+
"merge_provider_registrations",
|
|
1075
|
+
]
|