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,1024 @@
|
|
|
1
|
+
"""Managed DeepSeek Harness toolchain and standard bundle developer workflow.
|
|
2
|
+
|
|
3
|
+
KsADK does not copy, fork, or rebuild DeepSeek Harness. It installs one
|
|
4
|
+
published CLI package into an isolated AgentEngine configuration directory and
|
|
5
|
+
delegates bundle composition to that exact executable. Plugin source remains
|
|
6
|
+
an ordinary npm package that follows DSH's public ``dsh.bundle.patch`` format.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import shutil
|
|
15
|
+
import subprocess
|
|
16
|
+
import tempfile
|
|
17
|
+
import time
|
|
18
|
+
import uuid
|
|
19
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
20
|
+
from contextlib import contextmanager
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any, Iterator, Literal
|
|
24
|
+
|
|
25
|
+
from pydantic import BaseModel, ConfigDict
|
|
26
|
+
|
|
27
|
+
from ksadk.configs.global_config import get_global_config_dir
|
|
28
|
+
from ksadk.plugins.bridges.dsh import (
|
|
29
|
+
DshBridgeError,
|
|
30
|
+
DshProfilePluginBridge,
|
|
31
|
+
dsh_subprocess_environment,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
DSH_PACKAGE = "@deepseek-ai/dsh"
|
|
35
|
+
DSH_VERSION = "0.1.2-rc.1"
|
|
36
|
+
DSH_PACKAGE_SPEC = f"{DSH_PACKAGE}@{DSH_VERSION}"
|
|
37
|
+
DSH_GITHUB_TAG = "dsh-v0.1.2-rc.1"
|
|
38
|
+
DSH_GITHUB_COMMIT = "a66e4702047846cdaa10c66c9d3df3951f5ea70d"
|
|
39
|
+
CORDIS_VERSION_RANGE = "^4.0.2"
|
|
40
|
+
PNPM_VERSION = "11.7.0"
|
|
41
|
+
|
|
42
|
+
# The managed package is a complete Core DSH distribution. Keep these
|
|
43
|
+
# packages explicit so a registry/dist-tag mistake cannot silently degrade the
|
|
44
|
+
# installation into the old capability-only mini host.
|
|
45
|
+
DSH_CORE_PACKAGES = (
|
|
46
|
+
"@deepseek-ai/dsh-base",
|
|
47
|
+
"@deepseek-ai/dsh-web-app",
|
|
48
|
+
"@deepseek-ai/dsh-cordis-client-runner",
|
|
49
|
+
"@deepseek-ai/dsh-client-ui-cordis",
|
|
50
|
+
"@deepseek-ai/dsh-app-boot",
|
|
51
|
+
"@deepseek-ai/dsh-headless",
|
|
52
|
+
"@deepseek-ai/dsh-sdk-app",
|
|
53
|
+
"@deepseek-ai/dsh-mcp-client",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
TOOLCHAIN_HOME_ENV = "AGENTENGINE_PLUGIN_TOOLCHAIN_HOME"
|
|
57
|
+
PNPM_BIN_ENV = "AGENTENGINE_PNPM_BIN"
|
|
58
|
+
|
|
59
|
+
_VERSION = re.compile(r"\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b")
|
|
60
|
+
_PACKAGE_NAME = re.compile(
|
|
61
|
+
r"^(?:@[a-z0-9][a-z0-9._-]*/)?[a-z0-9][a-z0-9._-]*$"
|
|
62
|
+
)
|
|
63
|
+
_LOCK_TIMEOUT_SECONDS = 30.0
|
|
64
|
+
_STALE_LOCK_SECONDS = 10 * 60
|
|
65
|
+
_MAX_MANIFEST_BYTES = 2 * 1024 * 1024
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _to_camel(value: str) -> str:
|
|
69
|
+
head, *tail = value.split("_")
|
|
70
|
+
return head + "".join(part.capitalize() for part in tail)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class _ToolchainModel(BaseModel):
|
|
74
|
+
model_config = ConfigDict(
|
|
75
|
+
alias_generator=_to_camel,
|
|
76
|
+
populate_by_name=True,
|
|
77
|
+
extra="forbid",
|
|
78
|
+
frozen=True,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class DshToolchainStatus(_ToolchainModel):
|
|
83
|
+
package: Literal["@deepseek-ai/dsh"] = DSH_PACKAGE
|
|
84
|
+
expected_version: Literal["0.1.2-rc.1"] = DSH_VERSION
|
|
85
|
+
installed: bool
|
|
86
|
+
usable: bool
|
|
87
|
+
root: str
|
|
88
|
+
executable: str | None = None
|
|
89
|
+
actual_version: str | None = None
|
|
90
|
+
lockfile_present: bool = False
|
|
91
|
+
pnpm_available: bool = False
|
|
92
|
+
pnpm_version: str | None = None
|
|
93
|
+
problem: str | None = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class DshPluginCreateResult(_ToolchainModel):
|
|
97
|
+
ecosystem: Literal["dsh"] = "dsh"
|
|
98
|
+
package_name: str
|
|
99
|
+
target: str
|
|
100
|
+
entrypoint: str
|
|
101
|
+
bundle_patch: str
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class DshPluginValidationResult(_ToolchainModel):
|
|
105
|
+
ecosystem: Literal["dsh"] = "dsh"
|
|
106
|
+
package_name: str
|
|
107
|
+
package_version: str
|
|
108
|
+
host_version: str
|
|
109
|
+
profile_digest: str
|
|
110
|
+
lifecycle: tuple[str, ...] = (
|
|
111
|
+
"install",
|
|
112
|
+
"project",
|
|
113
|
+
"disable",
|
|
114
|
+
"enable",
|
|
115
|
+
"uninstall",
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class DshPluginPackResult(_ToolchainModel):
|
|
120
|
+
ecosystem: Literal["dsh"] = "dsh"
|
|
121
|
+
package_name: str
|
|
122
|
+
package_version: str
|
|
123
|
+
artifact: str
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class DshToolchainError(RuntimeError):
|
|
127
|
+
"""Base error for the managed DSH development toolchain."""
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class DshToolchainUnavailableError(DshToolchainError):
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class DshToolchainVersionMismatchError(DshToolchainError):
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class DshToolchainInstallError(DshToolchainError):
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class DshPluginSourceError(DshToolchainError):
|
|
143
|
+
pass
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class DshPluginValidationError(DshToolchainError):
|
|
147
|
+
def __init__(
|
|
148
|
+
self,
|
|
149
|
+
stage: str,
|
|
150
|
+
message: str = "DSH plugin validation failed",
|
|
151
|
+
*,
|
|
152
|
+
diagnostic: str | None = None,
|
|
153
|
+
) -> None:
|
|
154
|
+
super().__init__(message)
|
|
155
|
+
self.stage = stage
|
|
156
|
+
self.diagnostic = diagnostic
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class DshPluginPackError(DshToolchainError):
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass(frozen=True)
|
|
164
|
+
class CommandResult:
|
|
165
|
+
stdout: str = ""
|
|
166
|
+
stderr: str = ""
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
CommandRunner = Callable[[Sequence[str], Path, Mapping[str, str]], CommandResult]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class DshToolchainManager:
|
|
173
|
+
"""Install and resolve the one supported published DSH CLI version."""
|
|
174
|
+
|
|
175
|
+
def __init__(
|
|
176
|
+
self,
|
|
177
|
+
*,
|
|
178
|
+
base_dir: Path | None = None,
|
|
179
|
+
pnpm_command: Sequence[str] | None = None,
|
|
180
|
+
command_runner: CommandRunner | None = None,
|
|
181
|
+
lock_timeout_seconds: float = _LOCK_TIMEOUT_SECONDS,
|
|
182
|
+
) -> None:
|
|
183
|
+
configured = os.environ.get(TOOLCHAIN_HOME_ENV, "").strip()
|
|
184
|
+
base = (
|
|
185
|
+
base_dir
|
|
186
|
+
or (Path(configured).expanduser() if configured else None)
|
|
187
|
+
or get_global_config_dir() / "plugin-toolchains"
|
|
188
|
+
)
|
|
189
|
+
self._base_dir = base.expanduser().resolve()
|
|
190
|
+
self._root = self._base_dir / "dsh" / DSH_VERSION
|
|
191
|
+
self._pnpm_command = tuple(pnpm_command) if pnpm_command is not None else None
|
|
192
|
+
if self._pnpm_command is not None and not self._pnpm_command:
|
|
193
|
+
raise ValueError("pnpm command cannot be empty")
|
|
194
|
+
self._runner = command_runner or self._run_command
|
|
195
|
+
self._lock_timeout_seconds = lock_timeout_seconds
|
|
196
|
+
self._assert_safe_managed_root(self._root)
|
|
197
|
+
|
|
198
|
+
@property
|
|
199
|
+
def root(self) -> Path:
|
|
200
|
+
return self._root
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def executable(self) -> Path:
|
|
204
|
+
return self._root / "node_modules" / ".bin" / "dsh"
|
|
205
|
+
|
|
206
|
+
def status(self) -> DshToolchainStatus:
|
|
207
|
+
"""Inspect the managed installation without mutating it."""
|
|
208
|
+
|
|
209
|
+
pnpm_path, pnpm_version = self._inspect_pnpm()
|
|
210
|
+
manifest_valid = self._manifest_is_pinned()
|
|
211
|
+
lock_valid = self._lockfile_is_pinned()
|
|
212
|
+
executable = self.executable
|
|
213
|
+
if not manifest_valid:
|
|
214
|
+
problem = "not_installed" if not self._root.exists() else "manifest_mismatch"
|
|
215
|
+
return self._status(
|
|
216
|
+
installed=False,
|
|
217
|
+
usable=False,
|
|
218
|
+
pnpm_path=pnpm_path,
|
|
219
|
+
pnpm_version=pnpm_version,
|
|
220
|
+
problem=problem,
|
|
221
|
+
)
|
|
222
|
+
if not lock_valid:
|
|
223
|
+
return self._status(
|
|
224
|
+
installed=True,
|
|
225
|
+
usable=False,
|
|
226
|
+
pnpm_path=pnpm_path,
|
|
227
|
+
pnpm_version=pnpm_version,
|
|
228
|
+
problem="lockfile_missing_or_mismatched",
|
|
229
|
+
)
|
|
230
|
+
try:
|
|
231
|
+
resolved = executable.resolve(strict=True)
|
|
232
|
+
except (FileNotFoundError, OSError):
|
|
233
|
+
return self._status(
|
|
234
|
+
installed=True,
|
|
235
|
+
usable=False,
|
|
236
|
+
pnpm_path=pnpm_path,
|
|
237
|
+
pnpm_version=pnpm_version,
|
|
238
|
+
problem="executable_missing",
|
|
239
|
+
)
|
|
240
|
+
if not resolved.is_relative_to(self._root.resolve()):
|
|
241
|
+
return self._status(
|
|
242
|
+
installed=True,
|
|
243
|
+
usable=False,
|
|
244
|
+
pnpm_path=pnpm_path,
|
|
245
|
+
pnpm_version=pnpm_version,
|
|
246
|
+
executable=str(resolved),
|
|
247
|
+
problem="executable_outside_managed_root",
|
|
248
|
+
)
|
|
249
|
+
try:
|
|
250
|
+
actual = self._command_version((str(executable),), cwd=self._root)
|
|
251
|
+
except DshToolchainUnavailableError:
|
|
252
|
+
return self._status(
|
|
253
|
+
installed=True,
|
|
254
|
+
usable=False,
|
|
255
|
+
pnpm_path=pnpm_path,
|
|
256
|
+
pnpm_version=pnpm_version,
|
|
257
|
+
executable=str(executable),
|
|
258
|
+
problem="executable_unavailable",
|
|
259
|
+
)
|
|
260
|
+
if actual != DSH_VERSION:
|
|
261
|
+
return self._status(
|
|
262
|
+
installed=True,
|
|
263
|
+
usable=False,
|
|
264
|
+
pnpm_path=pnpm_path,
|
|
265
|
+
pnpm_version=pnpm_version,
|
|
266
|
+
executable=str(executable),
|
|
267
|
+
actual_version=actual,
|
|
268
|
+
problem="version_mismatch",
|
|
269
|
+
)
|
|
270
|
+
if not self._core_package_graph_is_complete():
|
|
271
|
+
return self._status(
|
|
272
|
+
installed=True,
|
|
273
|
+
usable=False,
|
|
274
|
+
pnpm_path=pnpm_path,
|
|
275
|
+
pnpm_version=pnpm_version,
|
|
276
|
+
executable=str(executable),
|
|
277
|
+
actual_version=actual,
|
|
278
|
+
problem="core_packages_missing_or_mismatched",
|
|
279
|
+
)
|
|
280
|
+
return self._status(
|
|
281
|
+
installed=True,
|
|
282
|
+
usable=True,
|
|
283
|
+
pnpm_path=pnpm_path,
|
|
284
|
+
pnpm_version=pnpm_version,
|
|
285
|
+
executable=str(executable),
|
|
286
|
+
actual_version=actual,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
def install(self) -> DshToolchainStatus:
|
|
290
|
+
"""Atomically install the pinned official npm package with a pnpm lock."""
|
|
291
|
+
|
|
292
|
+
pnpm = self.require_pnpm()
|
|
293
|
+
with self._install_lock():
|
|
294
|
+
current = self.status()
|
|
295
|
+
if current.usable:
|
|
296
|
+
return current
|
|
297
|
+
parent = self._root.parent
|
|
298
|
+
parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
299
|
+
self._clean_abandoned_staging(parent)
|
|
300
|
+
staging = Path(tempfile.mkdtemp(prefix=f".{DSH_VERSION}.install-", dir=parent))
|
|
301
|
+
backup: Path | None = None
|
|
302
|
+
try:
|
|
303
|
+
self._write_install_manifest(staging)
|
|
304
|
+
environment = self._installation_environment()
|
|
305
|
+
self._runner(
|
|
306
|
+
(
|
|
307
|
+
*pnpm,
|
|
308
|
+
"install",
|
|
309
|
+
"--lockfile-only",
|
|
310
|
+
"--ignore-scripts",
|
|
311
|
+
"--config.auto-install-peers=true",
|
|
312
|
+
),
|
|
313
|
+
staging,
|
|
314
|
+
environment,
|
|
315
|
+
)
|
|
316
|
+
lockfile = staging / "pnpm-lock.yaml"
|
|
317
|
+
if not self._lockfile_is_pinned(lockfile):
|
|
318
|
+
raise DshToolchainInstallError(
|
|
319
|
+
"pnpm did not create a lockfile pinned to the supported DSH package"
|
|
320
|
+
)
|
|
321
|
+
self._runner(
|
|
322
|
+
(
|
|
323
|
+
*pnpm,
|
|
324
|
+
"install",
|
|
325
|
+
"--frozen-lockfile",
|
|
326
|
+
"--ignore-scripts",
|
|
327
|
+
"--config.auto-install-peers=true",
|
|
328
|
+
),
|
|
329
|
+
staging,
|
|
330
|
+
environment,
|
|
331
|
+
)
|
|
332
|
+
staged_executable = staging / "node_modules" / ".bin" / "dsh"
|
|
333
|
+
resolved = staged_executable.resolve(strict=True)
|
|
334
|
+
if not resolved.is_relative_to(staging.resolve()):
|
|
335
|
+
raise DshToolchainInstallError(
|
|
336
|
+
"installed DSH executable escapes the managed toolchain directory"
|
|
337
|
+
)
|
|
338
|
+
actual = self._command_version((str(staged_executable),), cwd=staging)
|
|
339
|
+
if actual != DSH_VERSION:
|
|
340
|
+
raise DshToolchainVersionMismatchError(
|
|
341
|
+
f"expected DSH {DSH_VERSION}, got {actual}"
|
|
342
|
+
)
|
|
343
|
+
if not self._core_package_graph_is_complete(staging):
|
|
344
|
+
raise DshToolchainInstallError(
|
|
345
|
+
"installed DSH package does not contain the pinned Core runtime graph"
|
|
346
|
+
)
|
|
347
|
+
self._write_receipt(staging, actual)
|
|
348
|
+
if self._root.exists():
|
|
349
|
+
backup = parent / f".{DSH_VERSION}.backup-{uuid.uuid4().hex}"
|
|
350
|
+
os.replace(self._root, backup)
|
|
351
|
+
try:
|
|
352
|
+
os.replace(staging, self._root)
|
|
353
|
+
installed = self.status()
|
|
354
|
+
if not installed.usable:
|
|
355
|
+
raise DshToolchainInstallError(
|
|
356
|
+
f"installed DSH toolchain failed verification: {installed.problem}"
|
|
357
|
+
)
|
|
358
|
+
except BaseException:
|
|
359
|
+
if self._root.exists():
|
|
360
|
+
shutil.rmtree(self._root)
|
|
361
|
+
if backup is not None and backup.exists():
|
|
362
|
+
os.replace(backup, self._root)
|
|
363
|
+
raise
|
|
364
|
+
if backup is not None and backup.exists():
|
|
365
|
+
shutil.rmtree(backup)
|
|
366
|
+
return installed
|
|
367
|
+
except DshToolchainError:
|
|
368
|
+
raise
|
|
369
|
+
except Exception as error:
|
|
370
|
+
raise DshToolchainInstallError("could not install the DSH toolchain") from error
|
|
371
|
+
finally:
|
|
372
|
+
if staging.exists():
|
|
373
|
+
shutil.rmtree(staging)
|
|
374
|
+
if backup is not None and backup.exists() and self._root.exists():
|
|
375
|
+
shutil.rmtree(backup)
|
|
376
|
+
|
|
377
|
+
def require_command(self, explicit: str | Path | None = None) -> tuple[str, ...]:
|
|
378
|
+
"""Return an exact-version DSH executable, managed unless explicitly set."""
|
|
379
|
+
|
|
380
|
+
if explicit is not None and str(explicit).strip():
|
|
381
|
+
executable = self._resolve_program(str(explicit))
|
|
382
|
+
# An explicit installation does not require the managed default root
|
|
383
|
+
# to exist (for example in a fresh Studio HOME).
|
|
384
|
+
actual = self._command_version((executable,), cwd=Path(executable).parent)
|
|
385
|
+
if actual != DSH_VERSION:
|
|
386
|
+
raise DshToolchainVersionMismatchError(
|
|
387
|
+
f"expected DSH {DSH_VERSION}, got {actual}"
|
|
388
|
+
)
|
|
389
|
+
return (executable,)
|
|
390
|
+
state = self.status()
|
|
391
|
+
if state.problem == "version_mismatch":
|
|
392
|
+
raise DshToolchainVersionMismatchError(
|
|
393
|
+
f"expected DSH {DSH_VERSION}, got {state.actual_version or 'unknown'}"
|
|
394
|
+
)
|
|
395
|
+
if not state.usable or state.executable is None:
|
|
396
|
+
raise DshToolchainUnavailableError(
|
|
397
|
+
"managed DSH toolchain is not installed; run "
|
|
398
|
+
"`agentengine plugin toolchain install`"
|
|
399
|
+
)
|
|
400
|
+
return (state.executable,)
|
|
401
|
+
|
|
402
|
+
def resolve_module_entry(self, package_name: str) -> Path:
|
|
403
|
+
"""Resolve one dependency from the pinned DSH installation.
|
|
404
|
+
|
|
405
|
+
Provider sidecars may need the exact Cordis implementation owned by
|
|
406
|
+
their DSH host. Resolution is anchored at the installed DSH package,
|
|
407
|
+
never at a source checkout or the caller's ambient ``node_modules``.
|
|
408
|
+
The result is fenced to the managed toolchain root.
|
|
409
|
+
"""
|
|
410
|
+
|
|
411
|
+
self._validate_package_name(package_name)
|
|
412
|
+
self.require_command()
|
|
413
|
+
dsh_manifest = self._root / "node_modules" / DSH_PACKAGE / "package.json"
|
|
414
|
+
try:
|
|
415
|
+
dsh_manifest = dsh_manifest.resolve(strict=True)
|
|
416
|
+
except (FileNotFoundError, OSError) as error:
|
|
417
|
+
raise DshToolchainUnavailableError(
|
|
418
|
+
"managed DSH package manifest is unavailable"
|
|
419
|
+
) from error
|
|
420
|
+
node = self._resolve_program("node")
|
|
421
|
+
script = (
|
|
422
|
+
"const {createRequire}=require('node:module');"
|
|
423
|
+
f"const resolve=createRequire({json.dumps(str(dsh_manifest))}).resolve;"
|
|
424
|
+
f"process.stdout.write(resolve({json.dumps(package_name)}));"
|
|
425
|
+
)
|
|
426
|
+
try:
|
|
427
|
+
result = self._invoke((node, "-e", script), cwd=self._root)
|
|
428
|
+
except DshToolchainError as error:
|
|
429
|
+
raise DshToolchainUnavailableError(
|
|
430
|
+
f"managed DSH dependency is unavailable: {package_name}"
|
|
431
|
+
) from error
|
|
432
|
+
raw = result.stdout.strip()
|
|
433
|
+
try:
|
|
434
|
+
resolved = Path(raw).resolve(strict=True)
|
|
435
|
+
except (FileNotFoundError, OSError) as error:
|
|
436
|
+
raise DshToolchainUnavailableError(
|
|
437
|
+
f"managed DSH dependency is unavailable: {package_name}"
|
|
438
|
+
) from error
|
|
439
|
+
if not resolved.is_relative_to(self._root):
|
|
440
|
+
raise DshToolchainUnavailableError(
|
|
441
|
+
f"managed DSH dependency escapes the toolchain root: {package_name}"
|
|
442
|
+
)
|
|
443
|
+
return resolved
|
|
444
|
+
|
|
445
|
+
def require_pnpm(self) -> tuple[str, ...]:
|
|
446
|
+
command = self._resolve_pnpm_command()
|
|
447
|
+
if self._root.exists():
|
|
448
|
+
result = self._runner(
|
|
449
|
+
(*command, "--version"),
|
|
450
|
+
self._root,
|
|
451
|
+
self._pnpm_environment(),
|
|
452
|
+
)
|
|
453
|
+
else:
|
|
454
|
+
# pnpm walks parent directories looking for packageManager. A
|
|
455
|
+
# first install under a home directory must not inherit an
|
|
456
|
+
# unrelated Yarn/npm project from one of those parents.
|
|
457
|
+
with tempfile.TemporaryDirectory(prefix="ksadk-pnpm-probe-") as directory:
|
|
458
|
+
result = self._runner(
|
|
459
|
+
(*command, "--version"),
|
|
460
|
+
Path(directory),
|
|
461
|
+
self._pnpm_environment(),
|
|
462
|
+
)
|
|
463
|
+
match = _VERSION.search(result.stdout or result.stderr)
|
|
464
|
+
if match is None:
|
|
465
|
+
raise DshToolchainUnavailableError("pnpm did not report a parseable version")
|
|
466
|
+
if match.group(1) != PNPM_VERSION:
|
|
467
|
+
raise DshToolchainVersionMismatchError(
|
|
468
|
+
f"expected pnpm {PNPM_VERSION}, got {match.group(1)}"
|
|
469
|
+
)
|
|
470
|
+
return command
|
|
471
|
+
|
|
472
|
+
def _status(
|
|
473
|
+
self,
|
|
474
|
+
*,
|
|
475
|
+
installed: bool,
|
|
476
|
+
usable: bool,
|
|
477
|
+
pnpm_path: str | None,
|
|
478
|
+
pnpm_version: str | None,
|
|
479
|
+
problem: str | None = None,
|
|
480
|
+
executable: str | None = None,
|
|
481
|
+
actual_version: str | None = None,
|
|
482
|
+
) -> DshToolchainStatus:
|
|
483
|
+
return DshToolchainStatus(
|
|
484
|
+
installed=installed,
|
|
485
|
+
usable=usable,
|
|
486
|
+
root=str(self._root),
|
|
487
|
+
executable=executable,
|
|
488
|
+
actual_version=actual_version,
|
|
489
|
+
lockfile_present=(self._root / "pnpm-lock.yaml").is_file(),
|
|
490
|
+
pnpm_available=pnpm_path is not None,
|
|
491
|
+
pnpm_version=pnpm_version,
|
|
492
|
+
problem=problem,
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
def _inspect_pnpm(self) -> tuple[str | None, str | None]:
|
|
496
|
+
try:
|
|
497
|
+
command = self.require_pnpm()
|
|
498
|
+
result = self._runner(
|
|
499
|
+
(*command, "--version"),
|
|
500
|
+
self._root,
|
|
501
|
+
self._pnpm_environment(),
|
|
502
|
+
)
|
|
503
|
+
except DshToolchainError:
|
|
504
|
+
return None, None
|
|
505
|
+
match = _VERSION.search(result.stdout or result.stderr)
|
|
506
|
+
return " ".join(command), match.group(1) if match else None
|
|
507
|
+
|
|
508
|
+
def _resolve_pnpm_command(self) -> tuple[str, ...]:
|
|
509
|
+
if self._pnpm_command is not None:
|
|
510
|
+
command = self._pnpm_command
|
|
511
|
+
else:
|
|
512
|
+
configured = os.environ.get(PNPM_BIN_ENV, "").strip()
|
|
513
|
+
if configured:
|
|
514
|
+
command = (configured,)
|
|
515
|
+
else:
|
|
516
|
+
corepack = shutil.which("corepack")
|
|
517
|
+
command = (
|
|
518
|
+
(corepack, f"pnpm@{PNPM_VERSION}")
|
|
519
|
+
if corepack is not None
|
|
520
|
+
else ("pnpm",)
|
|
521
|
+
)
|
|
522
|
+
executable = self._resolve_program(command[0])
|
|
523
|
+
return (executable, *command[1:])
|
|
524
|
+
|
|
525
|
+
def _manifest_is_pinned(self, path: Path | None = None) -> bool:
|
|
526
|
+
manifest_path = path or self._root / "package.json"
|
|
527
|
+
try:
|
|
528
|
+
payload = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
529
|
+
except (FileNotFoundError, OSError, UnicodeError, json.JSONDecodeError):
|
|
530
|
+
return False
|
|
531
|
+
return (
|
|
532
|
+
isinstance(payload, dict)
|
|
533
|
+
and payload.get("private") is True
|
|
534
|
+
and payload.get("packageManager") == f"pnpm@{PNPM_VERSION}"
|
|
535
|
+
and isinstance(payload.get("dependencies"), dict)
|
|
536
|
+
and payload["dependencies"].get(DSH_PACKAGE) == DSH_VERSION
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
def _lockfile_is_pinned(self, path: Path | None = None) -> bool:
|
|
540
|
+
lockfile = path or self._root / "pnpm-lock.yaml"
|
|
541
|
+
try:
|
|
542
|
+
if lockfile.stat().st_size > _MAX_MANIFEST_BYTES:
|
|
543
|
+
return False
|
|
544
|
+
value = lockfile.read_text(encoding="utf-8")
|
|
545
|
+
except (FileNotFoundError, OSError, UnicodeError):
|
|
546
|
+
return False
|
|
547
|
+
return DSH_PACKAGE in value and DSH_VERSION in value
|
|
548
|
+
|
|
549
|
+
def _core_package_graph_is_complete(self, root: Path | None = None) -> bool:
|
|
550
|
+
install_root = root or self._root
|
|
551
|
+
dsh_manifest = install_root / "node_modules" / DSH_PACKAGE / "package.json"
|
|
552
|
+
try:
|
|
553
|
+
resolved_manifest = dsh_manifest.resolve(strict=True)
|
|
554
|
+
payload = json.loads(resolved_manifest.read_text(encoding="utf-8"))
|
|
555
|
+
except (FileNotFoundError, OSError, UnicodeError, json.JSONDecodeError):
|
|
556
|
+
return False
|
|
557
|
+
dependencies = payload.get("dependencies") if isinstance(payload, dict) else None
|
|
558
|
+
if not isinstance(dependencies, dict):
|
|
559
|
+
return False
|
|
560
|
+
for package in DSH_CORE_PACKAGES:
|
|
561
|
+
requirement = dependencies.get(package)
|
|
562
|
+
# pnpm keeps transitive dependencies beside the real dsh package
|
|
563
|
+
# inside its virtual store, not necessarily at the project root.
|
|
564
|
+
manifest = (
|
|
565
|
+
resolved_manifest.parent.parent.parent
|
|
566
|
+
/ Path(*package.split("/"))
|
|
567
|
+
/ "package.json"
|
|
568
|
+
)
|
|
569
|
+
if (
|
|
570
|
+
not isinstance(requirement, str)
|
|
571
|
+
or DSH_VERSION not in requirement
|
|
572
|
+
or not manifest.is_file()
|
|
573
|
+
):
|
|
574
|
+
return False
|
|
575
|
+
return True
|
|
576
|
+
|
|
577
|
+
def _command_version(self, command: Sequence[str], *, cwd: Path) -> str:
|
|
578
|
+
result = self._invoke((*command, "--version"), cwd=cwd)
|
|
579
|
+
match = _VERSION.search(result.stdout or result.stderr)
|
|
580
|
+
if match is None:
|
|
581
|
+
raise DshToolchainUnavailableError("DSH did not report a parseable version")
|
|
582
|
+
return match.group(1)
|
|
583
|
+
|
|
584
|
+
def _invoke(self, command: Sequence[str], *, cwd: Path) -> CommandResult:
|
|
585
|
+
try:
|
|
586
|
+
return self._runner(tuple(command), cwd, dsh_subprocess_environment())
|
|
587
|
+
except DshToolchainError:
|
|
588
|
+
raise
|
|
589
|
+
except Exception as error:
|
|
590
|
+
raise DshToolchainUnavailableError("toolchain command could not be executed") from error
|
|
591
|
+
|
|
592
|
+
@staticmethod
|
|
593
|
+
def _resolve_program(value: str) -> str:
|
|
594
|
+
candidate = Path(value).expanduser()
|
|
595
|
+
if candidate.is_absolute() or len(candidate.parts) > 1:
|
|
596
|
+
if not candidate.is_file():
|
|
597
|
+
raise DshToolchainUnavailableError(f"required executable is unavailable: {value}")
|
|
598
|
+
return str(candidate.resolve())
|
|
599
|
+
resolved = shutil.which(value)
|
|
600
|
+
if resolved is None:
|
|
601
|
+
raise DshToolchainUnavailableError(f"required executable is unavailable: {value}")
|
|
602
|
+
return resolved
|
|
603
|
+
|
|
604
|
+
@staticmethod
|
|
605
|
+
def _validate_package_name(name: str) -> None:
|
|
606
|
+
if len(name) > 214 or not _PACKAGE_NAME.fullmatch(name):
|
|
607
|
+
raise DshToolchainUnavailableError("invalid managed DSH package name")
|
|
608
|
+
|
|
609
|
+
def _write_install_manifest(self, root: Path) -> None:
|
|
610
|
+
self._write_json(
|
|
611
|
+
root / "package.json",
|
|
612
|
+
{
|
|
613
|
+
"name": "agentengine-managed-dsh-toolchain",
|
|
614
|
+
"private": True,
|
|
615
|
+
"packageManager": f"pnpm@{PNPM_VERSION}",
|
|
616
|
+
"dependencies": {DSH_PACKAGE: DSH_VERSION},
|
|
617
|
+
},
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
def _write_receipt(self, root: Path, actual: str) -> None:
|
|
621
|
+
self._write_json(
|
|
622
|
+
root / "toolchain.json",
|
|
623
|
+
{
|
|
624
|
+
"schemaVersion": 1,
|
|
625
|
+
"package": DSH_PACKAGE,
|
|
626
|
+
"requestedVersion": DSH_VERSION,
|
|
627
|
+
"actualVersion": actual,
|
|
628
|
+
"githubTag": DSH_GITHUB_TAG,
|
|
629
|
+
"githubCommit": DSH_GITHUB_COMMIT,
|
|
630
|
+
"distribution": "core",
|
|
631
|
+
"corePackages": list(DSH_CORE_PACKAGES),
|
|
632
|
+
"packageManager": f"pnpm@{PNPM_VERSION}",
|
|
633
|
+
},
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
@staticmethod
|
|
637
|
+
def _write_json(path: Path, value: object) -> None:
|
|
638
|
+
path.parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
639
|
+
temporary = path.with_name(f".{path.name}.{uuid.uuid4().hex}.tmp")
|
|
640
|
+
try:
|
|
641
|
+
temporary.write_text(
|
|
642
|
+
json.dumps(value, ensure_ascii=False, indent=2) + "\n",
|
|
643
|
+
encoding="utf-8",
|
|
644
|
+
)
|
|
645
|
+
temporary.chmod(0o600)
|
|
646
|
+
os.replace(temporary, path)
|
|
647
|
+
finally:
|
|
648
|
+
temporary.unlink(missing_ok=True)
|
|
649
|
+
|
|
650
|
+
@staticmethod
|
|
651
|
+
def _installation_environment() -> dict[str, str]:
|
|
652
|
+
environment = dsh_subprocess_environment()
|
|
653
|
+
environment.update(
|
|
654
|
+
{
|
|
655
|
+
"CI": "1",
|
|
656
|
+
"COREPACK_ENABLE_PROJECT_SPEC": "0",
|
|
657
|
+
"NPM_CONFIG_AUDIT": "false",
|
|
658
|
+
"NPM_CONFIG_FUND": "false",
|
|
659
|
+
}
|
|
660
|
+
)
|
|
661
|
+
return environment
|
|
662
|
+
|
|
663
|
+
@staticmethod
|
|
664
|
+
def _pnpm_environment() -> dict[str, str]:
|
|
665
|
+
environment = dsh_subprocess_environment()
|
|
666
|
+
environment["COREPACK_ENABLE_PROJECT_SPEC"] = "0"
|
|
667
|
+
return environment
|
|
668
|
+
|
|
669
|
+
@contextmanager
|
|
670
|
+
def _install_lock(self) -> Iterator[None]:
|
|
671
|
+
parent = self._root.parent
|
|
672
|
+
parent.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
673
|
+
lock = parent / f".{DSH_VERSION}.install.lock"
|
|
674
|
+
deadline = time.monotonic() + self._lock_timeout_seconds
|
|
675
|
+
while True:
|
|
676
|
+
try:
|
|
677
|
+
lock.mkdir(mode=0o700)
|
|
678
|
+
self._write_json(lock / "owner.json", {"pid": os.getpid()})
|
|
679
|
+
break
|
|
680
|
+
except FileExistsError:
|
|
681
|
+
if self._lock_is_stale(lock):
|
|
682
|
+
try:
|
|
683
|
+
shutil.rmtree(lock)
|
|
684
|
+
except FileNotFoundError:
|
|
685
|
+
pass
|
|
686
|
+
continue
|
|
687
|
+
if time.monotonic() >= deadline:
|
|
688
|
+
raise DshToolchainInstallError(
|
|
689
|
+
"another DSH toolchain installation is still in progress"
|
|
690
|
+
)
|
|
691
|
+
time.sleep(0.05)
|
|
692
|
+
try:
|
|
693
|
+
yield
|
|
694
|
+
finally:
|
|
695
|
+
shutil.rmtree(lock, ignore_errors=True)
|
|
696
|
+
|
|
697
|
+
@staticmethod
|
|
698
|
+
def _lock_is_stale(lock: Path) -> bool:
|
|
699
|
+
try:
|
|
700
|
+
age = time.time() - lock.stat().st_mtime
|
|
701
|
+
except FileNotFoundError:
|
|
702
|
+
return False
|
|
703
|
+
if age <= _STALE_LOCK_SECONDS:
|
|
704
|
+
return False
|
|
705
|
+
try:
|
|
706
|
+
payload = json.loads((lock / "owner.json").read_text(encoding="utf-8"))
|
|
707
|
+
pid = int(payload.get("pid", -1))
|
|
708
|
+
except (OSError, ValueError, TypeError, json.JSONDecodeError):
|
|
709
|
+
return True
|
|
710
|
+
if pid <= 0:
|
|
711
|
+
return True
|
|
712
|
+
try:
|
|
713
|
+
os.kill(pid, 0)
|
|
714
|
+
except ProcessLookupError:
|
|
715
|
+
return True
|
|
716
|
+
except (PermissionError, OSError):
|
|
717
|
+
return False
|
|
718
|
+
return False
|
|
719
|
+
|
|
720
|
+
@staticmethod
|
|
721
|
+
def _clean_abandoned_staging(parent: Path) -> None:
|
|
722
|
+
for candidate in parent.glob(f".{DSH_VERSION}.install-*"):
|
|
723
|
+
if candidate.is_dir() and candidate.parent == parent:
|
|
724
|
+
shutil.rmtree(candidate)
|
|
725
|
+
|
|
726
|
+
def _assert_safe_managed_root(self, root: Path) -> None:
|
|
727
|
+
if root.name != DSH_VERSION or root.parent.name != "dsh":
|
|
728
|
+
raise ValueError("managed DSH root must end in dsh/<pinned-version>")
|
|
729
|
+
if root in {Path(root.anchor), Path.home().resolve(), self._base_dir}:
|
|
730
|
+
raise ValueError("managed DSH root is too broad")
|
|
731
|
+
|
|
732
|
+
@staticmethod
|
|
733
|
+
def _run_command(
|
|
734
|
+
command: Sequence[str],
|
|
735
|
+
cwd: Path,
|
|
736
|
+
environment: Mapping[str, str],
|
|
737
|
+
) -> CommandResult:
|
|
738
|
+
try:
|
|
739
|
+
completed = subprocess.run(
|
|
740
|
+
list(command),
|
|
741
|
+
cwd=cwd,
|
|
742
|
+
env=dict(environment),
|
|
743
|
+
check=False,
|
|
744
|
+
capture_output=True,
|
|
745
|
+
text=True,
|
|
746
|
+
timeout=180,
|
|
747
|
+
)
|
|
748
|
+
except (OSError, subprocess.TimeoutExpired) as error:
|
|
749
|
+
raise DshToolchainUnavailableError("toolchain command did not complete") from error
|
|
750
|
+
if completed.returncode != 0:
|
|
751
|
+
diagnostic = _redact_diagnostic(completed.stderr or completed.stdout)
|
|
752
|
+
raise DshToolchainInstallError(
|
|
753
|
+
f"toolchain command failed with exit code {completed.returncode}"
|
|
754
|
+
+ (f": {diagnostic[-2000:]}" if diagnostic else "")
|
|
755
|
+
)
|
|
756
|
+
return CommandResult(stdout=completed.stdout, stderr=completed.stderr)
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
class DshPluginDeveloper:
|
|
760
|
+
"""Create, validate, and pack standard DSH npm bundle projects."""
|
|
761
|
+
|
|
762
|
+
def __init__(
|
|
763
|
+
self,
|
|
764
|
+
*,
|
|
765
|
+
toolchain: DshToolchainManager | None = None,
|
|
766
|
+
explicit_dsh: str | Path | None = None,
|
|
767
|
+
bridge_factory: Callable[..., DshProfilePluginBridge] = DshProfilePluginBridge,
|
|
768
|
+
command_runner: CommandRunner | None = None,
|
|
769
|
+
) -> None:
|
|
770
|
+
self._toolchain = toolchain or DshToolchainManager(command_runner=command_runner)
|
|
771
|
+
self._explicit_dsh = explicit_dsh
|
|
772
|
+
self._bridge_factory = bridge_factory
|
|
773
|
+
self._runner = command_runner or DshToolchainManager._run_command
|
|
774
|
+
|
|
775
|
+
def create(self, target: Path, *, package_name: str | None = None) -> DshPluginCreateResult:
|
|
776
|
+
target = target.expanduser().resolve()
|
|
777
|
+
if target.exists():
|
|
778
|
+
raise DshPluginSourceError("plugin target already exists")
|
|
779
|
+
name = package_name or self._default_package_name(target.name)
|
|
780
|
+
self._validate_package_name(name)
|
|
781
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
782
|
+
target.mkdir(mode=0o755)
|
|
783
|
+
try:
|
|
784
|
+
package = {
|
|
785
|
+
"name": name,
|
|
786
|
+
"version": "0.1.0",
|
|
787
|
+
"description": "A DeepSeek Harness Cordis plugin bundle.",
|
|
788
|
+
"type": "module",
|
|
789
|
+
"main": "index.js",
|
|
790
|
+
"types": "index.d.ts",
|
|
791
|
+
"files": ["index.js", "index.d.ts", "cordis.patch.yml"],
|
|
792
|
+
"engines": {"node": ">=22.19.0"},
|
|
793
|
+
"peerDependencies": {"@deepseek-ai/cordis": CORDIS_VERSION_RANGE},
|
|
794
|
+
"dsh": {"bundle": {"patch": "./cordis.patch.yml"}},
|
|
795
|
+
}
|
|
796
|
+
(target / "package.json").write_text(
|
|
797
|
+
json.dumps(package, ensure_ascii=False, indent=2) + "\n",
|
|
798
|
+
encoding="utf-8",
|
|
799
|
+
)
|
|
800
|
+
(target / "cordis.patch.yml").write_text(
|
|
801
|
+
"- insert:\n"
|
|
802
|
+
" - id: plugin-main\n"
|
|
803
|
+
f" name: {json.dumps(name)}\n",
|
|
804
|
+
encoding="utf-8",
|
|
805
|
+
)
|
|
806
|
+
symbol = re.sub(r"[^A-Za-z0-9]+", "-", name).strip("-") or "plugin"
|
|
807
|
+
(target / "index.js").write_text(
|
|
808
|
+
f"export const name = {json.dumps(symbol)}\n\n"
|
|
809
|
+
"/** @param {import('@deepseek-ai/cordis').Context} ctx */\n"
|
|
810
|
+
"export function apply(ctx) {\n"
|
|
811
|
+
" // Register resources through Cordis effects so unload is reversible.\n"
|
|
812
|
+
" ctx.effect(() => () => {})\n"
|
|
813
|
+
"}\n",
|
|
814
|
+
encoding="utf-8",
|
|
815
|
+
)
|
|
816
|
+
(target / "index.d.ts").write_text(
|
|
817
|
+
"import type { Context } from '@deepseek-ai/cordis'\n\n"
|
|
818
|
+
"export declare const name: string\n"
|
|
819
|
+
"export declare function apply(ctx: Context): void\n",
|
|
820
|
+
encoding="utf-8",
|
|
821
|
+
)
|
|
822
|
+
except BaseException:
|
|
823
|
+
shutil.rmtree(target, ignore_errors=True)
|
|
824
|
+
raise
|
|
825
|
+
return DshPluginCreateResult(
|
|
826
|
+
package_name=name,
|
|
827
|
+
target=str(target),
|
|
828
|
+
entrypoint="index.js",
|
|
829
|
+
bundle_patch="cordis.patch.yml",
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
def validate(self, source: str | Path) -> DshPluginValidationResult:
|
|
833
|
+
local_source, _package = self._resolve_local_bundle(source)
|
|
834
|
+
source_value = str(local_source) if local_source is not None else str(source).strip()
|
|
835
|
+
command = self._toolchain.require_command(self._explicit_dsh)
|
|
836
|
+
stage = "start"
|
|
837
|
+
with tempfile.TemporaryDirectory(prefix="agentengine-dsh-validate-") as directory:
|
|
838
|
+
root = Path(directory)
|
|
839
|
+
try:
|
|
840
|
+
with self._bridge_factory(
|
|
841
|
+
dsh_home=root / "home",
|
|
842
|
+
profile="validate",
|
|
843
|
+
dsh_command=command,
|
|
844
|
+
cwd=(local_source.parent if local_source is not None else Path.cwd()),
|
|
845
|
+
) as bridge:
|
|
846
|
+
stage = "install"
|
|
847
|
+
installed = bridge.install_plugin(
|
|
848
|
+
source_value,
|
|
849
|
+
accept_host_permissions=True,
|
|
850
|
+
)
|
|
851
|
+
stage = "project"
|
|
852
|
+
projection = bridge.project_profile()
|
|
853
|
+
stage = "disable"
|
|
854
|
+
bridge.set_enabled(installed.name, enabled=False)
|
|
855
|
+
stage = "enable"
|
|
856
|
+
bridge.set_enabled(installed.name, enabled=True)
|
|
857
|
+
stage = "uninstall"
|
|
858
|
+
bridge.uninstall_plugin(installed.name)
|
|
859
|
+
return DshPluginValidationResult(
|
|
860
|
+
package_name=installed.name,
|
|
861
|
+
package_version=installed.version,
|
|
862
|
+
host_version=projection.host_version,
|
|
863
|
+
profile_digest=projection.config_digest,
|
|
864
|
+
)
|
|
865
|
+
except DshToolchainError:
|
|
866
|
+
raise
|
|
867
|
+
except ValueError as error:
|
|
868
|
+
if stage == "install":
|
|
869
|
+
raise DshPluginSourceError(str(error)) from error
|
|
870
|
+
raise DshPluginValidationError(
|
|
871
|
+
stage,
|
|
872
|
+
diagnostic=_redact_diagnostic(str(error)),
|
|
873
|
+
) from error
|
|
874
|
+
except DshBridgeError as error:
|
|
875
|
+
raise DshPluginValidationError(
|
|
876
|
+
stage,
|
|
877
|
+
diagnostic=_redact_diagnostic(str(error)),
|
|
878
|
+
) from error
|
|
879
|
+
except Exception as error:
|
|
880
|
+
raise DshPluginValidationError(
|
|
881
|
+
stage,
|
|
882
|
+
diagnostic=_redact_diagnostic(str(error)),
|
|
883
|
+
) from error
|
|
884
|
+
|
|
885
|
+
def pack(
|
|
886
|
+
self,
|
|
887
|
+
source: Path,
|
|
888
|
+
*,
|
|
889
|
+
output_dir: Path | None = None,
|
|
890
|
+
) -> DshPluginPackResult:
|
|
891
|
+
local_source, package = self._resolve_local_bundle(source)
|
|
892
|
+
assert local_source is not None
|
|
893
|
+
if not local_source.is_dir():
|
|
894
|
+
raise DshPluginSourceError("only a DSH bundle source directory can be packed")
|
|
895
|
+
output = (output_dir or local_source / "dist").expanduser().resolve()
|
|
896
|
+
output.mkdir(parents=True, exist_ok=True)
|
|
897
|
+
before = {item.resolve() for item in output.glob("*.tgz") if item.is_file()}
|
|
898
|
+
pnpm = self._toolchain.require_pnpm()
|
|
899
|
+
environment = dsh_subprocess_environment()
|
|
900
|
+
# Keep the pinned pnpm selected above even when an ancestor workspace
|
|
901
|
+
# declares another package manager through Corepack.
|
|
902
|
+
environment["COREPACK_ENABLE_PROJECT_SPEC"] = "0"
|
|
903
|
+
try:
|
|
904
|
+
self._runner(
|
|
905
|
+
(*pnpm, "pack", "--pack-destination", str(output)),
|
|
906
|
+
local_source,
|
|
907
|
+
environment,
|
|
908
|
+
)
|
|
909
|
+
except DshToolchainError as error:
|
|
910
|
+
raise DshPluginPackError("pnpm could not pack the DSH bundle") from error
|
|
911
|
+
except Exception as error:
|
|
912
|
+
raise DshPluginPackError("pnpm could not pack the DSH bundle") from error
|
|
913
|
+
created = [
|
|
914
|
+
item.resolve()
|
|
915
|
+
for item in output.glob("*.tgz")
|
|
916
|
+
if item.is_file() and item.resolve() not in before
|
|
917
|
+
]
|
|
918
|
+
if len(created) != 1 or not created[0].is_relative_to(output):
|
|
919
|
+
raise DshPluginPackError("pnpm pack did not produce exactly one bounded npm tarball")
|
|
920
|
+
return DshPluginPackResult(
|
|
921
|
+
package_name=str(package["name"]),
|
|
922
|
+
package_version=str(package["version"]),
|
|
923
|
+
artifact=str(created[0]),
|
|
924
|
+
)
|
|
925
|
+
|
|
926
|
+
@classmethod
|
|
927
|
+
def _resolve_local_bundle(
|
|
928
|
+
cls,
|
|
929
|
+
source: str | Path,
|
|
930
|
+
) -> tuple[Path | None, dict[str, Any]]:
|
|
931
|
+
raw = str(source).strip()
|
|
932
|
+
candidate = Path(raw).expanduser()
|
|
933
|
+
looks_local = isinstance(source, Path) or candidate.is_absolute() or raw.startswith(".")
|
|
934
|
+
if not candidate.exists():
|
|
935
|
+
if looks_local:
|
|
936
|
+
raise DshPluginSourceError("local DSH plugin source does not exist")
|
|
937
|
+
if not raw or raw.startswith("-") or any(char in raw for char in "\r\n\0"):
|
|
938
|
+
raise DshPluginSourceError("invalid DSH plugin source")
|
|
939
|
+
return None, {}
|
|
940
|
+
root = candidate.resolve()
|
|
941
|
+
if root.is_file() and root.name.endswith(".tgz"):
|
|
942
|
+
return root, {}
|
|
943
|
+
if root.is_file() and root.name == "package.json":
|
|
944
|
+
root = root.parent
|
|
945
|
+
if not root.is_dir():
|
|
946
|
+
raise DshPluginSourceError("local DSH plugin source must be a directory")
|
|
947
|
+
manifest_path = root / "package.json"
|
|
948
|
+
try:
|
|
949
|
+
if manifest_path.stat().st_size > _MAX_MANIFEST_BYTES:
|
|
950
|
+
raise DshPluginSourceError("DSH plugin package.json is too large")
|
|
951
|
+
package = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
952
|
+
except FileNotFoundError:
|
|
953
|
+
raise DshPluginSourceError("DSH plugin package.json is missing") from None
|
|
954
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as error:
|
|
955
|
+
raise DshPluginSourceError("DSH plugin package.json is invalid") from error
|
|
956
|
+
if not isinstance(package, dict):
|
|
957
|
+
raise DshPluginSourceError("DSH plugin package.json must be an object")
|
|
958
|
+
name = package.get("name")
|
|
959
|
+
version = package.get("version")
|
|
960
|
+
if not isinstance(name, str) or not isinstance(version, str) or not version.strip():
|
|
961
|
+
raise DshPluginSourceError("DSH plugin package name/version is invalid")
|
|
962
|
+
cls._validate_package_name(name)
|
|
963
|
+
dsh = package.get("dsh")
|
|
964
|
+
bundle = dsh.get("bundle") if isinstance(dsh, dict) else None
|
|
965
|
+
patch = bundle.get("patch") if isinstance(bundle, dict) else None
|
|
966
|
+
if not isinstance(patch, str) or not patch.strip():
|
|
967
|
+
raise DshPluginSourceError("package.json must declare dsh.bundle.patch")
|
|
968
|
+
relative = Path(patch)
|
|
969
|
+
target = (root / relative).resolve()
|
|
970
|
+
if relative.is_absolute() or ".." in relative.parts or not target.is_relative_to(root):
|
|
971
|
+
raise DshPluginSourceError("dsh.bundle.patch must stay inside the package")
|
|
972
|
+
if not target.is_file():
|
|
973
|
+
raise DshPluginSourceError("declared DSH bundle patch does not exist")
|
|
974
|
+
return root, package
|
|
975
|
+
|
|
976
|
+
@staticmethod
|
|
977
|
+
def _default_package_name(target_name: str) -> str:
|
|
978
|
+
value = re.sub(r"[^a-z0-9._-]+", "-", target_name.casefold()).strip("-._")
|
|
979
|
+
if not value:
|
|
980
|
+
value = "plugin"
|
|
981
|
+
return value if value.startswith("dsh-") else f"dsh-{value}"
|
|
982
|
+
|
|
983
|
+
@staticmethod
|
|
984
|
+
def _validate_package_name(name: str) -> None:
|
|
985
|
+
if len(name) > 214 or not _PACKAGE_NAME.fullmatch(name):
|
|
986
|
+
raise DshPluginSourceError("plugin name must be a valid lowercase npm package name")
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
__all__ = [
|
|
990
|
+
"CORDIS_VERSION_RANGE",
|
|
991
|
+
"DSH_CORE_PACKAGES",
|
|
992
|
+
"DSH_GITHUB_COMMIT",
|
|
993
|
+
"DSH_GITHUB_TAG",
|
|
994
|
+
"DSH_PACKAGE",
|
|
995
|
+
"DSH_PACKAGE_SPEC",
|
|
996
|
+
"DSH_VERSION",
|
|
997
|
+
"PNPM_BIN_ENV",
|
|
998
|
+
"PNPM_VERSION",
|
|
999
|
+
"TOOLCHAIN_HOME_ENV",
|
|
1000
|
+
"CommandResult",
|
|
1001
|
+
"DshPluginCreateResult",
|
|
1002
|
+
"DshPluginDeveloper",
|
|
1003
|
+
"DshPluginPackError",
|
|
1004
|
+
"DshPluginPackResult",
|
|
1005
|
+
"DshPluginSourceError",
|
|
1006
|
+
"DshPluginValidationError",
|
|
1007
|
+
"DshPluginValidationResult",
|
|
1008
|
+
"DshToolchainError",
|
|
1009
|
+
"DshToolchainInstallError",
|
|
1010
|
+
"DshToolchainManager",
|
|
1011
|
+
"DshToolchainStatus",
|
|
1012
|
+
"DshToolchainUnavailableError",
|
|
1013
|
+
"DshToolchainVersionMismatchError",
|
|
1014
|
+
]
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
def _redact_diagnostic(value: str) -> str:
|
|
1018
|
+
value = re.sub(r"(https?://)[^/\s:@]+:[^/\s@]+@", r"\1[redacted]@", value, flags=re.I)
|
|
1019
|
+
return re.sub(
|
|
1020
|
+
r"((?:token|password|authorization|_authToken)\s*[:=]\s*)[^\s]+",
|
|
1021
|
+
r"\1[redacted]",
|
|
1022
|
+
value,
|
|
1023
|
+
flags=re.I,
|
|
1024
|
+
).strip()
|