agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +13 -9
- agentengine_sdk_python-0.8.5.dist-info/RECORD +1296 -0
- ksadk/_build_provenance.json +1 -1
- ksadk/_process.py +83 -0
- ksadk/_str_enum.py +17 -0
- ksadk/a2ui/core.py +3 -3
- ksadk/api/client.py +111 -91
- ksadk/builders/code_builder.py +74 -21
- ksadk/builders/framework_requirements.py +22 -3
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +1 -0
- ksadk/cli/__init__.py +68 -3
- ksadk/cli/cmd_config.py +4 -4
- ksadk/cli/cmd_create.py +12 -12
- ksadk/cli/cmd_hermes.py +24 -2
- ksadk/cli/cmd_invoke.py +28 -5
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_openclaw.py +26 -1
- ksadk/cli/cmd_plugin.py +76 -13
- ksadk/cli/cmd_studio.py +64 -16
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/openclaw_env.py +1 -1
- ksadk/cli/resource_common.py +26 -0
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +425 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +56 -298
- ksadk/common/auth.py +16 -10
- ksadk/configs/__init__.py +1 -1
- ksadk/configs/env_registry.py +153 -31
- ksadk/configs/env_registry_studio.py +86 -0
- ksadk/configs/global_config.py +1 -1
- ksadk/configs/settings.py +3 -3
- ksadk/connector/__init__.py +17 -0
- ksadk/connector/channel.py +477 -0
- ksadk/context_engine/capabilities.py +52 -4
- ksadk/conversations/attachment_storage.py +10 -3
- ksadk/conversations/attachments.py +16 -5
- ksadk/conversations/message_projection.py +133 -21
- ksadk/conversations/normalize.py +28 -10
- ksadk/conversations/projector.py +4 -6
- ksadk/conversations/runtime_baseline.py +37 -0
- ksadk/conversations/runtime_invocation.py +22 -4
- ksadk/conversations/runtime_observability.py +39 -10
- ksadk/conversations/runtime_payloads.py +9 -0
- ksadk/conversations/runtime_persistence.py +105 -9
- ksadk/conversations/runtime_preparation.py +42 -33
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +34 -35
- ksadk/conversations/runtime_streaming.py +33 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/adapters/_codex_items.py +16 -8
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/_langgraph_support.py +34 -0
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/events/session_event.py +2 -2
- ksadk/harness/__init__.py +14 -0
- ksadk/harness/app.py +11 -0
- ksadk/harness/artifact_store.py +213 -0
- ksadk/harness/capabilities.py +115 -0
- ksadk/harness/capability_runtime.py +237 -0
- ksadk/harness/closure_contract.py +92 -0
- ksadk/harness/compaction_record.py +122 -0
- ksadk/harness/compiler.py +284 -0
- ksadk/harness/config.py +2 -2
- ksadk/harness/conformance/__init__.py +33 -0
- ksadk/harness/conformance/contract.py +506 -0
- ksadk/harness/conformance/fixtures.py +102 -0
- ksadk/harness/context_engine.py +403 -0
- ksadk/harness/context_maintenance.py +259 -0
- ksadk/harness/context_manifest.py +188 -0
- ksadk/harness/context_tuning.py +168 -0
- ksadk/harness/draft_runtime.py +322 -0
- ksadk/harness/engine/__init__.py +40 -0
- ksadk/harness/engine/base.py +122 -0
- ksadk/harness/engine/budgets.py +108 -0
- ksadk/harness/engine/capability_declarations.py +59 -0
- ksadk/harness/engine/completion_guard.py +42 -0
- ksadk/harness/engine/context_pipeline.py +579 -0
- ksadk/harness/engine/graph_builder.py +859 -0
- ksadk/harness/engine/langgraph.py +931 -0
- ksadk/harness/engine/mcp_disclosure.py +750 -0
- ksadk/harness/engine/policy_runtime.py +70 -0
- ksadk/harness/engine/postgres_checkpointer.py +63 -0
- ksadk/harness/engine/run_control_bridge.py +80 -0
- ksadk/harness/engine/run_types.py +88 -0
- ksadk/harness/engine/skill_disclosure.py +189 -0
- ksadk/harness/engine/spans.py +41 -0
- ksadk/harness/engine/subagents.py +343 -0
- ksadk/harness/engine/thread_ids.py +112 -0
- ksadk/harness/engine/tool_dispatch.py +144 -0
- ksadk/harness/event_tree.py +212 -0
- ksadk/harness/events.py +461 -0
- ksadk/harness/execution_policy.py +94 -0
- ksadk/harness/insights.py +210 -0
- ksadk/harness/lifecycle.py +578 -0
- ksadk/harness/lifecycle_conformance.py +233 -0
- ksadk/harness/lifecycle_local_plane.py +104 -0
- ksadk/harness/loop/__init__.py +44 -0
- ksadk/harness/loop/reason.py +454 -0
- ksadk/harness/loop/tools.py +762 -0
- ksadk/harness/managed_runtime.py +884 -0
- ksadk/harness/mcp_matrix.py +474 -0
- ksadk/harness/mcp_runtime.py +471 -0
- ksadk/harness/memory_consolidation.py +157 -0
- ksadk/harness/memory_loop.py +156 -0
- ksadk/harness/memory_runtime.py +541 -0
- ksadk/harness/metrics.py +90 -0
- ksadk/harness/model_capability.py +253 -0
- ksadk/harness/model_provider.py +220 -0
- ksadk/harness/observability/__init__.py +29 -0
- ksadk/harness/observability/inspection.py +528 -0
- ksadk/harness/observability/metrics.py +167 -0
- ksadk/harness/observability/otel_exporter.py +218 -0
- ksadk/harness/prompt_cache.py +70 -0
- ksadk/harness/public_activity.py +154 -0
- ksadk/harness/readiness.py +249 -0
- ksadk/harness/reasoner.py +466 -13
- ksadk/harness/release_readiness.py +140 -0
- ksadk/harness/resource_ref.py +69 -0
- ksadk/harness/run_control.py +668 -0
- ksadk/harness/runtime.py +171 -136
- ksadk/harness/runtime_capabilities.py +158 -0
- ksadk/harness/runtime_server.py +514 -0
- ksadk/harness/sandbox_adapters.py +739 -0
- ksadk/harness/sandbox_backend.py +530 -0
- ksadk/harness/sandbox_conformance.py +288 -0
- ksadk/harness/sandbox_lease.py +77 -0
- ksadk/harness/sandbox_lease_conformance.py +259 -0
- ksadk/harness/sandbox_matrix.py +170 -0
- ksadk/harness/sandbox_reconciliation.py +140 -0
- ksadk/harness/sandbox_recovery.py +586 -0
- ksadk/harness/sandbox_recovery_conformance.py +246 -0
- ksadk/harness/session_store.py +243 -0
- ksadk/harness/skill_composition.py +212 -0
- ksadk/harness/skill_feedback.py +123 -0
- ksadk/harness/skill_matrix.py +233 -0
- ksadk/harness/skill_runtime.py +259 -0
- ksadk/harness/spec.py +332 -0
- ksadk/harness/state.py +153 -0
- ksadk/harness/strategies.py +149 -0
- ksadk/harness/subagent.py +253 -0
- ksadk/harness/tool_policy.py +131 -0
- ksadk/harness/tool_receipts.py +96 -0
- ksadk/harness/tool_reliability.py +81 -0
- ksadk/harness/tools.py +38 -13
- ksadk/harness/user_errors.py +69 -0
- ksadk/harness/working_context.py +81 -0
- ksadk/harness/working_context_patch.py +99 -0
- ksadk/identity/resolver.py +18 -0
- ksadk/interaction/__init__.py +1 -1
- ksadk/interaction/ledger.py +1 -1
- ksadk/interaction/provider.py +2 -1
- ksadk/interaction/providers/__init__.py +3 -1
- ksadk/interaction/providers/adk.py +1 -1
- ksadk/interaction/providers/codex.py +1 -1
- ksadk/interaction/providers/harness.py +50 -0
- ksadk/interaction/providers/langgraph.py +2 -1
- ksadk/kernel/__init__.py +10 -0
- ksadk/kernel/approval_presentation.py +91 -0
- ksadk/kernel/authorization.py +1 -1
- ksadk/kernel/bootstrap.py +114 -106
- ksadk/kernel/contract_fingerprints.py +1 -1
- ksadk/kernel/contracts.py +5 -0
- ksadk/kernel/control.py +32 -1
- ksadk/kernel/execution_grants.py +221 -0
- ksadk/kernel/execution_grants_memory.py +133 -0
- ksadk/kernel/execution_grants_postgres.py +217 -0
- ksadk/kernel/execution_grants_sqlite.py +209 -0
- ksadk/kernel/ingress.py +42 -29
- ksadk/kernel/mapping.py +1 -1
- ksadk/kernel/memory_store.py +24 -11
- ksadk/kernel/postgres_store.py +63 -33
- ksadk/kernel/recovery.py +78 -14
- ksadk/kernel/sql/001_agent_kernel.sql +23 -0
- ksadk/kernel/sqlite_store.py +331 -25
- ksadk/kernel/state.py +2 -3
- ksadk/kernel/store.py +72 -2
- ksadk/kernel/worker.py +144 -51
- ksadk/kernel/worker_history.py +72 -0
- ksadk/kernel/worker_identity.py +47 -0
- 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/coordinator.py +22 -6
- ksadk/memory/extraction.py +40 -1
- ksadk/memory/models.py +84 -5
- ksadk/memory/provider_resolver.py +8 -0
- ksadk/memory/providers/local_postgres.py +200 -0
- ksadk/memory/providers/local_sqlite.py +42 -3
- ksadk/memory/retrieval.py +189 -0
- ksadk/memory/store_adapter.py +150 -0
- ksadk/model_policy.py +2 -2
- ksadk/model_proxy/detect.py +254 -0
- ksadk/model_proxy/server.py +14 -7
- ksadk/model_proxy/transform.py +40 -2
- ksadk/plugins/__init__.py +5 -1
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +4 -2
- ksadk/plugins/bridges/codex.py +120 -13
- ksadk/plugins/bridges/dsh.py +351 -156
- ksadk/plugins/builtins.py +72 -35
- ksadk/plugins/bundle_security.py +28 -4
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/companion_artifacts.py +83 -0
- ksadk/plugins/companions.py +368 -0
- ksadk/plugins/composition.py +8 -0
- ksadk/plugins/contracts.py +119 -1
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_channels.py +156 -0
- ksadk/plugins/dsh_home.py +140 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_teams.py +105 -0
- ksadk/plugins/dsh_toolchain.py +203 -32
- ksadk/plugins/ecosystem_probe.py +6 -6
- ksadk/plugins/execution_host.py +99 -0
- ksadk/plugins/host.py +102 -39
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +23 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/client.js +19 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/index.mjs +7 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/package.json +12 -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/dsh-teams-client/client.js +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/index.mjs +11 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/package.json +35 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/index.mjs +13 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/index.mjs +12 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/package.json +26 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/index.mjs +25 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/tools.json +235 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +1 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +920 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/client.mjs +133 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/index.mjs +14 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +115 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
- ksadk/plugins/providers/codex.py +344 -70
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh_capabilities.py +1450 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +294 -141
- ksadk/plugins/providers/harness_delegation.py +593 -0
- ksadk/plugins/providers/harness_managed.py +456 -0
- ksadk/plugins/providers/harness_tools.py +326 -0
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/providers/shipped_dsh.py +4 -1
- ksadk/plugins/resolver.py +8 -1
- ksadk/plugins/subagent_providers/codex.py +28 -6
- ksadk/plugins/teams/__init__.py +5 -0
- ksadk/plugins/teams/api.py +405 -0
- ksadk/plugins/teams/application.py +680 -0
- ksadk/plugins/teams/artifacts.py +60 -0
- ksadk/plugins/teams/context.py +96 -0
- ksadk/plugins/teams/contracts.py +136 -0
- ksadk/plugins/teams/domain.py +1427 -0
- ksadk/plugins/teams/domain_values.py +24 -0
- ksadk/plugins/teams/errors.py +13 -0
- ksadk/plugins/teams/migration.py +311 -0
- ksadk/plugins/teams/migration_cli.py +322 -0
- ksadk/plugins/teams/postgres_store.py +138 -0
- ksadk/plugins/teams/runtime.py +777 -0
- ksadk/plugins/teams/source_projection.py +84 -0
- ksadk/plugins/teams/store.py +311 -0
- ksadk/plugins/teams/task_decisions.py +423 -0
- ksadk/plugins/teams/transport.py +91 -0
- ksadk/plugins/teams/workspaces.py +255 -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 +182 -38
- ksadk/runners/_langgraph_state_reader.py +106 -0
- ksadk/runners/_session_identity.py +285 -0
- ksadk/runners/adk_runner.py +166 -63
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +542 -195
- ksadk/runners/patch_langchain.py +47 -0
- ksadk/runners/usage_accumulator.py +11 -3
- ksadk/runtime/_runner_adapter/stream_mapping.py +194 -20
- ksadk/runtime/adapter.py +2 -0
- ksadk/runtime/conversation_execution.py +117 -17
- ksadk/runtime/executor.py +87 -3
- ksadk/runtime/factory.py +65 -274
- ksadk/runtime/framework_adapters.py +23 -0
- ksadk/runtime/preprocessing.py +21 -5
- ksadk/runtime/runner_adapter.py +106 -18
- ksadk/runtime/skill_eval_result.py +36 -0
- ksadk/runtime/timing.py +46 -0
- ksadk/runtime/usage.py +49 -18
- ksadk/runtime_context.py +142 -2
- ksadk/sandbox/backends/e2b.py +288 -25
- ksadk/sandbox/backends/local_process.py +72 -39
- ksadk/sandbox/base.py +64 -1
- ksadk/sandbox/diagnostics.py +82 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/sandbox/local_controls.py +746 -0
- ksadk/sandbox/local_launcher.py +90 -0
- ksadk/scheduler/dispatcher.py +1 -1
- ksadk/scheduler/sqlite_store.py +18 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/invocation_identity.py +118 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/common.py +32 -3
- ksadk/server/routes/control.py +271 -52
- ksadk/server/routes/dependencies.py +16 -0
- ksadk/server/routes/kernel_ingress.py +9 -1
- ksadk/server/routes/misc.py +233 -25
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/openai_compat.py +76 -13
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/run.py +106 -35
- ksadk/server/routes/sessions.py +491 -138
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/routes/workspace.py +130 -21
- ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-DHuAWfr5.js} +10 -7
- ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
- ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-DeBkbJvI.js} +9 -9
- ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
- ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-C35w-pn1.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-BCtGGkhN.js} +1 -1
- ksadk/server/static/assets/channel-_KDifNys.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-Bx1jS-X-.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
- ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-B7nCawed.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
- ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
- ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-1nXCdsej.js} +1 -1
- ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-2vL2sAdF.js} +1 -1
- ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-B3bA05-e.js} +1 -1
- ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-BLpRy_Yx.js} +1 -1
- ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-BO_UwatH.js} +1 -1
- ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-BdNFAney.js} +1 -1
- ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-C0J5_3qM.js} +1 -1
- ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-CGt_UGeO.js} +1 -1
- ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CIRMvUM4.js} +1 -1
- ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-CIpWk_5f.js} +1 -1
- ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-CPyieXEf.js} +1 -1
- ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-D-92S-Fd.js} +1 -1
- ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-DNKuMzWc.js} +1 -1
- ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-DWfdmz9s.js} +2 -2
- ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DppE_r-D.js} +1 -1
- ksadk/server/static/assets/{dist-C71CsujO.js → dist-DyG6Ya-z.js} +1 -1
- ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-M-SrdhhZ.js} +1 -1
- ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-mqD5TZup.js} +1 -1
- ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-n3n6t_FO.js} +1 -1
- ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-qe8xjesy.js} +1 -1
- ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-t6MzE0jU.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-Dpz9_0zn.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-DcxzRwYC.js} +1 -1
- ksadk/server/static/assets/index-BMd2mucF.css +2 -0
- ksadk/server/static/assets/index-D5qyyhTH.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
- ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-mtjOi4KM.js} +1 -1
- ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-BETqsxE_.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-DPWrvs90.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-CJG2mfBP.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-4d78KiEY.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-CMD3x_U_.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +34 -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/invocation_identity.py +235 -0
- 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/__init__.py +26 -0
- ksadk/skills/events.py +464 -0
- ksadk/skills/manifest_cache.py +263 -0
- ksadk/skills/mcp_server/__init__.py +0 -0
- ksadk/skills/mcp_server/_registry.py +33 -0
- ksadk/skills/mcp_server/_routing.py +26 -0
- ksadk/skills/mcp_server/_workspace_files.py +160 -0
- ksadk/skills/mcp_server/register.py +415 -0
- ksadk/skills/mcp_server/server.py +218 -0
- ksadk/skills/models.py +37 -4
- ksadk/skills/observability.py +132 -0
- ksadk/skills/package_store.py +261 -40
- ksadk/skills/runtime/agent.py +67 -9
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/artifacts.py +87 -0
- ksadk/skills/runtime/backends/e2b.py +460 -27
- ksadk/skills/runtime/backends/local.py +629 -62
- ksadk/skills/runtime/base.py +81 -7
- ksadk/skills/runtime/executor.py +268 -1
- ksadk/skills/runtime/loader.py +118 -5
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +49 -0
- ksadk/skills/service_client.py +167 -28
- ksadk/skills/tool_defs.py +108 -3
- ksadk/studio/api.py +810 -93
- ksadk/studio/api_catalog_routes.py +18 -0
- ksadk/studio/api_contracts.py +8 -2
- ksadk/studio/api_plugin_routes.py +562 -104
- ksadk/studio/api_resource_connections.py +221 -0
- ksadk/studio/authoring.py +12 -6
- ksadk/studio/authoring_coordinator.py +23 -16
- ksadk/studio/builder.py +88 -0
- ksadk/studio/capabilities.py +23 -6
- ksadk/studio/channel_connections.py +333 -0
- ksadk/studio/cloud.py +370 -112
- ksadk/studio/cloud_shared_web.py +638 -0
- ksadk/studio/codex_agent_service.py +130 -28
- ksadk/studio/codex_builder.py +242 -3
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +31 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +190 -26
- ksadk/studio/compatibility_report.py +12 -1
- ksadk/studio/compiler.py +88 -14
- ksadk/studio/configuration.py +182 -0
- ksadk/studio/contracts.py +165 -11
- ksadk/studio/dsh_application.py +247 -0
- ksadk/studio/dsh_capability_service.py +1374 -0
- ksadk/studio/dsh_lifecycle.py +58 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +367 -21
- ksadk/studio/entry.py +53 -0
- ksadk/studio/event_store.py +36 -5
- ksadk/studio/execution_host.py +525 -0
- ksadk/studio/framework_run.py +32 -10
- ksadk/studio/hosted_kernel.py +89 -14
- ksadk/studio/kernel_registry.py +418 -0
- ksadk/studio/kernel_sqlite_migration.py +181 -0
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +1180 -66
- ksadk/studio/model_profile_service.py +26 -11
- ksadk/studio/native_documents.py +172 -0
- ksadk/studio/plugin_composition.py +202 -24
- ksadk/studio/plugin_kernel_adapter.py +21 -106
- ksadk/studio/plugin_lifecycle.py +80 -0
- ksadk/studio/plugin_runtime.py +448 -56
- ksadk/studio/provider_recovery.py +59 -0
- ksadk/studio/recovery_page.py +70 -0
- ksadk/studio/resource_authority.py +664 -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 -2
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_activity.py +895 -0
- ksadk/studio/run_documents.py +127 -0
- ksadk/studio/run_service.py +789 -83
- ksadk/studio/runtime_catalog.py +53 -10
- ksadk/studio/runtime_source.py +16 -8
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +32 -280
- ksadk/studio/scheduler_service.py +3 -0
- ksadk/studio/service.py +861 -120
- ksadk/studio/shared_web.py +579 -82
- ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +8 -0
- ksadk/studio/static/assets/CodeBlock-DMIf4h33-UIqo-BPW.js +44 -0
- ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -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-BesSeCYl-BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-OhNwH4K9.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
- ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-g0I-I4dD.js +59 -0
- ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
- ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CLB4L11u.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BOma_Z_F.js +38 -0
- ksadk/studio/static/assets/channel-r8itPEik.js +1 -0
- ksadk/studio/static/assets/chunk-2E4U76K2-BFf_huql.js +2 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-2ZTRR5NV-C2qZJila.js +2 -0
- ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-DVtDP4rm.js +62 -0
- ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-6AZGARVD-BB6FqMl-.js +1 -0
- ksadk/studio/static/assets/chunk-6EIED4P4-DdUJkP0f.js +1 -0
- ksadk/studio/static/assets/chunk-6K3QC6MW-CqVsVn-y.js +1 -0
- ksadk/studio/static/assets/chunk-6TQVIW2G-DKlLbNIP.js +1 -0
- ksadk/studio/static/assets/chunk-747NJXEK-BFkZPlab.js +2 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-BZNhM4vB.js +2 -0
- ksadk/studio/static/assets/chunk-CLGD4ZFX-D-GTtyKs.js +1 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-CpEZCUgg.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DE_8H717.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-BfEB0lNv.js +1 -0
- ksadk/studio/static/assets/chunk-I5DQTOEV-Hm2LfiYI.js +1 -0
- ksadk/studio/static/assets/chunk-ICYGCRZG-749o-pGJ.js +1 -0
- ksadk/studio/static/assets/chunk-IH6LHLGP-CC6I9F3i.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-D38axYOR.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-KI3K4JFJ-Rma-0k_M.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Dq5xn7aL.js +1 -0
- ksadk/studio/static/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-DiCQjx9b.js +10 -0
- ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-VdhKmfYq.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-C1_rzO5M.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-B45HvflI.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DsCFnRVE.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DljApgRX.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-DWqRtyqa.js +206 -0
- ksadk/studio/static/assets/chunk-TLUHSLCS-DUeGgnD5.js +2 -0
- ksadk/studio/static/assets/chunk-UY3FDG6J-CnmaAkG5.js +1 -0
- ksadk/studio/static/assets/chunk-XHIXRSVI-BFQ6B8BE.js +1 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/clsx-DB0hHKMi.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-om8AY0Mc.js +1 -0
- ksadk/studio/static/assets/createLucideIcon-DR0LGTP5.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-6BrmK52S.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.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-C6aH78c4.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-DY_tQ6C_.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-DX9p5cQT.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-DB2WSH8X.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-Ce1BJwHE.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-CGthTMmJ.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-CZ1tEenp.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BfoAZW9X.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-S985OIJF.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
- ksadk/studio/static/assets/index-CfEnms6Y.css +2 -0
- ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
- ksadk/studio/static/assets/index.dom-BQenBtFm.js +1 -0
- ksadk/studio/static/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-CO3W8tFn.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-BUGEl8cO.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-Ch2ZYxvr.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-Da-Fp4vC.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
- ksadk/studio/static/assets/line-BDaeq300.js +1 -0
- ksadk/studio/static/assets/linear-DmucvK78.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-Cj5mYdBi.js +4 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-CvlsVQ38.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-BuHuNgT5.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-DlrWiSOv.js +39 -0
- ksadk/studio/static/assets/preload-helper-CO68xz6u.js +1 -0
- ksadk/studio/static/assets/presentation-yYw7xK60-BmcZriri.js +1 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-BA3hpUZM.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-BxpAazym.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-E-Ge0FcV.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-CA6YKhQ3.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-CcElXGg4.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-B6xuSHsQ.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DdXZOFqY.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-CJbOM-QK.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-NtgEEHLY.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-D-AVlW8B.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-CIuYhNy3.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-7HbApbrv.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-CMJiaedy.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-BdgtMvW2.js +7 -0
- ksadk/studio/static/index.html +8 -2
- ksadk/studio/teams_catalog.py +133 -0
- ksadk/studio/teams_installation.py +214 -0
- ksadk/studio/teams_node.py +545 -0
- ksadk/studio/teams_node_runner.py +69 -0
- ksadk/studio/teams_remote.py +274 -0
- ksadk/studio/templates.py +40 -19
- ksadk/studio/validator.py +13 -0
- ksadk/studio/workspace.py +19 -4
- ksadk/studio/workspace_plugins.py +136 -0
- ksadk/studio/workspace_registry.py +286 -0
- ksadk/toolsets/__init__.py +11 -0
- ksadk/toolsets/skills.py +446 -378
- ksadk/toolsets/workspace.py +3 -3
- ksadk/toolsets/workspace_identity.py +15 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/providers/lancedb.py +56 -2
- ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -148
- ksadk_runtime_common/workspace_files/router.py +26 -13
- agentengine_sdk_python-0.8.3.dist-info/RECORD +0 -833
- ksadk/server/static/assets/MathMessageMarkdown-D9uB55Oh.js +0 -8
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
- ksadk/server/static/assets/dist-DdRBIceA.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
- ksadk/server/static/assets/index-B2k_urY8.js +0 -241
- ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
- ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
ksadk/plugins/bridges/dsh.py
CHANGED
|
@@ -13,6 +13,7 @@ import json
|
|
|
13
13
|
import os
|
|
14
14
|
import re
|
|
15
15
|
import shutil
|
|
16
|
+
import signal
|
|
16
17
|
import stat
|
|
17
18
|
import subprocess
|
|
18
19
|
import tempfile
|
|
@@ -28,8 +29,16 @@ try:
|
|
|
28
29
|
except ImportError: # pragma: no cover - DSH production hosts are Unix
|
|
29
30
|
fcntl = None # type: ignore[assignment]
|
|
30
31
|
|
|
32
|
+
import yaml
|
|
31
33
|
from pydantic import BaseModel, ConfigDict
|
|
32
34
|
|
|
35
|
+
from ksadk.plugins.dsh_installation_digest import (
|
|
36
|
+
DshInstallationDigestError,
|
|
37
|
+
installation_digest,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
_COMMAND_TIMEOUT_SECONDS = 120
|
|
41
|
+
|
|
33
42
|
|
|
34
43
|
def _to_camel(value: str) -> str:
|
|
35
44
|
head, *tail = value.split("_")
|
|
@@ -52,18 +61,6 @@ class DshBridgeHost(_DshModel):
|
|
|
52
61
|
available: Literal[True] = True
|
|
53
62
|
|
|
54
63
|
|
|
55
|
-
class DshClientBundle(_DshModel):
|
|
56
|
-
"""One validated browser half from an installed DSH package."""
|
|
57
|
-
|
|
58
|
-
platform: Literal["web"] = "web"
|
|
59
|
-
digest: str
|
|
60
|
-
content_bytes: int
|
|
61
|
-
external: tuple[str, ...] = ()
|
|
62
|
-
inject: tuple[str, ...] = ()
|
|
63
|
-
compatible: bool
|
|
64
|
-
incompatibility_reason: str = ""
|
|
65
|
-
|
|
66
|
-
|
|
67
64
|
class DshPluginInventory(_DshModel):
|
|
68
65
|
ecosystem: Literal["dsh"] = "dsh"
|
|
69
66
|
integration_mode: Literal["bridged"] = "bridged"
|
|
@@ -75,10 +72,11 @@ class DshPluginInventory(_DshModel):
|
|
|
75
72
|
requested_spec: str
|
|
76
73
|
source_digest: str | None = None
|
|
77
74
|
source_kind: Literal["directory", "tgz"] | None = None
|
|
75
|
+
client_extension: bool = False
|
|
76
|
+
settings_integration: bool = False
|
|
78
77
|
installed: Literal[True] = True
|
|
79
78
|
enabled: bool
|
|
80
79
|
permissions_declared: Literal[False] = False
|
|
81
|
-
client_bundle: DshClientBundle | None = None
|
|
82
80
|
risk_disclosures: tuple[str, ...] = (
|
|
83
81
|
"DSH packages and install scripts run with the native host user privileges.",
|
|
84
82
|
"DSH bundle manifests do not declare a complete runtime permission set.",
|
|
@@ -93,6 +91,19 @@ class DshProfileProjection(_DshModel):
|
|
|
93
91
|
host_version: str
|
|
94
92
|
|
|
95
93
|
|
|
94
|
+
class DshProfileBuildSnapshot(_DshModel):
|
|
95
|
+
"""Credential-free identity of the actual local profile execution inputs."""
|
|
96
|
+
|
|
97
|
+
projection: DshProfileProjection
|
|
98
|
+
dependency_lock_digest: str
|
|
99
|
+
installation_digest: str
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def digest(self) -> str:
|
|
103
|
+
payload = json.dumps(self.model_dump(mode="json"), sort_keys=True, separators=(",", ":"))
|
|
104
|
+
return "sha256:" + hashlib.sha256(payload.encode()).hexdigest()
|
|
105
|
+
|
|
106
|
+
|
|
96
107
|
class DshBridgeError(RuntimeError):
|
|
97
108
|
"""Base failure for one bounded DSH profile operation."""
|
|
98
109
|
|
|
@@ -113,6 +124,10 @@ class DshPluginMutationError(DshBridgeError):
|
|
|
113
124
|
pass
|
|
114
125
|
|
|
115
126
|
|
|
127
|
+
class DshProfileRecoveryError(DshPluginMutationError):
|
|
128
|
+
"""The owner must keep run admission suspended until profile recovery."""
|
|
129
|
+
|
|
130
|
+
|
|
116
131
|
class _CommandResult(_DshModel):
|
|
117
132
|
stdout: str = ""
|
|
118
133
|
stderr: str = ""
|
|
@@ -122,13 +137,16 @@ CommandRunner = Callable[[Sequence[str], Path, Mapping[str, str]], _CommandResul
|
|
|
122
137
|
|
|
123
138
|
_PROFILE_NAME = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$")
|
|
124
139
|
_PACKAGE_NAME = re.compile(r"^(?:@[A-Za-z0-9._-]+/)?[A-Za-z0-9._-]+$")
|
|
140
|
+
_PINNED_REGISTRY_SOURCE = re.compile(
|
|
141
|
+
r"^(?:@[A-Za-z0-9._-]+/)?[A-Za-z0-9._-]+@"
|
|
142
|
+
r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$"
|
|
143
|
+
)
|
|
125
144
|
_HOST_VERSION = re.compile(r"\b(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b")
|
|
126
145
|
_STATE_FILE = ".ksadk-dsh-plugins.json"
|
|
127
146
|
_IMMUTABLE_SOURCE_DIR = "immutable-plugin-sources"
|
|
128
147
|
_SNAPSHOT_FILES = ("package.json", "pnpm-lock.yaml", "pnpm-workspace.yaml", _STATE_FILE)
|
|
148
|
+
_WEB_PROFILE_BUILTINS = ("@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app")
|
|
129
149
|
_MAX_JSON_BYTES = 2 * 1024 * 1024
|
|
130
|
-
_MAX_CLIENT_BUNDLE_BYTES = 8 * 1024 * 1024
|
|
131
|
-
_STUDIO_CLIENT_EXTERNALS = frozenset({"react"})
|
|
132
150
|
_PROFILE_LOCK_DIR = "profile-locks"
|
|
133
151
|
_DSH_SUBPROCESS_ENV_KEYS = (
|
|
134
152
|
"PATH",
|
|
@@ -165,6 +183,26 @@ _DSH_SUBPROCESS_ENV_KEYS = (
|
|
|
165
183
|
)
|
|
166
184
|
|
|
167
185
|
|
|
186
|
+
def validate_dsh_registry_source(source: str) -> str:
|
|
187
|
+
"""Return one exact, credential-free npm registry package coordinate."""
|
|
188
|
+
|
|
189
|
+
value = source.strip()
|
|
190
|
+
if not _PINNED_REGISTRY_SOURCE.fullmatch(value):
|
|
191
|
+
raise ValueError(
|
|
192
|
+
"DSH registry source must be <package>@<exact-semver>; "
|
|
193
|
+
"Git URLs, tags, and ranges are not allowed"
|
|
194
|
+
)
|
|
195
|
+
return value
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def validate_dsh_registry_request(source: str) -> str:
|
|
199
|
+
"""Accept a package name for latest resolution, or an exact coordinate."""
|
|
200
|
+
value = source.strip()
|
|
201
|
+
if len(value) <= 214 and not value.startswith("-") and _PACKAGE_NAME.fullmatch(value):
|
|
202
|
+
return value
|
|
203
|
+
return validate_dsh_registry_source(value)
|
|
204
|
+
|
|
205
|
+
|
|
168
206
|
def dsh_subprocess_environment(*, dsh_home: Path | None = None) -> dict[str, str]:
|
|
169
207
|
"""Build the explicit environment inherited by DSH and pnpm children.
|
|
170
208
|
|
|
@@ -205,6 +243,12 @@ class _PreparedSource:
|
|
|
205
243
|
artifact: str
|
|
206
244
|
|
|
207
245
|
|
|
246
|
+
@dataclass(frozen=True)
|
|
247
|
+
class _ProfileSnapshot:
|
|
248
|
+
files: Mapping[str, bytes | None]
|
|
249
|
+
node_modules_existed: bool
|
|
250
|
+
|
|
251
|
+
|
|
208
252
|
class DshProfilePluginBridge:
|
|
209
253
|
"""Manage DSH bundles in one isolated Profile with rollback and preflight."""
|
|
210
254
|
|
|
@@ -212,7 +256,7 @@ class DshProfilePluginBridge:
|
|
|
212
256
|
self,
|
|
213
257
|
*,
|
|
214
258
|
dsh_home: Path,
|
|
215
|
-
profile: str = "
|
|
259
|
+
profile: str = "web",
|
|
216
260
|
dsh_command: Sequence[str] | None = None,
|
|
217
261
|
command_runner: CommandRunner | None = None,
|
|
218
262
|
cwd: Path | None = None,
|
|
@@ -276,6 +320,14 @@ class DshProfilePluginBridge:
|
|
|
276
320
|
package = self._read_package(name)
|
|
277
321
|
if package is None or self._bundle_patch(package) is None:
|
|
278
322
|
continue
|
|
323
|
+
dsh = package.get("dsh")
|
|
324
|
+
client = dsh.get("client") if isinstance(dsh, dict) else None
|
|
325
|
+
inject = client.get("inject") if isinstance(client, dict) else None
|
|
326
|
+
client_inject = (
|
|
327
|
+
tuple(item for item in inject if isinstance(item, str))
|
|
328
|
+
if isinstance(inject, list)
|
|
329
|
+
else ()
|
|
330
|
+
)
|
|
279
331
|
receipt = state["sources"].get(name)
|
|
280
332
|
items.append(
|
|
281
333
|
DshPluginInventory(
|
|
@@ -289,8 +341,12 @@ class DshProfilePluginBridge:
|
|
|
289
341
|
requested_spec=requested_spec,
|
|
290
342
|
source_digest=receipt["digest"] if receipt is not None else None,
|
|
291
343
|
source_kind=receipt["kind"] if receipt is not None else None,
|
|
344
|
+
client_extension=isinstance(client, dict),
|
|
345
|
+
settings_integration=any(
|
|
346
|
+
"client-ui-settings" in item or "client-ui-slots" in item
|
|
347
|
+
for item in client_inject
|
|
348
|
+
),
|
|
292
349
|
enabled=name in active and name not in set(state["disabled"]),
|
|
293
|
-
client_bundle=self._client_bundle_metadata(name, package),
|
|
294
350
|
)
|
|
295
351
|
)
|
|
296
352
|
return tuple(sorted(items, key=lambda item: (item.display_name.casefold(), item.name)))
|
|
@@ -314,6 +370,7 @@ class DshProfilePluginBridge:
|
|
|
314
370
|
"explicit approval is required"
|
|
315
371
|
)
|
|
316
372
|
self._validate_source(source)
|
|
373
|
+
source = self._resolve_install_source(source.strip())
|
|
317
374
|
with self._profile_transaction(exclusive=True):
|
|
318
375
|
self._require_package_mutation_rollback(new_profile_allowed=True)
|
|
319
376
|
snapshot = self._snapshot()
|
|
@@ -492,36 +549,141 @@ class DshProfilePluginBridge:
|
|
|
492
549
|
host_version=self.host.version,
|
|
493
550
|
)
|
|
494
551
|
|
|
495
|
-
def
|
|
496
|
-
|
|
552
|
+
def migrate_to_isolated_layout(
|
|
553
|
+
self,
|
|
554
|
+
*,
|
|
555
|
+
accept_host_permissions: bool = False,
|
|
556
|
+
recover_external_dependency_links: bool = False,
|
|
557
|
+
) -> None:
|
|
558
|
+
"""Migrate a stopped profile; the caller owns Core/admission suspension.
|
|
497
559
|
|
|
560
|
+
Keep an independent byte copy for rollback: a frozen reinstall of the
|
|
561
|
+
old layout can itself hit the pinned pnpm shutdown defect. Studio-owned
|
|
562
|
+
profiles may also repair an isolated tree polluted by a legacy Core
|
|
563
|
+
module-fallback cache.
|
|
564
|
+
"""
|
|
565
|
+
if not accept_host_permissions:
|
|
566
|
+
raise DshPluginApprovalRequired("Profile migration may run package install scripts")
|
|
567
|
+
with self._profile_transaction(exclusive=True):
|
|
568
|
+
self._require_package_mutation_rollback(new_profile_allowed=False)
|
|
569
|
+
manifest = self._read_manifest()
|
|
570
|
+
self._verify_source_receipts(manifest, self._read_state(manifest))
|
|
571
|
+
settings_path = self._profile_root / "pnpm-workspace.yaml"
|
|
572
|
+
settings = yaml.safe_load(settings_path.read_text(encoding="utf-8"))
|
|
573
|
+
if not isinstance(settings, dict):
|
|
574
|
+
raise DshPluginMutationError("Invalid package-manager settings")
|
|
575
|
+
node_linker = settings.get("nodeLinker")
|
|
576
|
+
if node_linker not in {"hoisted", "isolated"}:
|
|
577
|
+
raise DshPluginMutationError(
|
|
578
|
+
"Only hoisted or isolated profiles can use this migration"
|
|
579
|
+
)
|
|
580
|
+
modules = self._profile_root / "node_modules"
|
|
581
|
+
if modules.is_symlink() or not modules.is_dir():
|
|
582
|
+
raise DshPluginMutationError("Profile installation is not a real directory")
|
|
583
|
+
# A normal migration only accepts a closed tree. Studio may repair
|
|
584
|
+
# its own legacy hoisted Profile when pnpm linked a dependency to
|
|
585
|
+
# an ambient store: move that tree atomically instead of reading or
|
|
586
|
+
# following the external target, then reinstall from the frozen lock.
|
|
587
|
+
moved_unsafe_tree = False
|
|
588
|
+
try:
|
|
589
|
+
original_digest = installation_digest(modules)
|
|
590
|
+
except DshInstallationDigestError as error:
|
|
591
|
+
if (
|
|
592
|
+
not recover_external_dependency_links
|
|
593
|
+
or str(error) != "DSH dependency link escapes the installed tree"
|
|
594
|
+
):
|
|
595
|
+
raise
|
|
596
|
+
original_digest = None
|
|
597
|
+
moved_unsafe_tree = True
|
|
598
|
+
if node_linker == "isolated" and not moved_unsafe_tree:
|
|
599
|
+
self._preflight()
|
|
600
|
+
return
|
|
601
|
+
fallback = self._profile_root / ".dsh-module-fallback"
|
|
602
|
+
if fallback.exists() and (fallback.is_symlink() or not fallback.is_dir()):
|
|
603
|
+
raise DshPluginMutationError("DSH module fallback is not a real directory")
|
|
604
|
+
snapshot = self._snapshot()
|
|
605
|
+
root = tempfile.mkdtemp(prefix=".layout-backup-", dir=self._profile_root)
|
|
606
|
+
preserve_backup = False
|
|
607
|
+
try:
|
|
608
|
+
backup = Path(root) / "node_modules"
|
|
609
|
+
fallback_backup = Path(root) / "module-fallback"
|
|
610
|
+
if moved_unsafe_tree:
|
|
611
|
+
os.replace(modules, backup)
|
|
612
|
+
else:
|
|
613
|
+
shutil.copytree(modules, backup, symlinks=True)
|
|
614
|
+
if installation_digest(backup) != original_digest:
|
|
615
|
+
raise DshPluginMutationError("Profile installation backup did not verify")
|
|
616
|
+
fallback_moved = fallback.is_dir()
|
|
617
|
+
if fallback_moved:
|
|
618
|
+
os.replace(fallback, fallback_backup)
|
|
619
|
+
original_files = Path(root) / "profile-files"
|
|
620
|
+
original_files.mkdir(mode=0o700)
|
|
621
|
+
for name, content in snapshot.files.items():
|
|
622
|
+
if content is not None:
|
|
623
|
+
original_path = original_files / name
|
|
624
|
+
original_path.write_bytes(content)
|
|
625
|
+
original_path.chmod(0o600)
|
|
626
|
+
try:
|
|
627
|
+
if not moved_unsafe_tree:
|
|
628
|
+
shutil.rmtree(modules)
|
|
629
|
+
settings["nodeLinker"] = "isolated"
|
|
630
|
+
settings_path.write_text(yaml.safe_dump(settings), encoding="utf-8")
|
|
631
|
+
settings_path.chmod(0o600)
|
|
632
|
+
self._plugin_command("install", "--frozen-lockfile")
|
|
633
|
+
current_lock = (self._profile_root / "pnpm-lock.yaml").read_bytes()
|
|
634
|
+
if current_lock != snapshot.files["pnpm-lock.yaml"]:
|
|
635
|
+
raise DshPluginMutationError("Layout migration changed the dependency lock")
|
|
636
|
+
# Native reconcile can re-enable previously disabled bundles.
|
|
637
|
+
for name in ("package.json", _STATE_FILE):
|
|
638
|
+
content = snapshot.files[name]
|
|
639
|
+
path = self._profile_root / name
|
|
640
|
+
if content is None:
|
|
641
|
+
path.unlink(missing_ok=True)
|
|
642
|
+
else:
|
|
643
|
+
path.write_bytes(content)
|
|
644
|
+
path.chmod(0o600)
|
|
645
|
+
self._verify_source_receipts(manifest, self._read_state(manifest))
|
|
646
|
+
self._preflight()
|
|
647
|
+
except BaseException as error:
|
|
648
|
+
try:
|
|
649
|
+
if modules.is_symlink():
|
|
650
|
+
modules.unlink()
|
|
651
|
+
elif modules.exists():
|
|
652
|
+
shutil.rmtree(modules)
|
|
653
|
+
os.replace(backup, modules)
|
|
654
|
+
if fallback.is_symlink():
|
|
655
|
+
fallback.unlink()
|
|
656
|
+
elif fallback.exists():
|
|
657
|
+
shutil.rmtree(fallback)
|
|
658
|
+
if fallback_moved:
|
|
659
|
+
os.replace(fallback_backup, fallback)
|
|
660
|
+
self._rollback(snapshot, error, reinstall=False)
|
|
661
|
+
except BaseException as recovery_error:
|
|
662
|
+
preserve_backup = True
|
|
663
|
+
raise DshProfileRecoveryError(
|
|
664
|
+
"Profile layout recovery failed; retain the layout backup for recovery"
|
|
665
|
+
) from recovery_error
|
|
666
|
+
raise
|
|
667
|
+
finally:
|
|
668
|
+
if not preserve_backup:
|
|
669
|
+
shutil.rmtree(root)
|
|
670
|
+
|
|
671
|
+
def snapshot_for_build(self) -> DshProfileBuildSnapshot:
|
|
672
|
+
"""Capture exact local inputs under the same profile mutation lock."""
|
|
498
673
|
with self._profile_transaction(exclusive=False):
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
raise DshPluginNotFoundError(
|
|
508
|
-
f"DSH plugin {name!r} has no Studio-compatible client bundle"
|
|
674
|
+
projection = self.project_profile()
|
|
675
|
+
lock = self._profile_root / "pnpm-lock.yaml"
|
|
676
|
+
if lock.is_symlink() or not lock.is_file() or lock.stat().st_size > 16 * 1024 * 1024:
|
|
677
|
+
raise DshPluginMutationError("DSH Build requires a bounded dependency lockfile")
|
|
678
|
+
return DshProfileBuildSnapshot(
|
|
679
|
+
projection=projection,
|
|
680
|
+
dependency_lock_digest="sha256:" + hashlib.sha256(lock.read_bytes()).hexdigest(),
|
|
681
|
+
installation_digest=installation_digest(self._profile_root / "node_modules"),
|
|
509
682
|
)
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
path = self._client_bundle_path(name, package)
|
|
515
|
-
if path is None:
|
|
516
|
-
raise DshPluginNotFoundError(f"DSH plugin {name!r} client bundle is unavailable")
|
|
517
|
-
try:
|
|
518
|
-
content = path.read_bytes()
|
|
519
|
-
except OSError as error:
|
|
520
|
-
raise DshPluginMutationError("DSH client bundle became unreadable") from error
|
|
521
|
-
actual_digest = f"sha256:{hashlib.sha256(content).hexdigest()}"
|
|
522
|
-
if actual_digest != expected_digest:
|
|
523
|
-
raise DshPluginMutationError("DSH client bundle changed after inventory projection")
|
|
524
|
-
return content
|
|
683
|
+
|
|
684
|
+
def verify_build_snapshot(self, expected: DshProfileBuildSnapshot) -> None:
|
|
685
|
+
if self.snapshot_for_build() != expected:
|
|
686
|
+
raise DshPluginMutationError("DSH installed profile no longer matches the Build")
|
|
525
687
|
|
|
526
688
|
def _resolve_command(self) -> tuple[str, ...]:
|
|
527
689
|
if self._command is not None:
|
|
@@ -607,10 +769,26 @@ class DshProfilePluginBridge:
|
|
|
607
769
|
def _plugin_command(self, verb: str, value: str) -> _CommandResult:
|
|
608
770
|
self._ensure_started()
|
|
609
771
|
assert self._command is not None
|
|
610
|
-
|
|
611
|
-
|
|
772
|
+
initializing = verb == "add" and not self._manifest_path().exists()
|
|
773
|
+
# The pinned pnpm hoisted linker can start fetch workers after its
|
|
774
|
+
# shutdown pass during removal. Use its supported isolated layout for
|
|
775
|
+
# newly owned profiles, without changing an existing profile's policy.
|
|
776
|
+
options = ("--config.node-linker=isolated",) if initializing else ()
|
|
777
|
+
result = self._invoke(
|
|
778
|
+
(*self._command, "plugin", "--profile", self._profile, verb, value, *options),
|
|
612
779
|
cwd=self._cwd,
|
|
613
780
|
)
|
|
781
|
+
if initializing:
|
|
782
|
+
settings_path = self._profile_root / "pnpm-workspace.yaml"
|
|
783
|
+
settings = yaml.safe_load(settings_path.read_text(encoding="utf-8"))
|
|
784
|
+
if not isinstance(settings, dict):
|
|
785
|
+
raise DshPluginMutationError("DSH initialized invalid package-manager settings")
|
|
786
|
+
settings["nodeLinker"] = "isolated"
|
|
787
|
+
# This is a newly created profile inside the install transaction;
|
|
788
|
+
# any subsequent failure removes it through the existing rollback.
|
|
789
|
+
settings_path.write_text(yaml.safe_dump(settings), encoding="utf-8")
|
|
790
|
+
settings_path.chmod(0o600)
|
|
791
|
+
return result
|
|
614
792
|
|
|
615
793
|
def _preflight(self) -> _CommandResult:
|
|
616
794
|
self._ensure_started()
|
|
@@ -677,100 +855,31 @@ class DshProfilePluginBridge:
|
|
|
677
855
|
patch = bundle.get("patch") if isinstance(bundle, dict) else None
|
|
678
856
|
return patch.strip() if isinstance(patch, str) and patch.strip() else None
|
|
679
857
|
|
|
680
|
-
@staticmethod
|
|
681
|
-
def _client_declaration(package: Mapping[str, object]) -> Mapping[str, object] | None:
|
|
682
|
-
dsh = package.get("dsh")
|
|
683
|
-
client = dsh.get("client") if isinstance(dsh, dict) else None
|
|
684
|
-
return client if isinstance(client, dict) else None
|
|
685
|
-
|
|
686
|
-
@staticmethod
|
|
687
|
-
def _string_tuple(value: object) -> tuple[str, ...] | None:
|
|
688
|
-
if value is None:
|
|
689
|
-
return ()
|
|
690
|
-
if not isinstance(value, list) or any(not isinstance(item, str) for item in value):
|
|
691
|
-
return None
|
|
692
|
-
return tuple(value)
|
|
693
|
-
|
|
694
|
-
@staticmethod
|
|
695
|
-
def _client_export(package: Mapping[str, object]) -> str | None:
|
|
696
|
-
exports = package.get("exports")
|
|
697
|
-
client = exports.get("./client") if isinstance(exports, dict) else None
|
|
698
|
-
if isinstance(client, str):
|
|
699
|
-
return client
|
|
700
|
-
default = client.get("default") if isinstance(client, dict) else None
|
|
701
|
-
return default if isinstance(default, str) else None
|
|
702
|
-
|
|
703
|
-
def _client_bundle_path(
|
|
704
|
-
self, name: str, package: Mapping[str, object]
|
|
705
|
-
) -> Path | None:
|
|
706
|
-
declared = self._client_export(package)
|
|
707
|
-
if not declared:
|
|
708
|
-
return None
|
|
709
|
-
relative = Path(declared)
|
|
710
|
-
if relative.is_absolute() or ".." in relative.parts:
|
|
711
|
-
return None
|
|
712
|
-
root = (self._profile_root / "node_modules" / Path(*name.split("/"))).resolve()
|
|
713
|
-
target = (root / relative).resolve()
|
|
714
|
-
if not target.is_relative_to(root) or not target.is_file():
|
|
715
|
-
return None
|
|
716
|
-
return target
|
|
717
|
-
|
|
718
|
-
def _client_bundle_metadata(
|
|
719
|
-
self, name: str, package: Mapping[str, object]
|
|
720
|
-
) -> DshClientBundle | None:
|
|
721
|
-
declaration = self._client_declaration(package)
|
|
722
|
-
if declaration is None or declaration.get("platform") != "web":
|
|
723
|
-
return None
|
|
724
|
-
inject = self._string_tuple(declaration.get("inject"))
|
|
725
|
-
external = self._string_tuple(declaration.get("external"))
|
|
726
|
-
target = self._client_bundle_path(name, package)
|
|
727
|
-
reason = ""
|
|
728
|
-
if inject is None or external is None:
|
|
729
|
-
reason = "dsh.client inject/external must be string arrays"
|
|
730
|
-
elif target is None:
|
|
731
|
-
reason = "exports[./client] does not resolve to a built bundle"
|
|
732
|
-
elif inject:
|
|
733
|
-
reason = "client bundle dependencies are not present in the Studio graph"
|
|
734
|
-
elif any(item not in _STUDIO_CLIENT_EXTERNALS for item in external):
|
|
735
|
-
reason = "client bundle requests unsupported external modules"
|
|
736
|
-
if target is None:
|
|
737
|
-
return DshClientBundle(
|
|
738
|
-
digest="",
|
|
739
|
-
content_bytes=0,
|
|
740
|
-
inject=inject or (),
|
|
741
|
-
external=external or (),
|
|
742
|
-
compatible=False,
|
|
743
|
-
incompatibility_reason=reason,
|
|
744
|
-
)
|
|
745
|
-
try:
|
|
746
|
-
size = target.stat().st_size
|
|
747
|
-
if size > _MAX_CLIENT_BUNDLE_BYTES:
|
|
748
|
-
reason = "client bundle exceeds the supported size limit"
|
|
749
|
-
content = b""
|
|
750
|
-
else:
|
|
751
|
-
content = target.read_bytes()
|
|
752
|
-
except OSError:
|
|
753
|
-
size = 0
|
|
754
|
-
content = b""
|
|
755
|
-
reason = "client bundle is unreadable"
|
|
756
|
-
return DshClientBundle(
|
|
757
|
-
digest=f"sha256:{hashlib.sha256(content).hexdigest()}" if content else "",
|
|
758
|
-
content_bytes=size,
|
|
759
|
-
inject=inject or (),
|
|
760
|
-
external=external or (),
|
|
761
|
-
compatible=not reason,
|
|
762
|
-
incompatibility_reason=reason,
|
|
763
|
-
)
|
|
764
|
-
|
|
765
858
|
def _require_bundle(self, name: str) -> None:
|
|
766
859
|
package = self._read_package(name)
|
|
767
|
-
|
|
768
|
-
if package is None or patch is None:
|
|
860
|
+
if package is None:
|
|
769
861
|
raise DshPluginMutationError(f"{name} does not declare dsh.bundle.patch")
|
|
862
|
+
patch = self._bundle_patch(package)
|
|
863
|
+
root = (self._profile_root / "node_modules" / Path(*name.split("/"))).resolve()
|
|
864
|
+
if patch is None:
|
|
865
|
+
# Real upstream plugins may ship without a dsh.bundle.patch yet
|
|
866
|
+
# still be valid Cordis tool plugins (inject: ['tools']). Generate
|
|
867
|
+
# a minimal bundle patch so the dsh profile loader activates them.
|
|
868
|
+
# This is a compatibility shim, not a source modification: the
|
|
869
|
+
# plugin's own code is untouched.
|
|
870
|
+
patch_path = root / "cordis.patch.yml"
|
|
871
|
+
patch_path.write_text(
|
|
872
|
+
"- insert:\n - id: "
|
|
873
|
+
+ name.rsplit("/", 1)[-1].replace("-", "_")
|
|
874
|
+
+ "\n name: '" + name + "'\n",
|
|
875
|
+
encoding="utf-8",
|
|
876
|
+
)
|
|
877
|
+
package.setdefault("dsh", {}).setdefault("bundle", {})["patch"] = "./cordis.patch.yml"
|
|
878
|
+
self._write_json(root / "package.json", package)
|
|
879
|
+
patch = "./cordis.patch.yml"
|
|
770
880
|
relative = Path(patch)
|
|
771
881
|
if relative.is_absolute() or ".." in relative.parts:
|
|
772
882
|
raise DshPluginMutationError(f"{name} declares an unsafe bundle patch path")
|
|
773
|
-
root = (self._profile_root / "node_modules" / Path(*name.split("/"))).resolve()
|
|
774
883
|
target = (root / relative).resolve()
|
|
775
884
|
if not target.is_relative_to(root) or not target.is_file():
|
|
776
885
|
raise DshPluginMutationError(f"{name} bundle patch is unavailable")
|
|
@@ -866,9 +975,40 @@ class DshProfilePluginBridge:
|
|
|
866
975
|
manifest["dsh"] = dsh
|
|
867
976
|
self._write_json(self._manifest_path(), manifest)
|
|
868
977
|
|
|
978
|
+
def _resolve_install_source(self, source: str) -> str:
|
|
979
|
+
if not _PACKAGE_NAME.fullmatch(source):
|
|
980
|
+
return source
|
|
981
|
+
# Resolve metadata before running package scripts. The mutable latest
|
|
982
|
+
# selector never reaches `dsh plugin add`; the exact version does.
|
|
983
|
+
result = self._invoke(
|
|
984
|
+
("npm", "view", f"{source}@latest", "version", "--json"), cwd=self._cwd
|
|
985
|
+
)
|
|
986
|
+
try:
|
|
987
|
+
if len(result.stdout) > _MAX_JSON_BYTES:
|
|
988
|
+
raise ValueError("oversized registry response")
|
|
989
|
+
version = json.loads(result.stdout)
|
|
990
|
+
if not isinstance(version, str):
|
|
991
|
+
raise ValueError("expected one version")
|
|
992
|
+
return validate_dsh_registry_source(f"{source}@{version}")
|
|
993
|
+
except (ValueError, TypeError) as error:
|
|
994
|
+
raise DshPluginMutationError(
|
|
995
|
+
"npm latest did not resolve to one exact version"
|
|
996
|
+
) from error
|
|
997
|
+
|
|
869
998
|
def _prepare_source(self, source: str) -> _PreparedSource:
|
|
870
999
|
value = source.strip()
|
|
871
1000
|
candidate = Path(value).expanduser()
|
|
1001
|
+
if not candidate.is_absolute():
|
|
1002
|
+
# dsh CLI 以 Profile 目录为 cwd 解析 add 的源参数;相对当前工作目录
|
|
1003
|
+
# 存在的本地源必须先绝对化,否则会被写成指向不存在位置的 link: 依赖。
|
|
1004
|
+
workspace_relative = self._cwd / candidate
|
|
1005
|
+
if workspace_relative.exists():
|
|
1006
|
+
candidate = workspace_relative
|
|
1007
|
+
elif value.endswith(".tgz"):
|
|
1008
|
+
raise DshPluginMutationError(
|
|
1009
|
+
f"local DSH plugin source does not exist: {value} "
|
|
1010
|
+
f"(resolved against {self._cwd})"
|
|
1011
|
+
)
|
|
872
1012
|
if not candidate.is_absolute() or not candidate.exists():
|
|
873
1013
|
return _PreparedSource(value, "", "tgz", "")
|
|
874
1014
|
local = candidate.resolve()
|
|
@@ -948,9 +1088,7 @@ class DshProfilePluginBridge:
|
|
|
948
1088
|
)
|
|
949
1089
|
artifact = (self._dsh_home / receipt["artifact"]).resolve()
|
|
950
1090
|
if not artifact.is_relative_to(store) or not artifact.is_file():
|
|
951
|
-
raise DshPluginMutationError(
|
|
952
|
-
f"DSH plugin {name!r} immutable source is unavailable"
|
|
953
|
-
)
|
|
1091
|
+
raise DshPluginMutationError(f"DSH plugin {name!r} immutable source is unavailable")
|
|
954
1092
|
try:
|
|
955
1093
|
actual = f"sha256:{hashlib.sha256(artifact.read_bytes()).hexdigest()}"
|
|
956
1094
|
except OSError as error:
|
|
@@ -958,9 +1096,7 @@ class DshProfilePluginBridge:
|
|
|
958
1096
|
f"DSH plugin {name!r} immutable source is unreadable"
|
|
959
1097
|
) from error
|
|
960
1098
|
if actual != receipt["digest"]:
|
|
961
|
-
raise DshPluginMutationError(
|
|
962
|
-
f"DSH plugin {name!r} immutable source digest changed"
|
|
963
|
-
)
|
|
1099
|
+
raise DshPluginMutationError(f"DSH plugin {name!r} immutable source digest changed")
|
|
964
1100
|
|
|
965
1101
|
@staticmethod
|
|
966
1102
|
def _write_json(path: Path, payload: object) -> None:
|
|
@@ -980,15 +1116,18 @@ class DshProfilePluginBridge:
|
|
|
980
1116
|
except FileNotFoundError:
|
|
981
1117
|
pass
|
|
982
1118
|
|
|
983
|
-
def _snapshot(self) ->
|
|
984
|
-
|
|
1119
|
+
def _snapshot(self) -> _ProfileSnapshot:
|
|
1120
|
+
files: dict[str, bytes | None] = {}
|
|
985
1121
|
for name in _SNAPSHOT_FILES:
|
|
986
1122
|
path = self._profile_root / name
|
|
987
1123
|
try:
|
|
988
|
-
|
|
1124
|
+
files[name] = path.read_bytes()
|
|
989
1125
|
except FileNotFoundError:
|
|
990
|
-
|
|
991
|
-
return
|
|
1126
|
+
files[name] = None
|
|
1127
|
+
return _ProfileSnapshot(
|
|
1128
|
+
files=files,
|
|
1129
|
+
node_modules_existed=(self._profile_root / "node_modules").exists(),
|
|
1130
|
+
)
|
|
992
1131
|
|
|
993
1132
|
def _require_package_mutation_rollback(self, *, new_profile_allowed: bool) -> None:
|
|
994
1133
|
"""Reject package mutations unless their filesystem effects are reversible."""
|
|
@@ -1002,13 +1141,31 @@ class DshProfilePluginBridge:
|
|
|
1002
1141
|
"existing DSH profile directory has no package manifest; refusing to mutate it"
|
|
1003
1142
|
)
|
|
1004
1143
|
if not (self._profile_root / "pnpm-lock.yaml").is_file():
|
|
1144
|
+
if new_profile_allowed and self._is_pristine_official_web_profile():
|
|
1145
|
+
return
|
|
1005
1146
|
raise DshPluginMutationError(
|
|
1006
1147
|
"existing DSH profile has no pnpm lockfile, so package rollback is unavailable"
|
|
1007
1148
|
)
|
|
1008
1149
|
|
|
1009
|
-
def
|
|
1150
|
+
def _is_pristine_official_web_profile(self) -> bool:
|
|
1151
|
+
"""Recognize only the untouched profile generated by ``dsh --profile web``."""
|
|
1152
|
+
|
|
1153
|
+
if self._profile != "web" or (self._profile_root / "node_modules").exists():
|
|
1154
|
+
return False
|
|
1155
|
+
if (self._profile_root / _STATE_FILE).exists():
|
|
1156
|
+
return False
|
|
1157
|
+
manifest = self._read_manifest()
|
|
1158
|
+
return (
|
|
1159
|
+
self._dependencies(manifest) == {}
|
|
1160
|
+
and tuple(self._bundles(manifest)) == _WEB_PROFILE_BUILTINS
|
|
1161
|
+
and (self._profile_root / "pnpm-workspace.yaml").is_file()
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
def _rollback(
|
|
1165
|
+
self, snapshot: _ProfileSnapshot, original: BaseException, *, reinstall: bool = True,
|
|
1166
|
+
) -> None:
|
|
1010
1167
|
try:
|
|
1011
|
-
if all(content is None for content in snapshot.values()):
|
|
1168
|
+
if all(content is None for content in snapshot.files.values()):
|
|
1012
1169
|
profiles_root = (self._dsh_home / "profiles").resolve()
|
|
1013
1170
|
profile_root = self._profile_root.resolve()
|
|
1014
1171
|
if profile_root.parent != profiles_root:
|
|
@@ -1016,18 +1173,29 @@ class DshProfilePluginBridge:
|
|
|
1016
1173
|
if profile_root.exists():
|
|
1017
1174
|
shutil.rmtree(profile_root, ignore_errors=False)
|
|
1018
1175
|
return
|
|
1176
|
+
node_modules = self._profile_root / "node_modules"
|
|
1177
|
+
if not snapshot.node_modules_existed and node_modules.exists():
|
|
1178
|
+
profile_root = self._profile_root.resolve()
|
|
1179
|
+
if node_modules.is_symlink() or node_modules.resolve().parent != profile_root:
|
|
1180
|
+
raise DshPluginMutationError(
|
|
1181
|
+
"refusing to clean an untrusted DSH node_modules path"
|
|
1182
|
+
)
|
|
1183
|
+
shutil.rmtree(node_modules, ignore_errors=False)
|
|
1019
1184
|
self._profile_root.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
1020
|
-
for name, content in snapshot.items():
|
|
1185
|
+
for name, content in snapshot.files.items():
|
|
1021
1186
|
path = self._profile_root / name
|
|
1022
1187
|
if content is None:
|
|
1023
1188
|
path.unlink(missing_ok=True)
|
|
1024
1189
|
else:
|
|
1025
1190
|
path.write_bytes(content)
|
|
1026
1191
|
path.chmod(0o600)
|
|
1027
|
-
if
|
|
1192
|
+
if (
|
|
1193
|
+
reinstall and snapshot.files.get("pnpm-lock.yaml") is not None
|
|
1194
|
+
and self._manifest_path().is_file()
|
|
1195
|
+
):
|
|
1028
1196
|
self._plugin_command("install", "--frozen-lockfile")
|
|
1029
1197
|
for name in ("package.json", _STATE_FILE):
|
|
1030
|
-
content = snapshot.get(name)
|
|
1198
|
+
content = snapshot.files.get(name)
|
|
1031
1199
|
path = self._profile_root / name
|
|
1032
1200
|
if content is None:
|
|
1033
1201
|
path.unlink(missing_ok=True)
|
|
@@ -1053,7 +1221,18 @@ class DshProfilePluginBridge:
|
|
|
1053
1221
|
or value.startswith(("file:", "link:"))
|
|
1054
1222
|
or value.startswith(("./", "../", "file:./", "file:../", "link:./", "link:../"))
|
|
1055
1223
|
):
|
|
1056
|
-
raise ValueError(
|
|
1224
|
+
raise ValueError(
|
|
1225
|
+
"DSH plugin source must be an exact registry version or absolute local path"
|
|
1226
|
+
)
|
|
1227
|
+
candidate = Path(value).expanduser()
|
|
1228
|
+
if candidate.is_absolute():
|
|
1229
|
+
if not candidate.exists():
|
|
1230
|
+
raise ValueError("absolute local DSH plugin source does not exist")
|
|
1231
|
+
return
|
|
1232
|
+
# Bare names resolve latest to an exact version before package mutation.
|
|
1233
|
+
# Git, URL, explicit tags and ranges remain unsupported. Local sources
|
|
1234
|
+
# are packed and content-addressed by _prepare_source.
|
|
1235
|
+
validate_dsh_registry_request(value)
|
|
1057
1236
|
|
|
1058
1237
|
@staticmethod
|
|
1059
1238
|
def _validate_package_name(name: str) -> None:
|
|
@@ -1071,15 +1250,30 @@ class DshProfilePluginBridge:
|
|
|
1071
1250
|
environment: Mapping[str, str],
|
|
1072
1251
|
) -> _CommandResult:
|
|
1073
1252
|
try:
|
|
1074
|
-
|
|
1253
|
+
process = subprocess.Popen(
|
|
1075
1254
|
list(command),
|
|
1076
1255
|
cwd=cwd,
|
|
1077
1256
|
env=dict(environment),
|
|
1078
|
-
|
|
1079
|
-
|
|
1257
|
+
stdout=subprocess.PIPE,
|
|
1258
|
+
stderr=subprocess.PIPE,
|
|
1080
1259
|
text=True,
|
|
1081
|
-
|
|
1260
|
+
start_new_session=os.name == "posix",
|
|
1082
1261
|
)
|
|
1262
|
+
try:
|
|
1263
|
+
stdout, stderr = process.communicate(timeout=_COMMAND_TIMEOUT_SECONDS)
|
|
1264
|
+
except BaseException:
|
|
1265
|
+
# DSH synchronously waits on pnpm. Stop both before profile
|
|
1266
|
+
# rollback, including when a child still owns the output pipes.
|
|
1267
|
+
if os.name == "posix":
|
|
1268
|
+
try:
|
|
1269
|
+
os.killpg(process.pid, signal.SIGKILL)
|
|
1270
|
+
except ProcessLookupError:
|
|
1271
|
+
pass
|
|
1272
|
+
else: # pragma: no cover - supported production hosts are Unix
|
|
1273
|
+
process.kill()
|
|
1274
|
+
process.communicate()
|
|
1275
|
+
raise
|
|
1276
|
+
completed = subprocess.CompletedProcess(command, process.returncode, stdout, stderr)
|
|
1083
1277
|
except (OSError, subprocess.TimeoutExpired) as error:
|
|
1084
1278
|
raise DshHostUnavailableError("DSH host command did not complete") from error
|
|
1085
1279
|
if completed.returncode != 0:
|
|
@@ -1104,7 +1298,6 @@ def _redact_diagnostic(value: str) -> str:
|
|
|
1104
1298
|
__all__ = [
|
|
1105
1299
|
"DshBridgeError",
|
|
1106
1300
|
"DshBridgeHost",
|
|
1107
|
-
"DshClientBundle",
|
|
1108
1301
|
"DshHostUnavailableError",
|
|
1109
1302
|
"DshPluginApprovalRequired",
|
|
1110
1303
|
"DshPluginInventory",
|
|
@@ -1112,5 +1305,7 @@ __all__ = [
|
|
|
1112
1305
|
"DshPluginNotFoundError",
|
|
1113
1306
|
"DshProfilePluginBridge",
|
|
1114
1307
|
"DshProfileProjection",
|
|
1308
|
+
"DshProfileRecoveryError",
|
|
1115
1309
|
"dsh_subprocess_environment",
|
|
1310
|
+
"validate_dsh_registry_source",
|
|
1116
1311
|
]
|