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/studio/service.py
CHANGED
|
@@ -4,15 +4,20 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import hashlib
|
|
7
|
+
import json
|
|
7
8
|
import logging
|
|
8
9
|
import os
|
|
10
|
+
import zipfile
|
|
11
|
+
from collections.abc import AsyncIterator, Awaitable, Mapping, Sequence
|
|
12
|
+
from contextlib import asynccontextmanager
|
|
9
13
|
from dataclasses import dataclass
|
|
10
14
|
from pathlib import Path
|
|
11
|
-
from typing import Any, Callable, Literal, cast
|
|
15
|
+
from typing import Any, Callable, Literal, TypeVar, cast
|
|
12
16
|
from urllib.parse import urlparse
|
|
13
17
|
from uuid import uuid4
|
|
14
18
|
|
|
15
19
|
from ksadk.api import AgentEngineClient
|
|
20
|
+
from ksadk.conversations.contracts import ConversationCapability, ConversationSurface
|
|
16
21
|
from ksadk.evaluation import (
|
|
17
22
|
EvaluationConfig as PublicEvaluationConfig,
|
|
18
23
|
)
|
|
@@ -39,10 +44,23 @@ from ksadk.evaluation.studio_build_adapter import (
|
|
|
39
44
|
from ksadk.events.store import RuntimeEventStore
|
|
40
45
|
from ksadk.observability.session_log import SessionLogError, export_session_log
|
|
41
46
|
from ksadk.observability.trajectory import encode_sse, project_trajectory_event
|
|
47
|
+
from ksadk.plugins.bundle_security import BundleSecurityError
|
|
48
|
+
from ksadk.plugins.contracts import PluginManifest
|
|
49
|
+
from ksadk.plugins.providers.legacy import LegacyHarnessSource
|
|
50
|
+
from ksadk.plugins.providers.legacy_catalog import (
|
|
51
|
+
KSADK_HARNESS_AGENT_PROVIDER_PLUGIN_ID,
|
|
52
|
+
)
|
|
42
53
|
from ksadk.runtime import RuntimeExecutor, build_default_runtime_registry
|
|
54
|
+
from ksadk.scheduler.contracts import (
|
|
55
|
+
ScheduleCommandTemplate,
|
|
56
|
+
ScheduledTask,
|
|
57
|
+
ScheduledTaskTarget,
|
|
58
|
+
ScheduleSpec,
|
|
59
|
+
)
|
|
43
60
|
from ksadk.sessions.local_service import LocalSessionService
|
|
44
61
|
from ksadk.studio.agent_avatar_assets import AgentAvatarAssetStore
|
|
45
62
|
from ksadk.studio.agent_lifecycle import delete_framework_agent
|
|
63
|
+
from ksadk.studio.attachment_store import ConversationAttachmentStore
|
|
46
64
|
from ksadk.studio.authoring_coordinator import StudioAuthoringCoordinator
|
|
47
65
|
from ksadk.studio.builder import AgentBundleBuilder
|
|
48
66
|
from ksadk.studio.capabilities import builtin_tool_contracts
|
|
@@ -66,6 +84,8 @@ from ksadk.studio.codex_manifest import (
|
|
|
66
84
|
CodexAgentManifest,
|
|
67
85
|
CodexManifestRepository,
|
|
68
86
|
)
|
|
87
|
+
from ksadk.studio.codex_plugin_store import CodexPluginSnapshotStore
|
|
88
|
+
from ksadk.studio.codex_provider_build import CodexProviderBuildManager
|
|
69
89
|
from ksadk.studio.codex_run import CodexRunSpecResolver
|
|
70
90
|
from ksadk.studio.compiler import AgentCompiler
|
|
71
91
|
from ksadk.studio.contracts import (
|
|
@@ -76,7 +96,10 @@ from ksadk.studio.contracts import (
|
|
|
76
96
|
AgentTemplateComposeRequest,
|
|
77
97
|
AgentTemplateComposition,
|
|
78
98
|
BuildStatus,
|
|
99
|
+
BundleManifest,
|
|
79
100
|
DeploymentRequest,
|
|
101
|
+
Diagnostic,
|
|
102
|
+
DiagnosticSeverity,
|
|
80
103
|
Operation,
|
|
81
104
|
OperationKind,
|
|
82
105
|
RunEvent,
|
|
@@ -84,6 +107,13 @@ from ksadk.studio.contracts import (
|
|
|
84
107
|
RuntimeRef,
|
|
85
108
|
ToolContract,
|
|
86
109
|
)
|
|
110
|
+
from ksadk.studio.dsh_capability_service import (
|
|
111
|
+
StudioDshCapabilityService,
|
|
112
|
+
)
|
|
113
|
+
from ksadk.studio.dsh_provider_registration import (
|
|
114
|
+
StudioDshProviderRegistrationError,
|
|
115
|
+
StudioDshProviderRegistrationManager,
|
|
116
|
+
)
|
|
87
117
|
from ksadk.studio.errors import StudioError
|
|
88
118
|
from ksadk.studio.event_store import RunEventStore
|
|
89
119
|
from ksadk.studio.framework_run import FrameworkRunSpecResolver
|
|
@@ -91,11 +121,29 @@ from ksadk.studio.mcp_runtime import MCPRuntimeAdapter
|
|
|
91
121
|
from ksadk.studio.model_client import CredentialResolver, OpenAICompatibleModelClient
|
|
92
122
|
from ksadk.studio.model_profile_service import test_model_profile_connection
|
|
93
123
|
from ksadk.studio.operations import OperationManager
|
|
124
|
+
from ksadk.studio.plugin_composition import StudioPluginCompositionCompiler
|
|
125
|
+
from ksadk.studio.plugin_runtime import StudioPluginRuntime
|
|
94
126
|
from ksadk.studio.repository import AgentDraftRepository, BuildRepository, load_yaml_file
|
|
127
|
+
from ksadk.studio.resource_authority import (
|
|
128
|
+
ResourceAuthorityPolicy,
|
|
129
|
+
SignedKnowledgeResourceAuthority,
|
|
130
|
+
resource_authority_policy_from_environment,
|
|
131
|
+
)
|
|
132
|
+
from ksadk.studio.resource_build_admission import (
|
|
133
|
+
admit_resource_build,
|
|
134
|
+
resource_build_required,
|
|
135
|
+
)
|
|
95
136
|
from ksadk.studio.resource_catalog import LocalResourceCatalog
|
|
96
|
-
from ksadk.studio.
|
|
137
|
+
from ksadk.studio.resource_connections import ResourceConnectionRepository
|
|
138
|
+
from ksadk.studio.run_service import StudioRunService, StudioRunSpec
|
|
97
139
|
from ksadk.studio.runtime_catalog import inspect_runtime_catalog
|
|
98
140
|
from ksadk.studio.runtime_source import materialize_generated_runtime_source
|
|
141
|
+
from ksadk.studio.scheduler_runtime import (
|
|
142
|
+
StudioScheduledKernelRegistry,
|
|
143
|
+
StudioSchedulerRuntimeError,
|
|
144
|
+
)
|
|
145
|
+
from ksadk.studio.scheduler_service import StudioSchedulerService
|
|
146
|
+
from ksadk.studio.soul import soul_digest
|
|
99
147
|
from ksadk.studio.templates import (
|
|
100
148
|
compose_blank_agent,
|
|
101
149
|
compose_research_agent,
|
|
@@ -105,6 +153,8 @@ from ksadk.studio.templates import (
|
|
|
105
153
|
from ksadk.studio.validator import AgentValidator
|
|
106
154
|
from ksadk.studio.workspace import Workspace
|
|
107
155
|
|
|
156
|
+
_T = TypeVar("_T")
|
|
157
|
+
|
|
108
158
|
_TRAJECTORY_KEEPALIVE_SECONDS = 15.0
|
|
109
159
|
_EVALUATION_TARGET_LABELS = {
|
|
110
160
|
TargetKind.A2A: "A2A Agent",
|
|
@@ -129,14 +179,78 @@ class StudioService:
|
|
|
129
179
|
cloud_gateway: CloudDeploymentGateway | None = None,
|
|
130
180
|
codex_runtime_inspector: RuntimeInspector | None = None,
|
|
131
181
|
runtime_executor: RuntimeExecutor | None = None,
|
|
182
|
+
harness_reasoner: Any | None = None,
|
|
183
|
+
plugin_provider_manifests: Mapping[str, PluginManifest] | None = None,
|
|
184
|
+
plugin_provider_factories: Mapping[str, Any] | None = None,
|
|
185
|
+
legacy_harness_sources: Sequence[LegacyHarnessSource] = (),
|
|
186
|
+
dsh_provider_registration_manager: StudioDshProviderRegistrationManager | None = None,
|
|
187
|
+
dsh_capability_service: StudioDshCapabilityService | None = None,
|
|
188
|
+
resource_authority_policy: ResourceAuthorityPolicy | None = None,
|
|
132
189
|
) -> None:
|
|
190
|
+
provider_manifests = dict(plugin_provider_manifests or {})
|
|
191
|
+
provider_factories = dict(plugin_provider_factories or {})
|
|
192
|
+
if provider_manifests.keys() != provider_factories.keys():
|
|
193
|
+
raise ValueError(
|
|
194
|
+
"plugin provider manifests and factories must use the same exact references"
|
|
195
|
+
)
|
|
133
196
|
self.workspace = Workspace(root)
|
|
134
197
|
self.workspace.initialize()
|
|
198
|
+
self._startup_provider_manifests = provider_manifests
|
|
199
|
+
self._startup_provider_factories = provider_factories
|
|
200
|
+
self._active_provider_manifests = dict(provider_manifests)
|
|
201
|
+
self._dsh_provider_registration_manager = (
|
|
202
|
+
dsh_provider_registration_manager
|
|
203
|
+
or StudioDshProviderRegistrationManager.discover_or_create_workspace_default(
|
|
204
|
+
self.workspace.root
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
self.dsh_capabilities = (
|
|
208
|
+
dsh_capability_service
|
|
209
|
+
or StudioDshCapabilityService.discover_or_create_workspace_default(self.workspace.root)
|
|
210
|
+
)
|
|
211
|
+
if dsh_capability_service is not None or os.environ.get(
|
|
212
|
+
"KSADK_DSH_HOME", ""
|
|
213
|
+
).strip() or os.environ.get("KSADK_DSH_PROFILE", "").strip():
|
|
214
|
+
self._resource_dsh_provider_registration_manager = None
|
|
215
|
+
self.resource_dsh_capabilities = self.dsh_capabilities
|
|
216
|
+
else:
|
|
217
|
+
self._resource_dsh_provider_registration_manager = (
|
|
218
|
+
StudioDshProviderRegistrationManager.create_workspace_resource_default(
|
|
219
|
+
self.workspace.root
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
self.resource_dsh_capabilities = (
|
|
223
|
+
StudioDshCapabilityService.create_workspace_resource_default(
|
|
224
|
+
self.workspace.root
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
self._start_lock = asyncio.Lock()
|
|
228
|
+
self._started = False
|
|
229
|
+
self._closed = False
|
|
135
230
|
self._apply_persisted_settings()
|
|
136
231
|
self.avatar_assets = AgentAvatarAssetStore(self.workspace)
|
|
232
|
+
self.conversation_attachments = ConversationAttachmentStore(self.workspace)
|
|
137
233
|
self.drafts = AgentDraftRepository(self.workspace)
|
|
138
234
|
self.catalog = LocalResourceCatalog(self.workspace)
|
|
139
235
|
self.builds = BuildRepository(self.workspace)
|
|
236
|
+
self.credentials = (
|
|
237
|
+
credential_resolver
|
|
238
|
+
or getattr(model_client, "credential_resolver", None)
|
|
239
|
+
or CredentialResolver(self.workspace)
|
|
240
|
+
)
|
|
241
|
+
self.resource_connections = ResourceConnectionRepository(self.workspace, self.credentials)
|
|
242
|
+
effective_resource_policy = (
|
|
243
|
+
resource_authority_policy
|
|
244
|
+
if resource_authority_policy is not None
|
|
245
|
+
else resource_authority_policy_from_environment()
|
|
246
|
+
)
|
|
247
|
+
self.resource_authority = (
|
|
248
|
+
SignedKnowledgeResourceAuthority(
|
|
249
|
+
self.resource_connections, effective_resource_policy
|
|
250
|
+
)
|
|
251
|
+
if effective_resource_policy is not None
|
|
252
|
+
else None
|
|
253
|
+
)
|
|
140
254
|
self.validator = AgentValidator()
|
|
141
255
|
self.builder = AgentBundleBuilder(
|
|
142
256
|
self.workspace,
|
|
@@ -147,12 +261,19 @@ class StudioService:
|
|
|
147
261
|
),
|
|
148
262
|
repository=self.builds,
|
|
149
263
|
)
|
|
264
|
+
self.plugin_compositions = StudioPluginCompositionCompiler(
|
|
265
|
+
self.workspace,
|
|
266
|
+
self.catalog,
|
|
267
|
+
provider_manifests=provider_manifests,
|
|
268
|
+
)
|
|
150
269
|
self.event_store = RunEventStore(self.workspace)
|
|
151
270
|
self.session_service = LocalSessionService(project_dir=str(self.workspace.root))
|
|
152
271
|
self.runtime_events = RuntimeEventStore(self.session_service)
|
|
153
272
|
self.codex_manifests = CodexManifestRepository(self.workspace)
|
|
154
273
|
self.codex_builds = CodexBuildRepository(self.workspace)
|
|
155
274
|
self.codex_drafts = CodexDraftRepository(self.workspace)
|
|
275
|
+
self.codex_plugin_snapshots = CodexPluginSnapshotStore(self.workspace)
|
|
276
|
+
self.codex_provider_builds = CodexProviderBuildManager(self)
|
|
156
277
|
codex_builder_kwargs = {}
|
|
157
278
|
if codex_runtime_inspector is not None:
|
|
158
279
|
codex_builder_kwargs["runtime_inspector"] = codex_runtime_inspector
|
|
@@ -162,6 +283,10 @@ class StudioService:
|
|
|
162
283
|
build_repository=self.codex_builds,
|
|
163
284
|
resource_catalog=self.catalog,
|
|
164
285
|
draft_repository=self.codex_drafts,
|
|
286
|
+
plugin_snapshot_store=self.codex_plugin_snapshots,
|
|
287
|
+
resource_connections=self.resource_connections,
|
|
288
|
+
provider_build=self.codex_provider_builds.prepare,
|
|
289
|
+
provider_validate=self.codex_provider_builds.bundle_root,
|
|
165
290
|
**codex_builder_kwargs,
|
|
166
291
|
)
|
|
167
292
|
self.runtime_executor = runtime_executor or RuntimeExecutor(
|
|
@@ -174,17 +299,15 @@ class StudioService:
|
|
|
174
299
|
session_service=self.session_service,
|
|
175
300
|
runtime_events=self.runtime_events,
|
|
176
301
|
)
|
|
177
|
-
self.credentials = (
|
|
178
|
-
credential_resolver
|
|
179
|
-
or getattr(model_client, "credential_resolver", None)
|
|
180
|
-
or CredentialResolver(self.workspace)
|
|
181
|
-
)
|
|
182
302
|
self.codex_runs = CodexRunSpecResolver(
|
|
183
303
|
self.workspace,
|
|
184
304
|
build_repository=self.codex_builds,
|
|
185
305
|
manifest_repository=self.codex_manifests,
|
|
186
306
|
credential_resolver=self.credentials,
|
|
187
307
|
resource_catalog=self.catalog,
|
|
308
|
+
draft_repository=self.codex_drafts,
|
|
309
|
+
plugin_snapshot_store=self.codex_plugin_snapshots,
|
|
310
|
+
provider_bundle_resolver=self.codex_provider_builds.bundle_root,
|
|
188
311
|
)
|
|
189
312
|
self.framework_runs = FrameworkRunSpecResolver(
|
|
190
313
|
self.workspace,
|
|
@@ -194,6 +317,38 @@ class StudioService:
|
|
|
194
317
|
credential_resolver=self.credentials
|
|
195
318
|
)
|
|
196
319
|
self.model_client = runtime_model_client
|
|
320
|
+
self.plugin_runs = StudioPluginRuntime(
|
|
321
|
+
self.workspace,
|
|
322
|
+
build_repository=self.builds,
|
|
323
|
+
session_service=self.session_service,
|
|
324
|
+
model_client=self.model_client,
|
|
325
|
+
secret_resolver=self.credentials,
|
|
326
|
+
codex_local_launch_resolver=self.codex_provider_builds.native_launch,
|
|
327
|
+
runtime_executor=self.runtime_executor,
|
|
328
|
+
harness_reasoner=harness_reasoner,
|
|
329
|
+
provider_manifests=provider_manifests,
|
|
330
|
+
provider_factories=provider_factories,
|
|
331
|
+
legacy_harness_sources=legacy_harness_sources,
|
|
332
|
+
dsh_capability_service=self.dsh_capabilities,
|
|
333
|
+
resource_dsh_capability_service=self.resource_dsh_capabilities,
|
|
334
|
+
resource_authority=self.resource_authority,
|
|
335
|
+
resource_connections=self.resource_connections,
|
|
336
|
+
resource_actor_ref="local-user",
|
|
337
|
+
)
|
|
338
|
+
self.run_service.plugin_runtime = self.plugin_runs
|
|
339
|
+
self.scheduler_runtimes = StudioScheduledKernelRegistry(
|
|
340
|
+
resolve_build=self.resolve_run_spec,
|
|
341
|
+
resolve_adapter_provider=self._scheduler_adapter_provider,
|
|
342
|
+
session_service=self.session_service,
|
|
343
|
+
runtime_executor=self.runtime_executor,
|
|
344
|
+
)
|
|
345
|
+
self.scheduler = StudioSchedulerService(
|
|
346
|
+
self.workspace,
|
|
347
|
+
runtime_registry=self.scheduler_runtimes,
|
|
348
|
+
)
|
|
349
|
+
from ksadk.studio.scheduler_assistant import StudioScheduleAssistant
|
|
350
|
+
|
|
351
|
+
self.run_service.schedule_assistant = StudioScheduleAssistant(self)
|
|
197
352
|
self.mcp_runtime = MCPRuntimeAdapter(self.workspace, credentials=self.credentials)
|
|
198
353
|
self._cloud_gateway_override = cloud_gateway
|
|
199
354
|
self.cloud = CloudDeploymentService(
|
|
@@ -202,15 +357,772 @@ class StudioService:
|
|
|
202
357
|
build_repository=self.builds,
|
|
203
358
|
)
|
|
204
359
|
self.operations = OperationManager(self.workspace)
|
|
205
|
-
self.evaluation_storage = EvaluationStorage(
|
|
206
|
-
self.workspace.resolve(".agentkit/evaluations")
|
|
207
|
-
)
|
|
360
|
+
self.evaluation_storage = EvaluationStorage(self.workspace.resolve(".agentkit/evaluations"))
|
|
208
361
|
self.authoring = StudioAuthoringCoordinator(self)
|
|
209
362
|
self.codex_agents = CodexAgentService(self)
|
|
210
363
|
|
|
364
|
+
async def start(self) -> None:
|
|
365
|
+
"""Bind ready managed DSH registrations before build or execution."""
|
|
366
|
+
|
|
367
|
+
async with self._start_lock:
|
|
368
|
+
self._ensure_open()
|
|
369
|
+
if self._started:
|
|
370
|
+
return
|
|
371
|
+
await self._bootstrap_official_dsh_defaults()
|
|
372
|
+
manifests, factories, manager_refs = await self._provider_snapshot(refresh=False)
|
|
373
|
+
self.plugin_compositions.replace_provider_registrations(manifests)
|
|
374
|
+
self.plugin_runs.replace_provider_registrations(manifests, factories)
|
|
375
|
+
self._active_provider_manifests = manifests
|
|
376
|
+
manager = self._dsh_provider_registration_manager
|
|
377
|
+
if manager is not None and manager_refs is not None:
|
|
378
|
+
manager.mark_bound(manager_refs)
|
|
379
|
+
self._started = True
|
|
380
|
+
|
|
381
|
+
async def refresh_dsh_provider_registrations(self) -> None:
|
|
382
|
+
"""Rebind the exact current DSH Profile and release stale activations."""
|
|
383
|
+
|
|
384
|
+
async with self._start_lock:
|
|
385
|
+
self._ensure_open()
|
|
386
|
+
safe_to_resume = False
|
|
387
|
+
try:
|
|
388
|
+
await self.plugin_runs.suspend_admission()
|
|
389
|
+
await self.reset_dsh_capability_state()
|
|
390
|
+
await self._bind_dsh_provider_registrations_locked(refresh=True)
|
|
391
|
+
await self._refresh_dsh_catalog_resource(required=False)
|
|
392
|
+
safe_to_resume = True
|
|
393
|
+
finally:
|
|
394
|
+
if safe_to_resume:
|
|
395
|
+
await self.plugin_runs.resume_admission()
|
|
396
|
+
|
|
397
|
+
async def reconfigure_dsh_profile(
|
|
398
|
+
self,
|
|
399
|
+
operation: Callable[[], Awaitable[_T]],
|
|
400
|
+
) -> _T:
|
|
401
|
+
"""Run one Profile mutation while all Agent admission is suspended."""
|
|
402
|
+
|
|
403
|
+
async with self._start_lock:
|
|
404
|
+
self._ensure_open()
|
|
405
|
+
safe_to_resume = False
|
|
406
|
+
try:
|
|
407
|
+
await self.plugin_runs.suspend_admission()
|
|
408
|
+
await self.reset_dsh_capability_state()
|
|
409
|
+
try:
|
|
410
|
+
result = await operation()
|
|
411
|
+
except BaseException as mutation_error:
|
|
412
|
+
if (
|
|
413
|
+
isinstance(mutation_error, StudioError)
|
|
414
|
+
and mutation_error.code == "DSH_PROFILE_RECOVERY_REQUIRED"
|
|
415
|
+
):
|
|
416
|
+
raise
|
|
417
|
+
try:
|
|
418
|
+
await self._bind_dsh_provider_registrations_locked(refresh=True)
|
|
419
|
+
await self._refresh_dsh_catalog_resource(required=False)
|
|
420
|
+
safe_to_resume = True
|
|
421
|
+
except Exception as recovery_error: # noqa: BLE001
|
|
422
|
+
logging.getLogger(__name__).warning(
|
|
423
|
+
"DSH provider recovery after mutation failure skipped: %s",
|
|
424
|
+
recovery_error,
|
|
425
|
+
)
|
|
426
|
+
raise
|
|
427
|
+
await self._bind_dsh_provider_registrations_locked(refresh=True)
|
|
428
|
+
await self._refresh_dsh_catalog_resource(required=False)
|
|
429
|
+
safe_to_resume = True
|
|
430
|
+
return result
|
|
431
|
+
finally:
|
|
432
|
+
if safe_to_resume:
|
|
433
|
+
await self.plugin_runs.resume_admission()
|
|
434
|
+
|
|
435
|
+
async def _bind_dsh_provider_registrations_locked(self, *, refresh: bool) -> None:
|
|
436
|
+
if self._dsh_provider_registration_manager is None:
|
|
437
|
+
self._dsh_provider_registration_manager = (
|
|
438
|
+
StudioDshProviderRegistrationManager.discover_or_create_workspace_default(
|
|
439
|
+
self.workspace.root
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
await self._bootstrap_official_dsh_defaults()
|
|
443
|
+
manifests, factories, manager_refs = await self._provider_snapshot(refresh=refresh)
|
|
444
|
+
self.plugin_compositions.replace_provider_registrations(manifests)
|
|
445
|
+
self.plugin_runs.replace_provider_registrations(manifests, factories)
|
|
446
|
+
self._active_provider_manifests = manifests
|
|
447
|
+
manager = self._dsh_provider_registration_manager
|
|
448
|
+
if manager is not None and manager_refs is not None:
|
|
449
|
+
manager.mark_bound(manager_refs)
|
|
450
|
+
self._started = True
|
|
451
|
+
|
|
452
|
+
async def reset_dsh_capability_state(self) -> None:
|
|
453
|
+
"""Drop the current DSH capability/Core generation."""
|
|
454
|
+
|
|
455
|
+
self.catalog.clear_dsh_profile_mcp()
|
|
456
|
+
await self.dsh_capabilities.refresh()
|
|
457
|
+
|
|
458
|
+
async def refresh_dsh_catalog_resource(self): # type: ignore[no-untyped-def]
|
|
459
|
+
"""Validate and publish the current DSH Profile as a bindable MCP."""
|
|
460
|
+
|
|
461
|
+
_snapshot, resource = await self.dsh_capability_catalog_snapshot()
|
|
462
|
+
return resource
|
|
463
|
+
|
|
464
|
+
async def dsh_capability_catalog_snapshot(self): # type: ignore[no-untyped-def]
|
|
465
|
+
"""Atomically snapshot and publish one current DSH generation."""
|
|
466
|
+
|
|
467
|
+
async with self._start_lock:
|
|
468
|
+
self._ensure_open()
|
|
469
|
+
snapshot = await self.dsh_capabilities.capability_snapshot()
|
|
470
|
+
resource = self.catalog.replace_dsh_profile_mcp(snapshot.descriptor)
|
|
471
|
+
return snapshot, resource
|
|
472
|
+
|
|
473
|
+
async def ensure_dsh_catalog_available(self) -> None:
|
|
474
|
+
"""Publish an explicitly enabled DSH Profile for the generic selector.
|
|
475
|
+
|
|
476
|
+
The normal Studio startup remains side-effect free for legacy users.
|
|
477
|
+
The generic MCP catalog request performs only a profile metadata check;
|
|
478
|
+
it starts the managed capability host when the user has already enabled
|
|
479
|
+
at least one DSH plugin.
|
|
480
|
+
"""
|
|
481
|
+
|
|
482
|
+
async with self._start_lock:
|
|
483
|
+
self._ensure_open()
|
|
484
|
+
existing = self.catalog.list(kind="mcp", source="provider", limit=200)
|
|
485
|
+
if any(item.contract.get("materialization") == "dsh-profile" for item in existing):
|
|
486
|
+
return
|
|
487
|
+
checker = getattr(self.dsh_capabilities, "has_enabled_profile_plugins", None)
|
|
488
|
+
if checker is None:
|
|
489
|
+
return
|
|
490
|
+
try:
|
|
491
|
+
enabled = await checker()
|
|
492
|
+
except Exception as error: # noqa: BLE001 - optional ecosystem boundary
|
|
493
|
+
logging.getLogger(__name__).warning("DSH catalog discovery skipped: %s", error)
|
|
494
|
+
return
|
|
495
|
+
if enabled:
|
|
496
|
+
await self._refresh_dsh_catalog_resource(required=False)
|
|
497
|
+
|
|
498
|
+
@asynccontextmanager
|
|
499
|
+
async def dsh_profile_read_transaction(self) -> AsyncIterator[None]:
|
|
500
|
+
"""Fence a UI grant read against Profile mutation and shutdown."""
|
|
501
|
+
|
|
502
|
+
async with self._start_lock:
|
|
503
|
+
self._ensure_open()
|
|
504
|
+
yield
|
|
505
|
+
|
|
506
|
+
async def _refresh_dsh_catalog_resource(self, *, required: bool): # type: ignore[no-untyped-def]
|
|
507
|
+
try:
|
|
508
|
+
snapshot = await self.dsh_capabilities.capability_snapshot()
|
|
509
|
+
return self.catalog.replace_dsh_profile_mcp(snapshot.descriptor)
|
|
510
|
+
except Exception as error: # noqa: BLE001 - optional ecosystem boundary
|
|
511
|
+
self.catalog.clear_dsh_profile_mcp()
|
|
512
|
+
if required:
|
|
513
|
+
raise
|
|
514
|
+
logging.getLogger(__name__).warning(
|
|
515
|
+
"DSH capability catalog publication skipped: %s", error
|
|
516
|
+
)
|
|
517
|
+
return None
|
|
518
|
+
|
|
519
|
+
async def _bootstrap_official_dsh_defaults(self) -> None:
|
|
520
|
+
manager = self._dsh_provider_registration_manager
|
|
521
|
+
if manager is None:
|
|
522
|
+
return
|
|
523
|
+
try:
|
|
524
|
+
result = await manager.bootstrap_official_codex_provider()
|
|
525
|
+
except Exception as error: # optional DSH must fail closed to legacy paths
|
|
526
|
+
logging.getLogger(__name__).warning(
|
|
527
|
+
"official DSH provider bootstrap skipped: %s", error
|
|
528
|
+
)
|
|
529
|
+
else:
|
|
530
|
+
if result in {"installed", "already_enabled"}:
|
|
531
|
+
logging.getLogger(__name__).info(
|
|
532
|
+
"official Codex DSH provider bootstrap: %s", result
|
|
533
|
+
)
|
|
534
|
+
try:
|
|
535
|
+
resource_result = await manager.bootstrap_official_resource_plugins()
|
|
536
|
+
except Exception as error: # optional DSH must fail closed to legacy paths
|
|
537
|
+
logging.getLogger(__name__).warning(
|
|
538
|
+
"official DSH resource bootstrap skipped: %s", error
|
|
539
|
+
)
|
|
540
|
+
else:
|
|
541
|
+
if resource_result in {"installed", "already_enabled"}:
|
|
542
|
+
logging.getLogger(__name__).info(
|
|
543
|
+
"official platform resource DSH bootstrap: %s", resource_result
|
|
544
|
+
)
|
|
545
|
+
resource_manager = self._resource_dsh_provider_registration_manager
|
|
546
|
+
if resource_manager is None:
|
|
547
|
+
return
|
|
548
|
+
try:
|
|
549
|
+
resource_result = await resource_manager.bootstrap_official_resource_plugins()
|
|
550
|
+
except Exception as error:
|
|
551
|
+
logging.getLogger(__name__).warning(
|
|
552
|
+
"official resource execution Profile bootstrap skipped: %s", error
|
|
553
|
+
)
|
|
554
|
+
else:
|
|
555
|
+
if resource_result in {"installed", "already_enabled"}:
|
|
556
|
+
logging.getLogger(__name__).info(
|
|
557
|
+
"official resource execution Profile bootstrap: %s", resource_result
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
async def _provider_snapshot(
|
|
561
|
+
self, *, refresh: bool
|
|
562
|
+
) -> tuple[dict[str, PluginManifest], dict[str, Any], tuple[str, ...] | None]:
|
|
563
|
+
manifests = dict(self._startup_provider_manifests)
|
|
564
|
+
factories = dict(self._startup_provider_factories)
|
|
565
|
+
manager = self._dsh_provider_registration_manager
|
|
566
|
+
if manager is None:
|
|
567
|
+
return manifests, factories, None
|
|
568
|
+
try:
|
|
569
|
+
registrations = await (manager.refresh() if refresh else manager.start())
|
|
570
|
+
except StudioDshProviderRegistrationError as error:
|
|
571
|
+
logging.getLogger(__name__).warning(
|
|
572
|
+
"DSH AgentProvider discovery failed closed: %s", error.code
|
|
573
|
+
)
|
|
574
|
+
return manifests, factories, None
|
|
575
|
+
if registrations.manifests.keys() != registrations.factories.keys():
|
|
576
|
+
logging.getLogger(__name__).warning(
|
|
577
|
+
"DSH AgentProvider discovery returned a partial registration set"
|
|
578
|
+
)
|
|
579
|
+
return manifests, factories, None
|
|
580
|
+
for provider_ref, manifest in registrations.manifests.items():
|
|
581
|
+
if provider_ref in manifests and (
|
|
582
|
+
manifests[provider_ref] != manifest
|
|
583
|
+
or factories[provider_ref] is not registrations.factories[provider_ref]
|
|
584
|
+
):
|
|
585
|
+
logging.getLogger(__name__).warning(
|
|
586
|
+
"DSH AgentProvider registration conflicts with startup provider: %s",
|
|
587
|
+
provider_ref,
|
|
588
|
+
)
|
|
589
|
+
return (
|
|
590
|
+
dict(self._startup_provider_manifests),
|
|
591
|
+
dict(self._startup_provider_factories),
|
|
592
|
+
None,
|
|
593
|
+
)
|
|
594
|
+
manifests[provider_ref] = manifest
|
|
595
|
+
factories[provider_ref] = registrations.factories[provider_ref]
|
|
596
|
+
return manifests, factories, tuple(registrations.manifests)
|
|
597
|
+
|
|
598
|
+
def agent_provider_catalog(self) -> list[dict[str, Any]]:
|
|
599
|
+
"""Return only external providers that reached Studio's bound selector."""
|
|
600
|
+
|
|
601
|
+
reserved = {
|
|
602
|
+
KSADK_HARNESS_AGENT_PROVIDER_PLUGIN_ID,
|
|
603
|
+
}
|
|
604
|
+
package_by_ref: dict[str, str] = {}
|
|
605
|
+
display_name_by_ref: dict[str, str] = {}
|
|
606
|
+
manager = self._dsh_provider_registration_manager
|
|
607
|
+
if manager is not None:
|
|
608
|
+
package_by_ref = {
|
|
609
|
+
item.provider_ref: item.package_name
|
|
610
|
+
for item in manager.inventory.packages
|
|
611
|
+
if item.state == "bound" and item.provider_ref is not None
|
|
612
|
+
}
|
|
613
|
+
display_name_by_ref = {
|
|
614
|
+
item.provider_ref: item.display_name
|
|
615
|
+
for item in manager.inventory.packages
|
|
616
|
+
if item.state == "bound" and item.provider_ref is not None and item.display_name
|
|
617
|
+
}
|
|
618
|
+
items = []
|
|
619
|
+
for provider_ref, manifest in sorted(self._active_provider_manifests.items()):
|
|
620
|
+
if manifest.metadata.id in reserved:
|
|
621
|
+
continue
|
|
622
|
+
items.append(
|
|
623
|
+
{
|
|
624
|
+
"providerRef": provider_ref,
|
|
625
|
+
"pluginId": package_by_ref.get(provider_ref, manifest.metadata.id),
|
|
626
|
+
"resolvedVersion": manifest.metadata.version,
|
|
627
|
+
"displayName": display_name_by_ref.get(provider_ref, manifest.metadata.id),
|
|
628
|
+
"state": "enabled",
|
|
629
|
+
"compatible": True,
|
|
630
|
+
"selectable": True,
|
|
631
|
+
"reason": None,
|
|
632
|
+
"permissions": list(manifest.spec.permissions),
|
|
633
|
+
"isolation": manifest.spec.isolation,
|
|
634
|
+
"configSchemaDeclared": manifest.spec.config_schema is not None,
|
|
635
|
+
"secretFields": list(manifest.spec.secret_fields),
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
return items
|
|
639
|
+
|
|
640
|
+
def dsh_provider_runtime_state(self, package_name: str) -> dict[str, Any] | None:
|
|
641
|
+
"""Project one manager-owned package lifecycle state for plugin APIs."""
|
|
642
|
+
|
|
643
|
+
manager = self._dsh_provider_registration_manager
|
|
644
|
+
if manager is None:
|
|
645
|
+
return None
|
|
646
|
+
status = next(
|
|
647
|
+
(item for item in manager.inventory.packages if item.package_name == package_name),
|
|
648
|
+
None,
|
|
649
|
+
)
|
|
650
|
+
if status is None:
|
|
651
|
+
return None
|
|
652
|
+
return {
|
|
653
|
+
"state": status.state,
|
|
654
|
+
"providerRef": status.provider_ref,
|
|
655
|
+
"errorCode": status.error_code,
|
|
656
|
+
}
|
|
657
|
+
|
|
211
658
|
def runtime_catalog(self) -> list[dict]:
|
|
212
659
|
return inspect_runtime_catalog(self.runtime_executor)
|
|
213
660
|
|
|
661
|
+
def _scheduler_adapter_provider(self, spec: StudioRunSpec): # type: ignore[no-untyped-def]
|
|
662
|
+
if spec.plugin_bundle_root is not None:
|
|
663
|
+
return self.plugin_runs.kernel_adapter_provider(spec)
|
|
664
|
+
return lambda: self.runtime_executor.create_adapter(spec.launch_context)
|
|
665
|
+
|
|
666
|
+
def resolve_run_spec(
|
|
667
|
+
self,
|
|
668
|
+
build_id: str,
|
|
669
|
+
*,
|
|
670
|
+
model: str | None = None,
|
|
671
|
+
sandbox: str | None = None,
|
|
672
|
+
approval_mode: str | None = None,
|
|
673
|
+
) -> StudioRunSpec:
|
|
674
|
+
"""Resolve one immutable Build through its only compatible resolver."""
|
|
675
|
+
|
|
676
|
+
try:
|
|
677
|
+
self.codex_builds.get(build_id)
|
|
678
|
+
except Exception as exc:
|
|
679
|
+
if getattr(exc, "status_code", None) != 404:
|
|
680
|
+
raise
|
|
681
|
+
else:
|
|
682
|
+
# The record exists in the Codex repository. Any later resolution
|
|
683
|
+
# error belongs to that Build and must remain actionable; a nested
|
|
684
|
+
# 404 (for example a missing plugin snapshot) is not evidence that
|
|
685
|
+
# this is a framework Build.
|
|
686
|
+
return self.codex_runs.resolve(
|
|
687
|
+
build_id,
|
|
688
|
+
model=model,
|
|
689
|
+
sandbox=sandbox,
|
|
690
|
+
approval_mode=approval_mode,
|
|
691
|
+
)
|
|
692
|
+
framework_build = self.builds.get(build_id)
|
|
693
|
+
runtime_type = framework_build.runtime_type.strip().lower()
|
|
694
|
+
if runtime_type in {"harness", "plugin"}:
|
|
695
|
+
return self.plugin_runs.resolve(
|
|
696
|
+
build_id,
|
|
697
|
+
model=model,
|
|
698
|
+
approval_mode=approval_mode,
|
|
699
|
+
)
|
|
700
|
+
return self.framework_runs.resolve(
|
|
701
|
+
build_id,
|
|
702
|
+
model=model,
|
|
703
|
+
approval_mode=approval_mode,
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
def validate_schedule_build(
|
|
707
|
+
self,
|
|
708
|
+
build_ref: str | None,
|
|
709
|
+
*,
|
|
710
|
+
agent_id: str | None = None,
|
|
711
|
+
) -> None:
|
|
712
|
+
"""Reject a ScheduledTask target build that is not a real immutable Build.
|
|
713
|
+
|
|
714
|
+
The agent-scoped authoring path resolves the Build server-side via
|
|
715
|
+
:meth:`ensure_current_build`, so this guard is primarily for the raw
|
|
716
|
+
``/api/v1/schedules`` surface that accepts a caller-supplied
|
|
717
|
+
``agent_version_ref``. A version name or tag (for example "v1") is
|
|
718
|
+
not an immutable Build id and must fail at admission with an actionable
|
|
719
|
+
error instead of collapsing into a later opaque DISPATCH_FAILED.
|
|
720
|
+
"""
|
|
721
|
+
ref = (build_ref or "").strip()
|
|
722
|
+
if not ref:
|
|
723
|
+
raise StudioError(
|
|
724
|
+
"SCHEDULE_BUILD_REQUIRED",
|
|
725
|
+
"定时任务必须绑定一个已成功构建的 Build id(不能为空或使用版本名)",
|
|
726
|
+
status_code=422,
|
|
727
|
+
field="target.agentVersionRef",
|
|
728
|
+
)
|
|
729
|
+
try:
|
|
730
|
+
spec = self.resolve_run_spec(ref)
|
|
731
|
+
except StudioError as error:
|
|
732
|
+
if error.status_code == 404:
|
|
733
|
+
raise StudioError(
|
|
734
|
+
"SCHEDULE_BUILD_UNAVAILABLE",
|
|
735
|
+
f"定时任务绑定的 Build {ref!r} 不可用:请使用已成功构建的 Build id,而非版本名",
|
|
736
|
+
status_code=422,
|
|
737
|
+
field="target.agentVersionRef",
|
|
738
|
+
details={"buildId": ref},
|
|
739
|
+
) from error
|
|
740
|
+
raise
|
|
741
|
+
except Exception as error:
|
|
742
|
+
raise StudioError(
|
|
743
|
+
"SCHEDULE_BUILD_UNAVAILABLE",
|
|
744
|
+
f"定时任务绑定的 Build {ref!r} 不可用:{error}",
|
|
745
|
+
status_code=422,
|
|
746
|
+
field="target.agentVersionRef",
|
|
747
|
+
details={"buildId": ref},
|
|
748
|
+
) from error
|
|
749
|
+
if agent_id and spec.agent_id != agent_id:
|
|
750
|
+
raise StudioError(
|
|
751
|
+
"SCHEDULE_AGENT_MISMATCH",
|
|
752
|
+
"定时任务绑定的 Build 与所选 Agent 不一致",
|
|
753
|
+
status_code=422,
|
|
754
|
+
field="target.agentVersionRef",
|
|
755
|
+
details={"buildId": ref, "agentId": agent_id},
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
def conversation_surface(
|
|
759
|
+
self,
|
|
760
|
+
build_id: str,
|
|
761
|
+
*,
|
|
762
|
+
session_id: str,
|
|
763
|
+
) -> ConversationSurface:
|
|
764
|
+
"""Describe the actual local composer contract for one Build/session.
|
|
765
|
+
|
|
766
|
+
This is intentionally conservative. It derives the declaration from
|
|
767
|
+
the resolved Build, rather than guessing support from a model name or
|
|
768
|
+
sending provider-specific fields to every Runtime.
|
|
769
|
+
"""
|
|
770
|
+
|
|
771
|
+
spec = self.resolve_run_spec(build_id)
|
|
772
|
+
runtime_type = spec.launch_context.runtime_type.strip().lower()
|
|
773
|
+
runtime_mode: Literal["native", "translated"] = (
|
|
774
|
+
"native" if runtime_type == "codex" else "translated"
|
|
775
|
+
)
|
|
776
|
+
inputs = [ConversationCapability(name="text", mode="native")]
|
|
777
|
+
if spec.model:
|
|
778
|
+
inputs.append(ConversationCapability(name="model.select", mode=runtime_mode))
|
|
779
|
+
inputs.append(ConversationCapability(name="approval", mode=runtime_mode))
|
|
780
|
+
if runtime_type == "codex":
|
|
781
|
+
inputs.extend(
|
|
782
|
+
(
|
|
783
|
+
# Studio projects image data URLs to native Codex ImageInput.
|
|
784
|
+
ConversationCapability(name="attachment.image", mode="native"),
|
|
785
|
+
# Bounded UTF-8/code attachments are made model-visible as
|
|
786
|
+
# deterministic text parts by the Responses compatibility
|
|
787
|
+
# adapter. Binary files remain unavailable in Phase 2.
|
|
788
|
+
ConversationCapability(name="attachment.file", mode="translated"),
|
|
789
|
+
ConversationCapability(name="reasoning.effort", mode="native"),
|
|
790
|
+
ConversationCapability(name="goal", mode="native"),
|
|
791
|
+
ConversationCapability(name="plan", mode="native"),
|
|
792
|
+
)
|
|
793
|
+
)
|
|
794
|
+
|
|
795
|
+
outputs = [
|
|
796
|
+
ConversationCapability(name="text", mode="native"),
|
|
797
|
+
ConversationCapability(name="streaming", mode=runtime_mode),
|
|
798
|
+
]
|
|
799
|
+
if runtime_type == "codex":
|
|
800
|
+
outputs.extend(
|
|
801
|
+
(
|
|
802
|
+
ConversationCapability(name="reasoning", mode="native"),
|
|
803
|
+
ConversationCapability(name="tool.inspect", mode="native"),
|
|
804
|
+
ConversationCapability(name="approval", mode="native"),
|
|
805
|
+
ConversationCapability(name="goal", mode="native"),
|
|
806
|
+
ConversationCapability(name="plan", mode="native"),
|
|
807
|
+
ConversationCapability(name="cancel", mode="native"),
|
|
808
|
+
)
|
|
809
|
+
)
|
|
810
|
+
return ConversationSurface(
|
|
811
|
+
surface_id=f"studio.build.{spec.build_id}",
|
|
812
|
+
session_id=session_id,
|
|
813
|
+
provider_ref=f"studio.runtime.{runtime_type}",
|
|
814
|
+
inputs=tuple(inputs),
|
|
815
|
+
outputs=tuple(outputs),
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
async def ensure_current_build(self, agent_id: str):
|
|
819
|
+
"""Return the Build that is eligible for a local Studio turn.
|
|
820
|
+
|
|
821
|
+
This is deliberately one shared resolver for Web chat and Scheduler
|
|
822
|
+
authoring. A Scheduler must never select a mutable Draft or a stale
|
|
823
|
+
Codex manifest merely because a UI happened to show it as an Agent.
|
|
824
|
+
"""
|
|
825
|
+
|
|
826
|
+
await self.start()
|
|
827
|
+
if self.is_codex_agent(agent_id):
|
|
828
|
+
self.codex_agent_detail(agent_id)
|
|
829
|
+
builds = [
|
|
830
|
+
record
|
|
831
|
+
for record in self.codex_builds.list()
|
|
832
|
+
if record.agent_name == agent_id and self.codex_builder.is_current(record)
|
|
833
|
+
]
|
|
834
|
+
if builds:
|
|
835
|
+
return builds[0]
|
|
836
|
+
return await asyncio.to_thread(self.codex_builder.build, agent_id)
|
|
837
|
+
draft = self.drafts.get(agent_id)
|
|
838
|
+
composition_required = self.plugin_compositions.required_for(draft)
|
|
839
|
+
resources_required = resource_build_required(draft)
|
|
840
|
+
for record in self.builds.list_for_agent(agent_id):
|
|
841
|
+
if record.status == BuildStatus.SUCCEEDED:
|
|
842
|
+
if (composition_required or resources_required) and (
|
|
843
|
+
record.source_revision != draft.metadata.revision
|
|
844
|
+
or (composition_required and not self._build_has_composition(record))
|
|
845
|
+
or (resources_required and not self._build_has_resources(record))
|
|
846
|
+
):
|
|
847
|
+
continue
|
|
848
|
+
if composition_required:
|
|
849
|
+
composition = self.plugin_compositions.compile_if_required(draft)
|
|
850
|
+
if composition is None: # pragma: no cover - guarded by required_for
|
|
851
|
+
raise StudioError(
|
|
852
|
+
"PLUGIN_COMPOSITION_REQUIRED",
|
|
853
|
+
"当前 Agent 需要插件组合,但无法生成 Composition",
|
|
854
|
+
status_code=409,
|
|
855
|
+
)
|
|
856
|
+
self.plugin_compositions.bind_build(
|
|
857
|
+
composition,
|
|
858
|
+
agent_id=draft.metadata.id,
|
|
859
|
+
build_id=record.id,
|
|
860
|
+
)
|
|
861
|
+
return record
|
|
862
|
+
if draft.spec.model is None and not draft.spec.bindings.model_profile_id:
|
|
863
|
+
raise StudioError(
|
|
864
|
+
"AGENT_MODEL_REQUIRED",
|
|
865
|
+
"当前 Agent 未绑定 Model Profile,请先在 Agent 配置中选择模型;"
|
|
866
|
+
"API Key 只提供访问凭证,不会自动绑定模型。",
|
|
867
|
+
status_code=422,
|
|
868
|
+
field="spec.bindings.modelProfileId",
|
|
869
|
+
)
|
|
870
|
+
return await asyncio.to_thread(self._build_agent_bundle, draft)
|
|
871
|
+
|
|
872
|
+
def _build_agent_bundle(self, draft: AgentDraft):
|
|
873
|
+
composition = self.plugin_compositions.compile_if_required(draft)
|
|
874
|
+
resource_build = None
|
|
875
|
+
if resource_build_required(draft):
|
|
876
|
+
dsh_profile = self.resource_dsh_capabilities.capture_resource_build_snapshot()
|
|
877
|
+
resource_build = admit_resource_build(
|
|
878
|
+
draft,
|
|
879
|
+
authority=self.resource_authority,
|
|
880
|
+
connections=self.resource_connections,
|
|
881
|
+
dsh_profile=dsh_profile,
|
|
882
|
+
)
|
|
883
|
+
try:
|
|
884
|
+
record = self.builder.build(
|
|
885
|
+
draft,
|
|
886
|
+
composition=composition,
|
|
887
|
+
resource_build=resource_build,
|
|
888
|
+
)
|
|
889
|
+
except BundleSecurityError as error:
|
|
890
|
+
first = error.findings[0]
|
|
891
|
+
reason = {
|
|
892
|
+
"literal-secret-field": "明文凭证",
|
|
893
|
+
"url-credentials": "含账号信息的 URL",
|
|
894
|
+
"local-home-path": "本机用户目录路径",
|
|
895
|
+
"invalid-structured-input": "无法解析的结构化数据",
|
|
896
|
+
}.get(first.kind, "敏感内容")
|
|
897
|
+
raise StudioError(
|
|
898
|
+
"BUNDLE_SECURITY_REJECTED",
|
|
899
|
+
f"AgentBundle 安全检查未通过:{first.path} 检测到{reason}",
|
|
900
|
+
status_code=422,
|
|
901
|
+
details={
|
|
902
|
+
"securityFindings": [
|
|
903
|
+
{
|
|
904
|
+
"path": finding.path,
|
|
905
|
+
"kind": finding.kind,
|
|
906
|
+
"field": finding.field,
|
|
907
|
+
}
|
|
908
|
+
for finding in error.findings
|
|
909
|
+
]
|
|
910
|
+
},
|
|
911
|
+
) from error
|
|
912
|
+
if composition is not None:
|
|
913
|
+
self.plugin_compositions.bind_build(
|
|
914
|
+
composition,
|
|
915
|
+
agent_id=draft.metadata.id,
|
|
916
|
+
build_id=record.id,
|
|
917
|
+
)
|
|
918
|
+
return record
|
|
919
|
+
|
|
920
|
+
def _build_has_composition(self, record: Any) -> bool:
|
|
921
|
+
"""Reject stale pre-Phase-2 builds for a composed runtime.
|
|
922
|
+
|
|
923
|
+
This check is intentionally scoped to Harness/plugin runtimes. Legacy
|
|
924
|
+
ADK/LangGraph build selection retains its existing behavior.
|
|
925
|
+
"""
|
|
926
|
+
|
|
927
|
+
if not record.artifact_path:
|
|
928
|
+
return False
|
|
929
|
+
try:
|
|
930
|
+
archive = self.workspace.resolve(record.artifact_path, must_exist=True)
|
|
931
|
+
with zipfile.ZipFile(archive) as bundle:
|
|
932
|
+
manifest = json.loads(bundle.read("manifest.json"))
|
|
933
|
+
names = frozenset(bundle.namelist())
|
|
934
|
+
return bool(
|
|
935
|
+
isinstance(manifest, dict)
|
|
936
|
+
and manifest.get("compositionProfileDigest")
|
|
937
|
+
and "composition-profile.json" in names
|
|
938
|
+
and "plugin-lock.json" in names
|
|
939
|
+
)
|
|
940
|
+
except (KeyError, OSError, UnicodeError, ValueError, zipfile.BadZipFile):
|
|
941
|
+
return False
|
|
942
|
+
|
|
943
|
+
def _build_has_resources(self, record: Any) -> bool:
|
|
944
|
+
if (
|
|
945
|
+
not record.artifact_path
|
|
946
|
+
or not record.resource_build_digest
|
|
947
|
+
or not record.resource_snapshot_digest
|
|
948
|
+
):
|
|
949
|
+
return False
|
|
950
|
+
try:
|
|
951
|
+
archive = self.workspace.resolve(record.artifact_path, must_exist=True)
|
|
952
|
+
with zipfile.ZipFile(archive) as bundle:
|
|
953
|
+
manifest = BundleManifest.model_validate_json(bundle.read("manifest.json"))
|
|
954
|
+
names = frozenset(bundle.namelist())
|
|
955
|
+
return bool(
|
|
956
|
+
manifest.resource_build_digest == record.resource_build_digest
|
|
957
|
+
and manifest.resource_snapshot_digest == record.resource_snapshot_digest
|
|
958
|
+
and "platform-resources/resource-build.json" in names
|
|
959
|
+
)
|
|
960
|
+
except (KeyError, OSError, UnicodeError, ValueError, zipfile.BadZipFile):
|
|
961
|
+
return False
|
|
962
|
+
|
|
963
|
+
async def create_agent_schedule(
|
|
964
|
+
self,
|
|
965
|
+
agent_id: str,
|
|
966
|
+
*,
|
|
967
|
+
display_name: str,
|
|
968
|
+
prompt: str,
|
|
969
|
+
schedule: ScheduleSpec,
|
|
970
|
+
enabled: bool = True,
|
|
971
|
+
continuity: Literal["new_session", "continue_session"] = "new_session",
|
|
972
|
+
session_id: str | None = None,
|
|
973
|
+
) -> ScheduledTask:
|
|
974
|
+
"""Create a local-only schedule for the Kernel Runtime that owns it.
|
|
975
|
+
|
|
976
|
+
The browser provides only human intent (prompt/calendar/continuity).
|
|
977
|
+
The trusted Studio process resolves the immutable Build and concrete
|
|
978
|
+
Kernel instance. Thus a task cannot be pointed at another Agent
|
|
979
|
+
Instance, smuggle a permit reference, or claim cloud scheduling.
|
|
980
|
+
"""
|
|
981
|
+
|
|
982
|
+
await self.start()
|
|
983
|
+
build = await self.ensure_current_build(agent_id)
|
|
984
|
+
spec = self.resolve_run_spec(build.id)
|
|
985
|
+
await self.scheduler_runtimes.start()
|
|
986
|
+
try:
|
|
987
|
+
target = await self.scheduler_runtimes.ensure_build(
|
|
988
|
+
build.id,
|
|
989
|
+
expected_agent_id=agent_id,
|
|
990
|
+
)
|
|
991
|
+
runtime = self.scheduler_runtimes.runtime_for_build(build.id)
|
|
992
|
+
except StudioSchedulerRuntimeError as error:
|
|
993
|
+
raise StudioError(
|
|
994
|
+
error.code,
|
|
995
|
+
str(error),
|
|
996
|
+
status_code=409,
|
|
997
|
+
details={"agentId": agent_id, "buildId": build.id},
|
|
998
|
+
) from error
|
|
999
|
+
if continuity == "continue_session" and not session_id:
|
|
1000
|
+
raise StudioError(
|
|
1001
|
+
"SCHEDULE_SESSION_REQUIRED",
|
|
1002
|
+
"继续会话的定时任务必须选择一个已有会话。",
|
|
1003
|
+
status_code=422,
|
|
1004
|
+
field="sessionId",
|
|
1005
|
+
)
|
|
1006
|
+
if continuity == "continue_session":
|
|
1007
|
+
await self._require_schedule_session_owner(agent_id, session_id)
|
|
1008
|
+
self._require_schedule_continuation(runtime, spec.launch_context.runtime_type)
|
|
1009
|
+
task = ScheduledTask(
|
|
1010
|
+
task_id=f"sched-{uuid4().hex[:20]}",
|
|
1011
|
+
display_name=display_name,
|
|
1012
|
+
target=ScheduledTaskTarget(
|
|
1013
|
+
agent_id=agent_id,
|
|
1014
|
+
tenant_id=target.tenant_id,
|
|
1015
|
+
agent_instance_id=target.agent_instance_id,
|
|
1016
|
+
agent_version_ref=str(build.id),
|
|
1017
|
+
session_id=session_id,
|
|
1018
|
+
# This is an opaque local authority marker, never a browser
|
|
1019
|
+
# supplied credential. The dispatcher obtains a short-lived
|
|
1020
|
+
# in-process permit at the AgentControl ingress boundary.
|
|
1021
|
+
authorization_ref="runtime://local-kernel-ingress",
|
|
1022
|
+
),
|
|
1023
|
+
schedule=schedule,
|
|
1024
|
+
command=ScheduleCommandTemplate(payload={"content": prompt}),
|
|
1025
|
+
enabled=enabled,
|
|
1026
|
+
continuity=continuity,
|
|
1027
|
+
)
|
|
1028
|
+
return self.scheduler.create_task(task)
|
|
1029
|
+
|
|
1030
|
+
async def _require_schedule_session_owner(self, agent_id: str, session_id: str | None) -> None:
|
|
1031
|
+
session = (
|
|
1032
|
+
await self.session_service.get_session_metadata(session_id) if session_id else None
|
|
1033
|
+
)
|
|
1034
|
+
if session is None or session.agent_id != agent_id:
|
|
1035
|
+
raise StudioError(
|
|
1036
|
+
"SCHEDULE_SESSION_INVALID",
|
|
1037
|
+
"请选择该智能体已有的会话。",
|
|
1038
|
+
status_code=422,
|
|
1039
|
+
field="sessionId",
|
|
1040
|
+
)
|
|
1041
|
+
|
|
1042
|
+
async def validate_schedule_session(
|
|
1043
|
+
self, agent_id: str, continuity: str, session_id: str | None, build_id: str | None
|
|
1044
|
+
) -> None:
|
|
1045
|
+
if continuity != "continue_session":
|
|
1046
|
+
return
|
|
1047
|
+
await self._require_schedule_session_owner(agent_id, session_id)
|
|
1048
|
+
await self.scheduler_runtimes.ensure_build(build_id, expected_agent_id=agent_id)
|
|
1049
|
+
runtime = self.scheduler_runtimes.runtime_for_build(build_id)
|
|
1050
|
+
spec = self.resolve_run_spec(build_id)
|
|
1051
|
+
self._require_schedule_continuation(runtime, spec.launch_context.runtime_type)
|
|
1052
|
+
|
|
1053
|
+
@staticmethod
|
|
1054
|
+
def _require_schedule_continuation(runtime: Any, runtime_type: str) -> None:
|
|
1055
|
+
"""Fail closed unless the bound Provider can preserve one conversation.
|
|
1056
|
+
|
|
1057
|
+
Harness owns process-local Session history without exposing the generic
|
|
1058
|
+
checkpoint ``resume`` verb. Codex and external adapters must declare
|
|
1059
|
+
the typed resume capability. An older Runtime that lacks either proof
|
|
1060
|
+
remains usable for normal conversations and ``new_session`` schedules;
|
|
1061
|
+
only the optional follow-up mode is rejected.
|
|
1062
|
+
"""
|
|
1063
|
+
|
|
1064
|
+
if runtime_type.strip().lower() == "harness":
|
|
1065
|
+
return
|
|
1066
|
+
kernel = getattr(runtime, "kernel", None)
|
|
1067
|
+
describe = getattr(kernel, "capabilities", None)
|
|
1068
|
+
matrix = describe() if callable(describe) else None
|
|
1069
|
+
resume = getattr(matrix, "resume", None)
|
|
1070
|
+
if not bool(getattr(resume, "supported", False)):
|
|
1071
|
+
raise StudioError(
|
|
1072
|
+
"SCHEDULE_CONTINUATION_UNAVAILABLE",
|
|
1073
|
+
"当前 Runtime 未声明可恢复的会话续接能力;可改用新会话定时任务。",
|
|
1074
|
+
status_code=409,
|
|
1075
|
+
field="continuity",
|
|
1076
|
+
details={"runtimeType": runtime_type},
|
|
1077
|
+
)
|
|
1078
|
+
|
|
1079
|
+
def list_agent_schedules(self, agent_id: str) -> list[ScheduledTask]:
|
|
1080
|
+
return [task for task in self.scheduler.list_tasks() if task.target.agent_id == agent_id]
|
|
1081
|
+
|
|
1082
|
+
def get_agent_schedule(self, agent_id: str, task_id: str) -> ScheduledTask:
|
|
1083
|
+
task = self.scheduler.get_task(task_id)
|
|
1084
|
+
if task.target.agent_id != agent_id:
|
|
1085
|
+
from ksadk.studio.errors import not_found
|
|
1086
|
+
|
|
1087
|
+
raise not_found("schedule", task_id)
|
|
1088
|
+
return task
|
|
1089
|
+
|
|
1090
|
+
def update_agent_schedule(
|
|
1091
|
+
self,
|
|
1092
|
+
agent_id: str,
|
|
1093
|
+
task_id: str,
|
|
1094
|
+
*,
|
|
1095
|
+
display_name: str,
|
|
1096
|
+
prompt: str,
|
|
1097
|
+
schedule: ScheduleSpec,
|
|
1098
|
+
enabled: bool,
|
|
1099
|
+
continuity: Literal["new_session", "continue_session"],
|
|
1100
|
+
session_id: str | None,
|
|
1101
|
+
) -> ScheduledTask:
|
|
1102
|
+
existing = self.get_agent_schedule(agent_id, task_id)
|
|
1103
|
+
if continuity == "continue_session" and not session_id:
|
|
1104
|
+
raise StudioError(
|
|
1105
|
+
"SCHEDULE_SESSION_REQUIRED",
|
|
1106
|
+
"继续会话的定时任务必须选择一个已有会话。",
|
|
1107
|
+
status_code=422,
|
|
1108
|
+
field="sessionId",
|
|
1109
|
+
)
|
|
1110
|
+
task = existing.model_copy(
|
|
1111
|
+
update={
|
|
1112
|
+
"display_name": display_name,
|
|
1113
|
+
"schedule": schedule,
|
|
1114
|
+
"command": ScheduleCommandTemplate(payload={"content": prompt}),
|
|
1115
|
+
"enabled": enabled,
|
|
1116
|
+
"continuity": continuity,
|
|
1117
|
+
"target": existing.target.model_copy(update={"session_id": session_id}),
|
|
1118
|
+
}
|
|
1119
|
+
)
|
|
1120
|
+
return self.scheduler.update_task(task_id, task)
|
|
1121
|
+
|
|
1122
|
+
async def run_agent_schedule_now(self, agent_id: str, task_id: str):
|
|
1123
|
+
self.get_agent_schedule(agent_id, task_id)
|
|
1124
|
+
return await self.scheduler.run_now(task_id)
|
|
1125
|
+
|
|
214
1126
|
def codex_manifest_state(self, agent_id: str | None = None) -> dict:
|
|
215
1127
|
return self.codex_agents.manifest_state(agent_id)
|
|
216
1128
|
|
|
@@ -306,7 +1218,8 @@ class StudioService:
|
|
|
306
1218
|
from ksadk.studio.errors import not_found
|
|
307
1219
|
|
|
308
1220
|
runs = self.event_store.list_runs(session_id=session_id)
|
|
309
|
-
|
|
1221
|
+
session = await self.session_service.get_session_metadata(session_id)
|
|
1222
|
+
if not runs and session is None:
|
|
310
1223
|
raise not_found("session", session_id)
|
|
311
1224
|
if any(run.status == RunStatus.RUNNING for run in runs):
|
|
312
1225
|
raise StudioError(
|
|
@@ -315,9 +1228,54 @@ class StudioService:
|
|
|
315
1228
|
status_code=409,
|
|
316
1229
|
details={"sessionId": session_id},
|
|
317
1230
|
)
|
|
1231
|
+
await self.plugin_runs.close_session(session_id)
|
|
318
1232
|
await self.session_service.delete_session(session_id)
|
|
319
1233
|
self.event_store.delete_session(session_id)
|
|
320
1234
|
|
|
1235
|
+
async def aclose(self) -> None:
|
|
1236
|
+
"""Release local provider activations and supervised plugin processes."""
|
|
1237
|
+
|
|
1238
|
+
async with self._start_lock:
|
|
1239
|
+
if self._closed:
|
|
1240
|
+
return
|
|
1241
|
+
self._closed = True
|
|
1242
|
+
cleanup = asyncio.create_task(self._close_owned_plugin_services())
|
|
1243
|
+
interrupted = False
|
|
1244
|
+
while not cleanup.done():
|
|
1245
|
+
try:
|
|
1246
|
+
await asyncio.shield(cleanup)
|
|
1247
|
+
except asyncio.CancelledError:
|
|
1248
|
+
interrupted = True
|
|
1249
|
+
cleanup.result()
|
|
1250
|
+
if interrupted:
|
|
1251
|
+
raise asyncio.CancelledError
|
|
1252
|
+
|
|
1253
|
+
async def _close_owned_plugin_services(self) -> None:
|
|
1254
|
+
first_error: BaseException | None = None
|
|
1255
|
+
owned = [self.plugin_runs.aclose, self.dsh_capabilities.aclose]
|
|
1256
|
+
if self.resource_dsh_capabilities is not self.dsh_capabilities:
|
|
1257
|
+
owned.append(self.resource_dsh_capabilities.aclose)
|
|
1258
|
+
if self._dsh_provider_registration_manager is not None:
|
|
1259
|
+
owned.append(self._dsh_provider_registration_manager.aclose)
|
|
1260
|
+
if self._resource_dsh_provider_registration_manager is not None:
|
|
1261
|
+
owned.append(self._resource_dsh_provider_registration_manager.aclose)
|
|
1262
|
+
for close in owned:
|
|
1263
|
+
try:
|
|
1264
|
+
await close()
|
|
1265
|
+
except BaseException as error: # cleanup must continue
|
|
1266
|
+
if first_error is None:
|
|
1267
|
+
first_error = error
|
|
1268
|
+
if first_error is not None:
|
|
1269
|
+
raise first_error
|
|
1270
|
+
|
|
1271
|
+
def _ensure_open(self) -> None:
|
|
1272
|
+
if self._closed:
|
|
1273
|
+
raise StudioError(
|
|
1274
|
+
"STUDIO_SERVICE_CLOSED",
|
|
1275
|
+
"Studio service 已关闭",
|
|
1276
|
+
status_code=503,
|
|
1277
|
+
)
|
|
1278
|
+
|
|
321
1279
|
async def _require_runtime_session(self, session_id: str) -> None:
|
|
322
1280
|
if await self.session_service.get_session_metadata(session_id) is None:
|
|
323
1281
|
raise StudioError(
|
|
@@ -842,12 +1800,36 @@ class StudioService:
|
|
|
842
1800
|
|
|
843
1801
|
def agent_detail(self, agent_id: str) -> dict:
|
|
844
1802
|
if self.is_codex_agent(agent_id):
|
|
845
|
-
|
|
1803
|
+
detail = self.codex_agent_detail(agent_id)
|
|
1804
|
+
detail["soulProjection"] = self._soul_projection(detail["draft"])
|
|
1805
|
+
return detail
|
|
846
1806
|
draft = self.drafts.get(agent_id)
|
|
847
1807
|
return {
|
|
848
1808
|
"draft": draft,
|
|
849
1809
|
"builds": self.builds.list_for_agent(agent_id)[:10],
|
|
850
1810
|
"validation": self.validator.validate(draft),
|
|
1811
|
+
"soulProjection": self._soul_projection(draft),
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
@staticmethod
|
|
1815
|
+
def _soul_projection(draft: AgentDraft) -> dict[str, object]:
|
|
1816
|
+
"""Describe the reviewed Soul source without claiming runtime learning."""
|
|
1817
|
+
|
|
1818
|
+
soul = draft.spec.soul
|
|
1819
|
+
runtime_type = draft.spec.runtime.type if draft.spec.runtime is not None else ""
|
|
1820
|
+
compile_target = {
|
|
1821
|
+
"codex": "managed-runtime.base_instructions",
|
|
1822
|
+
"plugin": "instructions/soul.md",
|
|
1823
|
+
}.get(runtime_type, "resolved-agent-spec.instructions.system")
|
|
1824
|
+
return {
|
|
1825
|
+
"present": soul is not None,
|
|
1826
|
+
"source": "AgentSpec.soul",
|
|
1827
|
+
"sourceRevision": draft.metadata.revision,
|
|
1828
|
+
"schemaVersion": soul.schema_version if soul is not None else "agentkit.soul/v1",
|
|
1829
|
+
"digest": soul_digest(soul) if soul is not None else None,
|
|
1830
|
+
"digestAlgorithm": "sha256-canonical-json",
|
|
1831
|
+
"compileTarget": compile_target,
|
|
1832
|
+
"compileOrder": "before-instructions.system",
|
|
851
1833
|
}
|
|
852
1834
|
|
|
853
1835
|
def create_studio_agent(
|
|
@@ -993,6 +1975,83 @@ class StudioService:
|
|
|
993
1975
|
return detail["validation"]
|
|
994
1976
|
return self.validator.validate(draft, level=level)
|
|
995
1977
|
|
|
1978
|
+
async def resource_binding_status(self, agent_id: str, *, activation_id: str) -> dict:
|
|
1979
|
+
# Check workspace ownership, but never project the mutable draft as runtime state.
|
|
1980
|
+
await asyncio.to_thread(self.agent_detail, agent_id)
|
|
1981
|
+
status = await self.dsh_capabilities.resource_runtime_status(
|
|
1982
|
+
agent_id=agent_id, activation_id=activation_id,
|
|
1983
|
+
)
|
|
1984
|
+
if status is None:
|
|
1985
|
+
raise StudioError(
|
|
1986
|
+
"RESOURCE_ACTIVATION_NOT_FOUND", "未找到此 Agent 的资源运行实例",
|
|
1987
|
+
status_code=404,
|
|
1988
|
+
)
|
|
1989
|
+
return status
|
|
1990
|
+
|
|
1991
|
+
def validate_resource_bindings(self, agent_id: str, *, expected_revision: int) -> dict:
|
|
1992
|
+
from ksadk.resource_runtime.plugin_config import resource_plugin_config
|
|
1993
|
+
from ksadk.studio.resource_binding_validation import resource_binding_diagnostics
|
|
1994
|
+
|
|
1995
|
+
draft = self.agent_detail(agent_id)["draft"]
|
|
1996
|
+
if draft.metadata.revision != expected_revision:
|
|
1997
|
+
raise StudioError(
|
|
1998
|
+
"AGENT_REVISION_CONFLICT", "资源校验版本与当前 Agent 不一致", status_code=409,
|
|
1999
|
+
)
|
|
2000
|
+
diagnostics = resource_binding_diagnostics(
|
|
2001
|
+
draft.spec.bindings.plugins, draft.spec.memory, self.resource_connections,
|
|
2002
|
+
)
|
|
2003
|
+
configs = [
|
|
2004
|
+
(index, config)
|
|
2005
|
+
for index, binding in enumerate(draft.spec.bindings.plugins)
|
|
2006
|
+
if binding.enabled
|
|
2007
|
+
for config in [
|
|
2008
|
+
resource_plugin_config(
|
|
2009
|
+
binding.plugin_ref,
|
|
2010
|
+
binding.ecosystem,
|
|
2011
|
+
binding.config,
|
|
2012
|
+
enabled=True,
|
|
2013
|
+
)
|
|
2014
|
+
]
|
|
2015
|
+
if config is not None
|
|
2016
|
+
]
|
|
2017
|
+
verified = []
|
|
2018
|
+
if (
|
|
2019
|
+
self.resource_authority is not None
|
|
2020
|
+
and configs
|
|
2021
|
+
and not any(item.severity == DiagnosticSeverity.ERROR for item in diagnostics)
|
|
2022
|
+
):
|
|
2023
|
+
for index, config in configs:
|
|
2024
|
+
try:
|
|
2025
|
+
verified.append(self.resource_authority.admit(config))
|
|
2026
|
+
except StudioError as error:
|
|
2027
|
+
diagnostics.append(
|
|
2028
|
+
Diagnostic(
|
|
2029
|
+
severity=DiagnosticSeverity.ERROR,
|
|
2030
|
+
code=error.code,
|
|
2031
|
+
message=error.message,
|
|
2032
|
+
field=error.field
|
|
2033
|
+
or f"spec.bindings.plugins[{index}].config.binding",
|
|
2034
|
+
)
|
|
2035
|
+
)
|
|
2036
|
+
current = self.agent_detail(agent_id)["draft"]
|
|
2037
|
+
if current.metadata.revision != draft.metadata.revision:
|
|
2038
|
+
raise StudioError(
|
|
2039
|
+
"AGENT_REVISION_CONFLICT",
|
|
2040
|
+
"资源校验期间 Agent 已变更,请刷新后重试",
|
|
2041
|
+
status_code=409,
|
|
2042
|
+
)
|
|
2043
|
+
authorization_verified = bool(configs) and len(verified) == len(configs)
|
|
2044
|
+
if authorization_verified:
|
|
2045
|
+
diagnostics = [
|
|
2046
|
+
item for item in diagnostics if item.code != "RESOURCE_AUTHORITY_UNVERIFIED"
|
|
2047
|
+
]
|
|
2048
|
+
return {
|
|
2049
|
+
"revision": draft.metadata.revision,
|
|
2050
|
+
"valid": not any(item.severity == "error" for item in diagnostics),
|
|
2051
|
+
"authorizationVerified": authorization_verified,
|
|
2052
|
+
"diagnostics": [item.model_dump(by_alias=True, mode="json") for item in diagnostics],
|
|
2053
|
+
}
|
|
2054
|
+
|
|
996
2055
|
def submit_studio_build(
|
|
997
2056
|
self,
|
|
998
2057
|
agent_id: str,
|
|
@@ -1000,32 +2059,11 @@ class StudioService:
|
|
|
1000
2059
|
revision: int,
|
|
1001
2060
|
idempotency_key: str,
|
|
1002
2061
|
) -> Operation:
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
if runtime is None:
|
|
1009
|
-
from ksadk.studio.errors import StudioError
|
|
1010
|
-
|
|
1011
|
-
raise StudioError(
|
|
1012
|
-
"RUNTIME_NOT_REGISTERED",
|
|
1013
|
-
"Agent 引用的 RuntimeAdapter 未注册",
|
|
1014
|
-
status_code=422,
|
|
1015
|
-
details={"runtimeType": runtime_type},
|
|
1016
|
-
)
|
|
1017
|
-
if runtime["status"] != "ready":
|
|
1018
|
-
from ksadk.studio.errors import StudioError
|
|
1019
|
-
|
|
1020
|
-
raise StudioError(
|
|
1021
|
-
"RUNTIME_DEPENDENCY_MISSING",
|
|
1022
|
-
f"{runtime['displayName']} Runtime 依赖未安装",
|
|
1023
|
-
status_code=422,
|
|
1024
|
-
details={
|
|
1025
|
-
"runtimeType": runtime_type,
|
|
1026
|
-
"installCommand": runtime["installCommand"],
|
|
1027
|
-
},
|
|
1028
|
-
)
|
|
2062
|
+
# Codex build admission already runs the injected runtime inspector and
|
|
2063
|
+
# pins its result into the immutable build. Checking package metadata
|
|
2064
|
+
# first would reject an explicitly supplied RuntimeExecutor/inspector
|
|
2065
|
+
# (including an out-of-process Codex runtime) merely because the local
|
|
2066
|
+
# Studio interpreter does not have the optional wheel installed.
|
|
1029
2067
|
if self.is_codex_agent(agent_id):
|
|
1030
2068
|
detail = self.agent_detail(agent_id)
|
|
1031
2069
|
if revision != detail["draft"].metadata.revision:
|
|
@@ -1040,6 +2078,12 @@ class StudioService:
|
|
|
1040
2078
|
idempotency_key=idempotency_key,
|
|
1041
2079
|
agent_id=agent_id,
|
|
1042
2080
|
)
|
|
2081
|
+
|
|
2082
|
+
# A framework Build compiles and seals source/configuration only. Its
|
|
2083
|
+
# optional Runtime dependency belongs to run preflight, and may live in
|
|
2084
|
+
# a different process or deployment image. Rejecting the Build from
|
|
2085
|
+
# this Studio interpreter's package metadata would make portable
|
|
2086
|
+
# bundles impossible and incorrectly couple authoring to execution.
|
|
1043
2087
|
return self.submit_build(
|
|
1044
2088
|
agent_id,
|
|
1045
2089
|
revision=revision,
|
|
@@ -1271,8 +2315,7 @@ class StudioService:
|
|
|
1271
2315
|
resolved.model_profile_ids = [
|
|
1272
2316
|
resource_id
|
|
1273
2317
|
for resource_id in resolved.model_profile_ids
|
|
1274
|
-
if resource_id in known
|
|
1275
|
-
or resource_id not in current.model_profile_ids
|
|
2318
|
+
if resource_id in known or resource_id not in current.model_profile_ids
|
|
1276
2319
|
]
|
|
1277
2320
|
resolved.skills = selected_for_materialization(
|
|
1278
2321
|
candidate.skills,
|
|
@@ -1356,7 +2399,7 @@ class StudioService:
|
|
|
1356
2399
|
snapshot = draft.model_copy(deep=True)
|
|
1357
2400
|
|
|
1358
2401
|
async def runner(_operation_id: str):
|
|
1359
|
-
return await asyncio.to_thread(self.
|
|
2402
|
+
return await asyncio.to_thread(self._build_agent_bundle, snapshot)
|
|
1360
2403
|
|
|
1361
2404
|
return self.operations.submit(
|
|
1362
2405
|
kind=OperationKind.BUILD,
|
|
@@ -1420,21 +2463,13 @@ class StudioService:
|
|
|
1420
2463
|
):
|
|
1421
2464
|
"""Execute any immutable Studio Build through the canonical executor."""
|
|
1422
2465
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
except Exception as exc:
|
|
1431
|
-
if getattr(exc, "status_code", None) != 404:
|
|
1432
|
-
raise
|
|
1433
|
-
spec = self.framework_runs.resolve(
|
|
1434
|
-
build_id,
|
|
1435
|
-
model=model,
|
|
1436
|
-
approval_mode=approval_mode,
|
|
1437
|
-
)
|
|
2466
|
+
await self.start()
|
|
2467
|
+
spec = self.resolve_run_spec(
|
|
2468
|
+
build_id,
|
|
2469
|
+
model=model,
|
|
2470
|
+
sandbox=sandbox,
|
|
2471
|
+
approval_mode=approval_mode,
|
|
2472
|
+
)
|
|
1438
2473
|
if collaboration_mode or goal_objective or reasoning_effort:
|
|
1439
2474
|
from dataclasses import replace
|
|
1440
2475
|
|
|
@@ -1660,12 +2695,14 @@ class StudioService:
|
|
|
1660
2695
|
evalset = load_evalset(path)
|
|
1661
2696
|
except (EvalSetParseError, OSError):
|
|
1662
2697
|
continue
|
|
1663
|
-
evalsets.append(
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
2698
|
+
evalsets.append(
|
|
2699
|
+
{
|
|
2700
|
+
"path": path.relative_to(self.workspace.root).as_posix(),
|
|
2701
|
+
"name": evalset.name,
|
|
2702
|
+
"caseCount": len(evalset.cases),
|
|
2703
|
+
"contentDigest": evalset.content_digest,
|
|
2704
|
+
}
|
|
2705
|
+
)
|
|
1669
2706
|
evalsets.sort(key=lambda item: item["path"])
|
|
1670
2707
|
return {"builds": builds, "evalsets": evalsets}
|
|
1671
2708
|
|
|
@@ -1840,9 +2877,7 @@ class StudioService:
|
|
|
1840
2877
|
# this outbound control-plane request only, never in the Build or
|
|
1841
2878
|
# deployment receipt.
|
|
1842
2879
|
launch = self.codex_runs.resolve(build_id)
|
|
1843
|
-
runtime_environment = dict(
|
|
1844
|
-
(launch.launch_context.config or {}).get("env") or {}
|
|
1845
|
-
)
|
|
2880
|
+
runtime_environment = dict((launch.launch_context.config or {}).get("env") or {})
|
|
1846
2881
|
# Retrying a YAML deployment must update the Agent that the prior
|
|
1847
2882
|
# receipt already created. CreateAgent can have succeeded before
|
|
1848
2883
|
# a downstream Runtime-Service start failed; creating again would
|
|
@@ -1894,6 +2929,12 @@ class StudioService:
|
|
|
1894
2929
|
runner=managed_runtime_runner,
|
|
1895
2930
|
)
|
|
1896
2931
|
|
|
2932
|
+
# Do not turn a stale URL or a deleted Agent's Build into an accepted
|
|
2933
|
+
# operation that can only fail later in the worker. The Codex lookup
|
|
2934
|
+
# above intentionally falls back to framework builds, so establish
|
|
2935
|
+
# that the fallback record exists before returning HTTP 202.
|
|
2936
|
+
self.builds.get(build_id)
|
|
2937
|
+
|
|
1897
2938
|
async def runner(_operation_id: str):
|
|
1898
2939
|
return await self.cloud.deploy(build_id, request)
|
|
1899
2940
|
|
|
@@ -2026,14 +3067,10 @@ class StudioService:
|
|
|
2026
3067
|
|
|
2027
3068
|
workspace_identity = str(self.workspace.root.resolve())
|
|
2028
3069
|
region = (
|
|
2029
|
-
os.environ.get("AGENTENGINE_REGION")
|
|
2030
|
-
or os.environ.get("KSYUN_REGION")
|
|
2031
|
-
or "cn-beijing-6"
|
|
3070
|
+
os.environ.get("AGENTENGINE_REGION") or os.environ.get("KSYUN_REGION") or "cn-beijing-6"
|
|
2032
3071
|
).strip()
|
|
2033
3072
|
access_key = (
|
|
2034
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2035
|
-
or os.environ.get("KS3_ACCESS_KEY")
|
|
2036
|
-
or "unsigned"
|
|
3073
|
+
os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY") or "unsigned"
|
|
2037
3074
|
).strip()
|
|
2038
3075
|
|
|
2039
3076
|
def opaque(value: str) -> str:
|
|
@@ -2053,36 +3090,26 @@ class StudioService:
|
|
|
2053
3090
|
except Exception:
|
|
2054
3091
|
data = {}
|
|
2055
3092
|
defaults = {
|
|
2056
|
-
"sandbox": os.environ.get("KSADK_CODEX_SANDBOX", "
|
|
3093
|
+
"sandbox": os.environ.get("KSADK_CODEX_SANDBOX", "workspace-write-auto"),
|
|
2057
3094
|
"buildAfterCreate": True,
|
|
2058
3095
|
"codexProxy": current_proxy_mode(),
|
|
2059
3096
|
"cloudRegion": os.environ.get(
|
|
2060
3097
|
"AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "cn-beijing-6")
|
|
2061
3098
|
),
|
|
2062
3099
|
"cloudBucket": os.environ.get("KS3_BUCKET", ""),
|
|
2063
|
-
"cloudAccountId": (
|
|
2064
|
-
os.environ.get("KSYUN_ACCOUNT_ID", "").strip()
|
|
2065
|
-
),
|
|
3100
|
+
"cloudAccountId": (os.environ.get("KSYUN_ACCOUNT_ID", "").strip()),
|
|
2066
3101
|
# AK/SK 不回显(避免本地 UI 回传 secret);只暴露配置状态。
|
|
2067
3102
|
# 已配置 = 启动环境或已持久化 settings 里 AK+SK 齐全。
|
|
2068
3103
|
"cloudAccountConfigured": bool(
|
|
2069
|
-
(
|
|
2070
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2071
|
-
or os.environ.get("KS3_ACCESS_KEY", "")
|
|
2072
|
-
).strip()
|
|
3104
|
+
(os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
|
|
2073
3105
|
and (
|
|
2074
|
-
os.environ.get("KSYUN_SECRET_KEY")
|
|
2075
|
-
or os.environ.get("KS3_SECRET_KEY", "")
|
|
3106
|
+
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2076
3107
|
).strip()
|
|
2077
3108
|
),
|
|
2078
3109
|
"cloudSignedAccountConfigured": bool(
|
|
2079
|
-
(
|
|
2080
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2081
|
-
or os.environ.get("KS3_ACCESS_KEY", "")
|
|
2082
|
-
).strip()
|
|
3110
|
+
(os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
|
|
2083
3111
|
and (
|
|
2084
|
-
os.environ.get("KSYUN_SECRET_KEY")
|
|
2085
|
-
or os.environ.get("KS3_SECRET_KEY", "")
|
|
3112
|
+
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2086
3113
|
).strip()
|
|
2087
3114
|
),
|
|
2088
3115
|
"traceContent": os.environ.get("KSADK_STUDIO_TRACE_CONTENT", "1") != "0",
|
|
@@ -2191,26 +3218,34 @@ class StudioService:
|
|
|
2191
3218
|
secret_key = (
|
|
2192
3219
|
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2193
3220
|
).strip()
|
|
2194
|
-
|
|
3221
|
+
configured_region = os.environ.get(
|
|
2195
3222
|
"AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "")
|
|
2196
3223
|
).strip()
|
|
2197
|
-
|
|
3224
|
+
environment_region = os.environ.get("KSYUN_REGION", "").strip()
|
|
3225
|
+
logical_region = (
|
|
3226
|
+
"pre-online"
|
|
3227
|
+
if environment_region.lower() == "pre-online"
|
|
3228
|
+
else configured_region
|
|
3229
|
+
)
|
|
3230
|
+
if not all((access_key, secret_key, logical_region)):
|
|
2198
3231
|
return UnavailableCloudGateway()
|
|
2199
3232
|
control_client = AgentEngineClient(
|
|
2200
|
-
region=
|
|
3233
|
+
region=logical_region,
|
|
2201
3234
|
access_key=access_key,
|
|
2202
3235
|
secret_key=secret_key,
|
|
2203
3236
|
)
|
|
3237
|
+
is_preonline = logical_region.lower() == "pre-online"
|
|
2204
3238
|
stream_base_url = os.environ.get("AGENTENGINE_STREAM_SERVER_URL", "").strip()
|
|
2205
|
-
if not stream_base_url and
|
|
3239
|
+
if not stream_base_url and is_preonline:
|
|
2206
3240
|
# The pre-online KOP response path currently buffers SSE until
|
|
2207
|
-
# EOF
|
|
2208
|
-
#
|
|
3241
|
+
# EOF, and KOP may not yet publish newly deployed native Action
|
|
3242
|
+
# names. Its internal Server ingress validates the same V4
|
|
3243
|
+
# signature for RunAgent, ManagedRuntime, and plugin delivery.
|
|
2209
3244
|
stream_base_url = "http://agent-api-pre.kspmas-internal.ksyun.com"
|
|
2210
3245
|
stream_client = (
|
|
2211
3246
|
AgentEngineClient(
|
|
2212
3247
|
base_url=stream_base_url,
|
|
2213
|
-
region=
|
|
3248
|
+
region=logical_region,
|
|
2214
3249
|
access_key=access_key,
|
|
2215
3250
|
secret_key=secret_key,
|
|
2216
3251
|
)
|
|
@@ -2218,9 +3253,10 @@ class StudioService:
|
|
|
2218
3253
|
else control_client
|
|
2219
3254
|
)
|
|
2220
3255
|
return DirectAgentEngineCloudDeploymentGateway(
|
|
2221
|
-
region=
|
|
3256
|
+
region=logical_region,
|
|
2222
3257
|
client=control_client,
|
|
2223
3258
|
stream_client=stream_client,
|
|
3259
|
+
managed_runtime_client=stream_client if is_preonline else None,
|
|
2224
3260
|
bucket=os.environ.get("KS3_BUCKET", "").strip() or None,
|
|
2225
3261
|
ks3_credentials={
|
|
2226
3262
|
"access_key": access_key,
|