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
ksadk/plugins/host.py
ADDED
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
"""Transactional, side-effect-owning PluginHost foundation (P2-03A).
|
|
2
|
+
|
|
3
|
+
The host has no knowledge of AgentControl, SessionEvent sequencing, or cloud
|
|
4
|
+
deployment. It only stages a fully resolved profile, atomically swaps it once
|
|
5
|
+
healthy, and disposes owned effects in reverse dependency order.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from collections.abc import Coroutine, Mapping
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import Any, Protocol, runtime_checkable
|
|
14
|
+
from uuid import uuid4
|
|
15
|
+
|
|
16
|
+
from ksadk.plugins.bundle import ResolvedPluginBundle
|
|
17
|
+
from ksadk.plugins.contracts import (
|
|
18
|
+
CompositionProfile,
|
|
19
|
+
PluginInventory,
|
|
20
|
+
PluginInventoryItem,
|
|
21
|
+
PluginLockEntry,
|
|
22
|
+
PluginManifest,
|
|
23
|
+
)
|
|
24
|
+
from ksadk.plugins.resolver import (
|
|
25
|
+
PluginRegistry,
|
|
26
|
+
PluginResolutionError,
|
|
27
|
+
ResolvedComposition,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PluginHostError(RuntimeError):
|
|
32
|
+
"""Stable reject/failure from PluginHost profile transactions."""
|
|
33
|
+
|
|
34
|
+
def __init__(self, code: str, message: str) -> None:
|
|
35
|
+
super().__init__(message)
|
|
36
|
+
self.code = code
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@runtime_checkable
|
|
40
|
+
class ManagedPlugin(Protocol):
|
|
41
|
+
"""Effects owned by one staged plugin instance."""
|
|
42
|
+
|
|
43
|
+
async def start(self) -> None: ...
|
|
44
|
+
|
|
45
|
+
async def health(self) -> bool: ...
|
|
46
|
+
|
|
47
|
+
async def drain(self) -> None: ...
|
|
48
|
+
|
|
49
|
+
async def dispose(self) -> None: ...
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@runtime_checkable
|
|
53
|
+
class PluginFactory(Protocol):
|
|
54
|
+
"""Factory seam; `stage` must not expose partially started effects."""
|
|
55
|
+
|
|
56
|
+
async def stage(
|
|
57
|
+
self,
|
|
58
|
+
manifest: PluginManifest,
|
|
59
|
+
*,
|
|
60
|
+
profile: CompositionProfile,
|
|
61
|
+
services: Mapping[str, Any],
|
|
62
|
+
) -> ManagedPlugin: ...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class PluginCapabilityBinding:
|
|
67
|
+
"""One locked capability and the active runtime that owns it."""
|
|
68
|
+
|
|
69
|
+
plugin_id: str
|
|
70
|
+
plugin_version: str
|
|
71
|
+
definition: str
|
|
72
|
+
slot: str
|
|
73
|
+
runtime: ManagedPlugin
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class PluginExecutionContext:
|
|
78
|
+
"""Read-only capability view passed to the active AgentProvider."""
|
|
79
|
+
|
|
80
|
+
profile_digest: str
|
|
81
|
+
plugin_lock_digest: str
|
|
82
|
+
bindings: tuple[PluginCapabilityBinding, ...]
|
|
83
|
+
# The host owns this key. Capability plugins may use it to bind ephemeral
|
|
84
|
+
# leases to the same provider activation without learning request payloads.
|
|
85
|
+
activation_key: str = ""
|
|
86
|
+
|
|
87
|
+
def all(
|
|
88
|
+
self,
|
|
89
|
+
definition: str,
|
|
90
|
+
*,
|
|
91
|
+
slot: str | None = None,
|
|
92
|
+
) -> tuple[PluginCapabilityBinding, ...]:
|
|
93
|
+
return tuple(
|
|
94
|
+
binding
|
|
95
|
+
for binding in self.bindings
|
|
96
|
+
if binding.definition == definition and (slot is None or binding.slot == slot)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
def require(
|
|
100
|
+
self,
|
|
101
|
+
definition: str,
|
|
102
|
+
*,
|
|
103
|
+
slot: str | None = None,
|
|
104
|
+
) -> PluginCapabilityBinding:
|
|
105
|
+
matches = self.all(definition, slot=slot)
|
|
106
|
+
if not matches:
|
|
107
|
+
suffix = f" in slot {slot!r}" if slot is not None else ""
|
|
108
|
+
raise PluginHostError(
|
|
109
|
+
"plugin_capability_unavailable",
|
|
110
|
+
f"active profile does not provide {definition!r}{suffix}",
|
|
111
|
+
)
|
|
112
|
+
if len(matches) != 1:
|
|
113
|
+
raise PluginHostError(
|
|
114
|
+
"plugin_capability_ambiguous",
|
|
115
|
+
f"active profile provides more than one {definition!r}; select a slot",
|
|
116
|
+
)
|
|
117
|
+
return matches[0]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@runtime_checkable
|
|
121
|
+
class PreparedAgent(ManagedPlugin, Protocol):
|
|
122
|
+
"""One provider-owned activation prepared from an immutable Bundle."""
|
|
123
|
+
|
|
124
|
+
async def execute(self, request: Any) -> Any: ...
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@runtime_checkable
|
|
128
|
+
class ExecutableAgentProvider(ManagedPlugin, Protocol):
|
|
129
|
+
"""AgentProvider execution seam used by the first PluginHost vertical.
|
|
130
|
+
|
|
131
|
+
``prepare`` must either return an unstarted activation or clean up all of
|
|
132
|
+
its own partial effects before raising. PluginHost owns start, health,
|
|
133
|
+
drain, and dispose for every returned activation.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
async def prepare(
|
|
137
|
+
self,
|
|
138
|
+
bundle: ResolvedPluginBundle,
|
|
139
|
+
*,
|
|
140
|
+
capabilities: PluginExecutionContext,
|
|
141
|
+
) -> PreparedAgent: ...
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True)
|
|
145
|
+
class _ActivePlugin:
|
|
146
|
+
entry: PluginLockEntry
|
|
147
|
+
runtime: ManagedPlugin
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass(frozen=True)
|
|
151
|
+
class _ActiveGraph:
|
|
152
|
+
resolved: ResolvedComposition
|
|
153
|
+
plugins: tuple[_ActivePlugin, ...]
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclass
|
|
157
|
+
class _ActiveActivation:
|
|
158
|
+
key: str
|
|
159
|
+
graph: _ActiveGraph
|
|
160
|
+
bundle_digest: str
|
|
161
|
+
runtime: PreparedAgent
|
|
162
|
+
operation_lock: asyncio.Lock
|
|
163
|
+
operation_task: asyncio.Task[Any] | None = None
|
|
164
|
+
closed: bool = False
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class PluginActivationSession:
|
|
168
|
+
"""Provider-owned activation retained across turns for one session.
|
|
169
|
+
|
|
170
|
+
The handle is deliberately small: PluginHost still owns lifecycle and
|
|
171
|
+
profile fencing, while the provider owns any native thread/checkpoint state
|
|
172
|
+
inside ``PreparedAgent``. Calls are serialized per activation because a
|
|
173
|
+
conversational session is an ordered command stream.
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
def __init__(self, host: "PluginHost", active: _ActiveActivation) -> None:
|
|
177
|
+
self._host = host
|
|
178
|
+
self._active = active
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def key(self) -> str:
|
|
182
|
+
return self._active.key
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def bundle_digest(self) -> str:
|
|
186
|
+
return self._active.bundle_digest
|
|
187
|
+
|
|
188
|
+
@property
|
|
189
|
+
def closed(self) -> bool:
|
|
190
|
+
return self._active.closed
|
|
191
|
+
|
|
192
|
+
async def execute(self, request: Any) -> Any:
|
|
193
|
+
return await self._host._execute_activation(self._active, request)
|
|
194
|
+
|
|
195
|
+
async def runtime_adapter(self) -> Any:
|
|
196
|
+
"""Return an optional provider-owned RuntimeAdapter for AgentKernel.
|
|
197
|
+
|
|
198
|
+
``execute`` remains the minimum cross-provider ABI. Providers that
|
|
199
|
+
need durable AgentControl/SessionEvent ownership (for example local
|
|
200
|
+
Scheduler Lite) may expose this additive seam. PluginHost retains the
|
|
201
|
+
activation/profile fence; unsupported providers fail explicitly.
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
return await self._host._runtime_adapter_activation(self._active)
|
|
205
|
+
|
|
206
|
+
async def close(self) -> None:
|
|
207
|
+
await self._host.close_activation(self._active.key, expected=self._active)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class PluginHost:
|
|
211
|
+
"""Apply resolved profiles without tearing down a healthy old graph first."""
|
|
212
|
+
|
|
213
|
+
def __init__(
|
|
214
|
+
self,
|
|
215
|
+
registry: PluginRegistry,
|
|
216
|
+
factories: Mapping[str, PluginFactory],
|
|
217
|
+
*,
|
|
218
|
+
allowed_permissions: frozenset[str] = frozenset(),
|
|
219
|
+
services: Mapping[str, Any] | None = None,
|
|
220
|
+
) -> None:
|
|
221
|
+
self._registry = registry
|
|
222
|
+
self._factories = dict(factories)
|
|
223
|
+
self._allowed_permissions = frozenset(allowed_permissions)
|
|
224
|
+
self._services = dict(services or {})
|
|
225
|
+
self._transaction_lock = asyncio.Lock()
|
|
226
|
+
self._active: _ActiveGraph | None = None
|
|
227
|
+
# A profile switch moves default admission atomically, while already
|
|
228
|
+
# prepared conversations may hold provider-native thread/checkpoint
|
|
229
|
+
# state. Retired graphs are reclaimed only after their last session
|
|
230
|
+
# activation closes.
|
|
231
|
+
self._retired: list[_ActiveGraph] = []
|
|
232
|
+
self._activations: dict[str, _ActiveActivation] = {}
|
|
233
|
+
self._last_failure: PluginHostError | None = None
|
|
234
|
+
|
|
235
|
+
async def apply(self, profile: CompositionProfile) -> PluginInventory:
|
|
236
|
+
"""Resolve, admit, stage, health-check, then atomically switch profile.
|
|
237
|
+
|
|
238
|
+
Any resolve/admission/stage/health error leaves the current graph
|
|
239
|
+
untouched. Staged effects from the failed candidate are drained and
|
|
240
|
+
disposed before the error is returned.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
async with self._transaction_lock:
|
|
244
|
+
resolved = self.preflight(profile)
|
|
245
|
+
if self._active and (
|
|
246
|
+
self._active.resolved.profile_digest == resolved.profile_digest
|
|
247
|
+
and self._active.resolved.plugin_lock_digest == resolved.plugin_lock_digest
|
|
248
|
+
):
|
|
249
|
+
return self._inventory_for(self._active)
|
|
250
|
+
|
|
251
|
+
ordered_entries = _dependency_order(resolved.plugin_lock.plugins)
|
|
252
|
+
staged: list[_ActivePlugin] = []
|
|
253
|
+
try:
|
|
254
|
+
for entry in ordered_entries:
|
|
255
|
+
manifest = self._registry.manifest_for(entry.id, entry.version)
|
|
256
|
+
factory = self._factories[entry.id]
|
|
257
|
+
runtime = await factory.stage(
|
|
258
|
+
manifest,
|
|
259
|
+
profile=resolved.profile,
|
|
260
|
+
services=self._services,
|
|
261
|
+
)
|
|
262
|
+
staged.append(_ActivePlugin(entry=entry, runtime=runtime))
|
|
263
|
+
for plugin in staged:
|
|
264
|
+
await plugin.runtime.start()
|
|
265
|
+
if not await plugin.runtime.health():
|
|
266
|
+
raise PluginHostError(
|
|
267
|
+
"plugin_health_failed",
|
|
268
|
+
f"plugin {plugin.entry.id}@{plugin.entry.version} failed health check",
|
|
269
|
+
)
|
|
270
|
+
except asyncio.CancelledError:
|
|
271
|
+
await self._finish_cleanup(self._dispose_staged(staged))
|
|
272
|
+
raise
|
|
273
|
+
except PluginHostError as error:
|
|
274
|
+
await self._finish_cleanup(self._dispose_staged(staged))
|
|
275
|
+
self._last_failure = error
|
|
276
|
+
raise
|
|
277
|
+
except Exception as error: # noqa: BLE001 - boundary adapts plugins
|
|
278
|
+
await self._finish_cleanup(self._dispose_staged(staged))
|
|
279
|
+
failure = PluginHostError("plugin_stage_failed", str(error))
|
|
280
|
+
self._last_failure = failure
|
|
281
|
+
raise failure from error
|
|
282
|
+
|
|
283
|
+
candidate = _ActiveGraph(resolved=resolved, plugins=tuple(staged))
|
|
284
|
+
previous = self._active
|
|
285
|
+
# This single assignment is the profile switch. It only happens
|
|
286
|
+
# after every staged effect has passed health, preserving the old
|
|
287
|
+
# graph on all earlier failures.
|
|
288
|
+
self._active = candidate
|
|
289
|
+
self._last_failure = None
|
|
290
|
+
if previous is not None:
|
|
291
|
+
self._retired.append(previous)
|
|
292
|
+
await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
|
|
293
|
+
return self._inventory_for(candidate)
|
|
294
|
+
|
|
295
|
+
def preflight(self, profile: CompositionProfile) -> ResolvedComposition:
|
|
296
|
+
"""Resolve and admit a profile without importing or starting a plugin."""
|
|
297
|
+
|
|
298
|
+
try:
|
|
299
|
+
resolved = self._registry.resolve(profile)
|
|
300
|
+
except PluginResolutionError as error:
|
|
301
|
+
failure = PluginHostError(error.code, str(error))
|
|
302
|
+
self._last_failure = failure
|
|
303
|
+
raise failure from error
|
|
304
|
+
entries = _dependency_order(resolved.plugin_lock.plugins)
|
|
305
|
+
self._admit(entries)
|
|
306
|
+
for entry in entries:
|
|
307
|
+
if entry.id not in self._factories:
|
|
308
|
+
failure = PluginHostError(
|
|
309
|
+
"plugin_factory_unavailable",
|
|
310
|
+
f"no factory is registered for {entry.id}@{entry.version}",
|
|
311
|
+
)
|
|
312
|
+
self._last_failure = failure
|
|
313
|
+
raise failure
|
|
314
|
+
return resolved
|
|
315
|
+
|
|
316
|
+
def inventory(self) -> PluginInventory | None:
|
|
317
|
+
"""Return only the currently active profile inventory, if any."""
|
|
318
|
+
|
|
319
|
+
if self._active is None:
|
|
320
|
+
return None
|
|
321
|
+
return self._inventory_for(self._active)
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def activation_count(self) -> int:
|
|
325
|
+
"""Number of live provider-owned activations (diagnostic only)."""
|
|
326
|
+
|
|
327
|
+
return sum(not active.closed for active in self._activations.values())
|
|
328
|
+
|
|
329
|
+
async def execute(self, bundle: ResolvedPluginBundle, request: Any) -> Any:
|
|
330
|
+
"""Execute one disposable activation (compatibility convenience API)."""
|
|
331
|
+
|
|
332
|
+
session = await self.open_activation(
|
|
333
|
+
bundle,
|
|
334
|
+
activation_key=f"one-shot:{uuid4().hex}",
|
|
335
|
+
)
|
|
336
|
+
try:
|
|
337
|
+
return await session.execute(request)
|
|
338
|
+
finally:
|
|
339
|
+
await session.close()
|
|
340
|
+
|
|
341
|
+
async def open_activation(
|
|
342
|
+
self,
|
|
343
|
+
bundle: ResolvedPluginBundle,
|
|
344
|
+
*,
|
|
345
|
+
activation_key: str,
|
|
346
|
+
) -> PluginActivationSession:
|
|
347
|
+
"""Open or reuse one profile-fenced, provider-owned activation.
|
|
348
|
+
|
|
349
|
+
Reuse is permitted for the exact graph and immutable Bundle digest. A
|
|
350
|
+
profile switch retires its old graph for new sessions, but an existing
|
|
351
|
+
session key remains pinned to that graph until it closes.
|
|
352
|
+
"""
|
|
353
|
+
|
|
354
|
+
key = str(activation_key).strip()
|
|
355
|
+
if not key or len(key) > 512:
|
|
356
|
+
raise PluginHostError(
|
|
357
|
+
"agent_activation_key_invalid",
|
|
358
|
+
"activation_key must be a non-empty value of at most 512 characters",
|
|
359
|
+
)
|
|
360
|
+
async with self._transaction_lock:
|
|
361
|
+
existing = self._activations.get(key)
|
|
362
|
+
if existing is not None:
|
|
363
|
+
if (
|
|
364
|
+
not existing.closed
|
|
365
|
+
and existing.bundle_digest == bundle.bundle_digest
|
|
366
|
+
and self._bundle_matches_graph(bundle, existing.graph)
|
|
367
|
+
):
|
|
368
|
+
# This activation may belong to a retired graph: it was
|
|
369
|
+
# pinned before a newer profile became active.
|
|
370
|
+
return PluginActivationSession(self, existing)
|
|
371
|
+
await self._close_activation_record(existing)
|
|
372
|
+
if self._activations.get(key) is existing:
|
|
373
|
+
self._activations.pop(key, None)
|
|
374
|
+
await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
|
|
375
|
+
|
|
376
|
+
graph = self._require_bundle_graph(bundle)
|
|
377
|
+
runtime = await self._prepare_activation(
|
|
378
|
+
graph,
|
|
379
|
+
bundle,
|
|
380
|
+
activation_key=key,
|
|
381
|
+
)
|
|
382
|
+
active = _ActiveActivation(
|
|
383
|
+
key=key,
|
|
384
|
+
graph=graph,
|
|
385
|
+
bundle_digest=bundle.bundle_digest,
|
|
386
|
+
runtime=runtime,
|
|
387
|
+
operation_lock=asyncio.Lock(),
|
|
388
|
+
)
|
|
389
|
+
self._activations[key] = active
|
|
390
|
+
return PluginActivationSession(self, active)
|
|
391
|
+
|
|
392
|
+
async def close_activation(
|
|
393
|
+
self,
|
|
394
|
+
activation_key: str,
|
|
395
|
+
*,
|
|
396
|
+
expected: _ActiveActivation | None = None,
|
|
397
|
+
) -> None:
|
|
398
|
+
"""Drain and dispose a retained activation if it is still current."""
|
|
399
|
+
|
|
400
|
+
async with self._transaction_lock:
|
|
401
|
+
active = self._activations.get(activation_key)
|
|
402
|
+
if active is None or (expected is not None and active is not expected):
|
|
403
|
+
return
|
|
404
|
+
await self._close_activation_record(active)
|
|
405
|
+
if self._activations.get(activation_key) is active:
|
|
406
|
+
self._activations.pop(activation_key, None)
|
|
407
|
+
await self._finish_cleanup(self._dispose_unpinned_retired_graphs())
|
|
408
|
+
|
|
409
|
+
@property
|
|
410
|
+
def last_failure(self) -> PluginHostError | None:
|
|
411
|
+
return self._last_failure
|
|
412
|
+
|
|
413
|
+
async def dispose(self) -> None:
|
|
414
|
+
"""Drain and dispose active plus retired graphs; there is no implicit restart."""
|
|
415
|
+
|
|
416
|
+
async with self._transaction_lock:
|
|
417
|
+
graphs = [graph for graph in [self._active, *self._retired] if graph is not None]
|
|
418
|
+
self._active = None
|
|
419
|
+
self._retired = []
|
|
420
|
+
if graphs:
|
|
421
|
+
await self._finish_cleanup(self._dispose_all_graphs(graphs))
|
|
422
|
+
|
|
423
|
+
@staticmethod
|
|
424
|
+
async def _finish_cleanup(cleanup: Coroutine[Any, Any, None]) -> None:
|
|
425
|
+
"""Defer caller cancellation until an owned-effect cleanup finishes."""
|
|
426
|
+
|
|
427
|
+
cleanup_task = asyncio.create_task(cleanup)
|
|
428
|
+
interrupted = False
|
|
429
|
+
while not cleanup_task.done():
|
|
430
|
+
try:
|
|
431
|
+
await asyncio.shield(cleanup_task)
|
|
432
|
+
except asyncio.CancelledError:
|
|
433
|
+
interrupted = True
|
|
434
|
+
cleanup_task.result()
|
|
435
|
+
if interrupted:
|
|
436
|
+
raise asyncio.CancelledError
|
|
437
|
+
|
|
438
|
+
async def _dispose_graph(self, graph: _ActiveGraph) -> None:
|
|
439
|
+
await self._close_graph_activations(graph)
|
|
440
|
+
await self._dispose_staged(list(graph.plugins))
|
|
441
|
+
|
|
442
|
+
async def _dispose_all_graphs(self, graphs: list[_ActiveGraph]) -> None:
|
|
443
|
+
await self._close_all_activations()
|
|
444
|
+
for graph in graphs:
|
|
445
|
+
await self._dispose_staged(list(graph.plugins))
|
|
446
|
+
|
|
447
|
+
async def _dispose_unpinned_retired_graphs(self) -> None:
|
|
448
|
+
for graph in tuple(self._retired):
|
|
449
|
+
if any(
|
|
450
|
+
not activation.closed and activation.graph is graph
|
|
451
|
+
for activation in self._activations.values()
|
|
452
|
+
):
|
|
453
|
+
continue
|
|
454
|
+
await self._dispose_staged(list(graph.plugins))
|
|
455
|
+
self._retired.remove(graph)
|
|
456
|
+
|
|
457
|
+
def _admit(self, entries: list[PluginLockEntry]) -> None:
|
|
458
|
+
for entry in entries:
|
|
459
|
+
manifest = self._registry.manifest_for(entry.id, entry.version)
|
|
460
|
+
missing = sorted(set(manifest.spec.permissions) - self._allowed_permissions)
|
|
461
|
+
if missing:
|
|
462
|
+
raise PluginHostError(
|
|
463
|
+
"plugin_permission_denied",
|
|
464
|
+
f"plugin {entry.id}@{entry.version} requests unapproved permissions: "
|
|
465
|
+
+ ", ".join(missing),
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
@staticmethod
|
|
469
|
+
async def _dispose_staged(staged: list[_ActivePlugin]) -> None:
|
|
470
|
+
"""Best-effort cleanup preserves the primary failure while draining all effects."""
|
|
471
|
+
|
|
472
|
+
for plugin in reversed(staged):
|
|
473
|
+
try:
|
|
474
|
+
await plugin.runtime.drain()
|
|
475
|
+
except Exception: # noqa: BLE001 - disposal must continue
|
|
476
|
+
pass
|
|
477
|
+
try:
|
|
478
|
+
await plugin.runtime.dispose()
|
|
479
|
+
except Exception: # noqa: BLE001 - disposal must continue
|
|
480
|
+
pass
|
|
481
|
+
|
|
482
|
+
@staticmethod
|
|
483
|
+
async def _dispose_activation(activation: PreparedAgent) -> None:
|
|
484
|
+
"""Best-effort cleanup for a prepared one-shot activation."""
|
|
485
|
+
|
|
486
|
+
try:
|
|
487
|
+
await activation.drain()
|
|
488
|
+
except Exception: # noqa: BLE001 - disposal must continue
|
|
489
|
+
pass
|
|
490
|
+
try:
|
|
491
|
+
await activation.dispose()
|
|
492
|
+
except Exception: # noqa: BLE001 - disposal must continue
|
|
493
|
+
pass
|
|
494
|
+
|
|
495
|
+
def _require_bundle_graph(self, bundle: ResolvedPluginBundle) -> _ActiveGraph:
|
|
496
|
+
graph = self._active
|
|
497
|
+
if graph is None:
|
|
498
|
+
raise PluginHostError("plugin_profile_inactive", "no plugin profile is active")
|
|
499
|
+
if not self._bundle_matches_graph(bundle, graph):
|
|
500
|
+
raise PluginHostError(
|
|
501
|
+
"plugin_bundle_profile_mismatch",
|
|
502
|
+
"Bundle composition does not match the active plugin graph",
|
|
503
|
+
)
|
|
504
|
+
return graph
|
|
505
|
+
|
|
506
|
+
@staticmethod
|
|
507
|
+
def _bundle_matches_graph(bundle: ResolvedPluginBundle, graph: _ActiveGraph) -> bool:
|
|
508
|
+
return (
|
|
509
|
+
bundle.composition.profile_digest == graph.resolved.profile_digest
|
|
510
|
+
and bundle.composition.plugin_lock_digest == graph.resolved.plugin_lock_digest
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
async def _prepare_activation(
|
|
514
|
+
self,
|
|
515
|
+
graph: _ActiveGraph,
|
|
516
|
+
bundle: ResolvedPluginBundle,
|
|
517
|
+
*,
|
|
518
|
+
activation_key: str,
|
|
519
|
+
) -> PreparedAgent:
|
|
520
|
+
capabilities = self._execution_context(graph, activation_key=activation_key)
|
|
521
|
+
provider_binding = capabilities.require("agent.provider/v1", slot="agent.execution")
|
|
522
|
+
provider = provider_binding.runtime
|
|
523
|
+
if not isinstance(provider, ExecutableAgentProvider):
|
|
524
|
+
raise PluginHostError(
|
|
525
|
+
"agent_provider_not_executable",
|
|
526
|
+
f"plugin {provider_binding.plugin_id}@"
|
|
527
|
+
f"{provider_binding.plugin_version} does not implement prepare",
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
activation: PreparedAgent | None = None
|
|
531
|
+
try:
|
|
532
|
+
try:
|
|
533
|
+
activation = await provider.prepare(bundle, capabilities=capabilities)
|
|
534
|
+
except PluginHostError:
|
|
535
|
+
raise
|
|
536
|
+
except Exception as error: # noqa: BLE001 - provider boundary
|
|
537
|
+
raise PluginHostError("agent_prepare_failed", str(error)) from error
|
|
538
|
+
if not isinstance(activation, PreparedAgent):
|
|
539
|
+
raise PluginHostError(
|
|
540
|
+
"agent_activation_invalid",
|
|
541
|
+
"AgentProvider.prepare returned an invalid activation",
|
|
542
|
+
)
|
|
543
|
+
try:
|
|
544
|
+
await activation.start()
|
|
545
|
+
except Exception as error: # noqa: BLE001 - activation boundary
|
|
546
|
+
raise PluginHostError("agent_activation_start_failed", str(error)) from error
|
|
547
|
+
try:
|
|
548
|
+
healthy = await activation.health()
|
|
549
|
+
except Exception as error: # noqa: BLE001 - activation boundary
|
|
550
|
+
raise PluginHostError("agent_activation_health_failed", str(error)) from error
|
|
551
|
+
if not healthy:
|
|
552
|
+
raise PluginHostError(
|
|
553
|
+
"agent_activation_health_failed",
|
|
554
|
+
"prepared Agent activation failed health check",
|
|
555
|
+
)
|
|
556
|
+
return activation
|
|
557
|
+
except asyncio.CancelledError:
|
|
558
|
+
if activation is not None:
|
|
559
|
+
await self._dispose_activation(activation)
|
|
560
|
+
raise
|
|
561
|
+
except PluginHostError as error:
|
|
562
|
+
self._last_failure = error
|
|
563
|
+
if activation is not None:
|
|
564
|
+
await self._dispose_activation(activation)
|
|
565
|
+
raise
|
|
566
|
+
|
|
567
|
+
async def _execute_activation(
|
|
568
|
+
self,
|
|
569
|
+
active: _ActiveActivation,
|
|
570
|
+
request: Any,
|
|
571
|
+
) -> Any:
|
|
572
|
+
async with active.operation_lock:
|
|
573
|
+
task = asyncio.current_task()
|
|
574
|
+
active.operation_task = task
|
|
575
|
+
try:
|
|
576
|
+
if active.closed:
|
|
577
|
+
raise PluginHostError(
|
|
578
|
+
"agent_activation_closed",
|
|
579
|
+
f"Agent activation {active.key!r} is closed",
|
|
580
|
+
)
|
|
581
|
+
result = await active.runtime.execute(request)
|
|
582
|
+
except asyncio.CancelledError:
|
|
583
|
+
if not active.closed:
|
|
584
|
+
await self._dispose_activation(active.runtime)
|
|
585
|
+
active.closed = True
|
|
586
|
+
raise
|
|
587
|
+
except PluginHostError as error:
|
|
588
|
+
self._last_failure = error
|
|
589
|
+
await self._dispose_activation(active.runtime)
|
|
590
|
+
active.closed = True
|
|
591
|
+
raise
|
|
592
|
+
except Exception as error: # noqa: BLE001 - provider boundary
|
|
593
|
+
failure = PluginHostError("agent_execution_failed", str(error))
|
|
594
|
+
self._last_failure = failure
|
|
595
|
+
await self._dispose_activation(active.runtime)
|
|
596
|
+
active.closed = True
|
|
597
|
+
raise failure from error
|
|
598
|
+
finally:
|
|
599
|
+
if active.operation_task is task:
|
|
600
|
+
active.operation_task = None
|
|
601
|
+
self._last_failure = None
|
|
602
|
+
return result
|
|
603
|
+
|
|
604
|
+
async def _runtime_adapter_activation(self, active: _ActiveActivation) -> Any:
|
|
605
|
+
async with active.operation_lock:
|
|
606
|
+
if active.closed:
|
|
607
|
+
raise PluginHostError(
|
|
608
|
+
"agent_activation_closed",
|
|
609
|
+
f"Agent activation {active.key!r} is closed",
|
|
610
|
+
)
|
|
611
|
+
provide = getattr(active.runtime, "runtime_adapter", None)
|
|
612
|
+
if not callable(provide):
|
|
613
|
+
raise PluginHostError(
|
|
614
|
+
"agent_provider_runtime_adapter_unavailable",
|
|
615
|
+
"AgentProvider does not expose a Kernel RuntimeAdapter",
|
|
616
|
+
)
|
|
617
|
+
try:
|
|
618
|
+
adapter = provide()
|
|
619
|
+
if asyncio.iscoroutine(adapter):
|
|
620
|
+
adapter = await adapter
|
|
621
|
+
except PluginHostError:
|
|
622
|
+
raise
|
|
623
|
+
except Exception as error: # noqa: BLE001 - provider boundary
|
|
624
|
+
raise PluginHostError(
|
|
625
|
+
"agent_provider_runtime_adapter_failed", str(error)
|
|
626
|
+
) from error
|
|
627
|
+
return adapter
|
|
628
|
+
|
|
629
|
+
async def _close_activation_record(self, active: _ActiveActivation) -> None:
|
|
630
|
+
await self._finish_cleanup(self._close_activation_record_owned(active))
|
|
631
|
+
|
|
632
|
+
async def _close_activation_record_owned(self, active: _ActiveActivation) -> None:
|
|
633
|
+
"""Finish the entire terminal close before propagating caller cancellation."""
|
|
634
|
+
|
|
635
|
+
if active.closed and active.operation_task is None:
|
|
636
|
+
return
|
|
637
|
+
active.closed = True
|
|
638
|
+
operation = active.operation_task
|
|
639
|
+
await self._abort_activation(active.runtime)
|
|
640
|
+
if operation is not None and operation is not asyncio.current_task():
|
|
641
|
+
operation.cancel()
|
|
642
|
+
try:
|
|
643
|
+
await asyncio.wait_for(active.operation_lock.acquire(), timeout=2.0)
|
|
644
|
+
except TimeoutError:
|
|
645
|
+
await self._bounded_dispose_activation(active.runtime)
|
|
646
|
+
return
|
|
647
|
+
try:
|
|
648
|
+
await self._bounded_dispose_activation(active.runtime)
|
|
649
|
+
finally:
|
|
650
|
+
active.operation_lock.release()
|
|
651
|
+
|
|
652
|
+
@staticmethod
|
|
653
|
+
async def _abort_activation(activation: PreparedAgent) -> None:
|
|
654
|
+
"""Finish provider revocation before a close can report success.
|
|
655
|
+
|
|
656
|
+
``abort`` is currently implemented only by the Harness activation and
|
|
657
|
+
revokes activation-scoped MCP credentials. A host-side timeout would
|
|
658
|
+
let close return while those credentials still authorize requests.
|
|
659
|
+
The underlying DSH lifecycle operation owns its network timeout and
|
|
660
|
+
kills the whole generation when revocation cannot be proven.
|
|
661
|
+
"""
|
|
662
|
+
|
|
663
|
+
abort = getattr(activation, "abort", None)
|
|
664
|
+
if not callable(abort):
|
|
665
|
+
return
|
|
666
|
+
try:
|
|
667
|
+
result = abort()
|
|
668
|
+
if asyncio.iscoroutine(result):
|
|
669
|
+
await result
|
|
670
|
+
except BaseException: # abort is best-effort; disposal still follows
|
|
671
|
+
pass
|
|
672
|
+
|
|
673
|
+
@classmethod
|
|
674
|
+
async def _bounded_dispose_activation(cls, activation: PreparedAgent) -> None:
|
|
675
|
+
try:
|
|
676
|
+
await asyncio.wait_for(cls._dispose_activation(activation), timeout=2.0)
|
|
677
|
+
except BaseException: # terminal close cannot wait forever on provider code
|
|
678
|
+
pass
|
|
679
|
+
|
|
680
|
+
async def _close_graph_activations(self, graph: _ActiveGraph) -> None:
|
|
681
|
+
selected = [
|
|
682
|
+
(key, active)
|
|
683
|
+
for key, active in tuple(self._activations.items())
|
|
684
|
+
if active.graph is graph
|
|
685
|
+
]
|
|
686
|
+
if selected:
|
|
687
|
+
await asyncio.gather(
|
|
688
|
+
*(self._close_activation_record(active) for _key, active in selected)
|
|
689
|
+
)
|
|
690
|
+
for key, active in selected:
|
|
691
|
+
if self._activations.get(key) is active:
|
|
692
|
+
self._activations.pop(key, None)
|
|
693
|
+
|
|
694
|
+
async def _close_all_activations(self) -> None:
|
|
695
|
+
selected = tuple(self._activations.items())
|
|
696
|
+
if selected:
|
|
697
|
+
await asyncio.gather(
|
|
698
|
+
*(self._close_activation_record(active) for _key, active in selected)
|
|
699
|
+
)
|
|
700
|
+
for key, active in selected:
|
|
701
|
+
if self._activations.get(key) is active:
|
|
702
|
+
self._activations.pop(key, None)
|
|
703
|
+
|
|
704
|
+
@staticmethod
|
|
705
|
+
def _execution_context(
|
|
706
|
+
graph: _ActiveGraph,
|
|
707
|
+
*,
|
|
708
|
+
activation_key: str = "",
|
|
709
|
+
) -> PluginExecutionContext:
|
|
710
|
+
bindings = tuple(
|
|
711
|
+
PluginCapabilityBinding(
|
|
712
|
+
plugin_id=plugin.entry.id,
|
|
713
|
+
plugin_version=plugin.entry.version,
|
|
714
|
+
definition=capability.definition,
|
|
715
|
+
slot=capability.slot,
|
|
716
|
+
runtime=plugin.runtime,
|
|
717
|
+
)
|
|
718
|
+
for plugin in graph.plugins
|
|
719
|
+
for capability in plugin.entry.provides
|
|
720
|
+
)
|
|
721
|
+
return PluginExecutionContext(
|
|
722
|
+
profile_digest=graph.resolved.profile_digest,
|
|
723
|
+
plugin_lock_digest=graph.resolved.plugin_lock_digest,
|
|
724
|
+
bindings=bindings,
|
|
725
|
+
activation_key=activation_key,
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
@staticmethod
|
|
729
|
+
def _inventory_for(graph: _ActiveGraph) -> PluginInventory:
|
|
730
|
+
return PluginInventory(
|
|
731
|
+
profile_digest=graph.resolved.profile_digest,
|
|
732
|
+
plugin_lock_digest=graph.resolved.plugin_lock_digest,
|
|
733
|
+
plugins=[
|
|
734
|
+
PluginInventoryItem(
|
|
735
|
+
id=plugin.entry.id,
|
|
736
|
+
version=plugin.entry.version,
|
|
737
|
+
digest=plugin.entry.digest,
|
|
738
|
+
state="ready",
|
|
739
|
+
health="healthy",
|
|
740
|
+
)
|
|
741
|
+
for plugin in graph.plugins
|
|
742
|
+
],
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
def _dependency_order(entries: list[PluginLockEntry]) -> list[PluginLockEntry]:
|
|
747
|
+
"""Dependency-first deterministic topological order from the locked graph."""
|
|
748
|
+
|
|
749
|
+
by_id = {entry.id: entry for entry in entries}
|
|
750
|
+
visiting: set[str] = set()
|
|
751
|
+
visited: set[str] = set()
|
|
752
|
+
ordered: list[PluginLockEntry] = []
|
|
753
|
+
|
|
754
|
+
def visit(plugin_id: str) -> None:
|
|
755
|
+
if plugin_id in visiting:
|
|
756
|
+
raise PluginHostError("plugin_dependency_cycle", "plugin lock dependency cycle")
|
|
757
|
+
if plugin_id in visited:
|
|
758
|
+
return
|
|
759
|
+
entry = by_id.get(plugin_id)
|
|
760
|
+
if entry is None:
|
|
761
|
+
raise PluginHostError(
|
|
762
|
+
"plugin_dependency_unresolved",
|
|
763
|
+
f"plugin dependency {plugin_id!r} is missing from the lock",
|
|
764
|
+
)
|
|
765
|
+
visiting.add(plugin_id)
|
|
766
|
+
for dependency in sorted(entry.dependencies, key=lambda item: item.id):
|
|
767
|
+
visit(dependency.id)
|
|
768
|
+
visiting.remove(plugin_id)
|
|
769
|
+
visited.add(plugin_id)
|
|
770
|
+
ordered.append(entry)
|
|
771
|
+
|
|
772
|
+
for entry in sorted(entries, key=lambda item: item.id):
|
|
773
|
+
visit(entry.id)
|
|
774
|
+
return ordered
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
__all__ = [
|
|
778
|
+
"ExecutableAgentProvider",
|
|
779
|
+
"ManagedPlugin",
|
|
780
|
+
"PluginCapabilityBinding",
|
|
781
|
+
"PluginActivationSession",
|
|
782
|
+
"PluginExecutionContext",
|
|
783
|
+
"PluginFactory",
|
|
784
|
+
"PluginHost",
|
|
785
|
+
"PluginHostError",
|
|
786
|
+
"PreparedAgent",
|
|
787
|
+
]
|