agentengine-sdk-python 0.8.2__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +22 -28
- agentengine_sdk_python-0.8.4.dist-info/RECORD +1070 -0
- ksadk/_build_provenance.json +1 -0
- ksadk/agui/_agent_helpers.py +4 -0
- ksadk/api/client.py +108 -91
- ksadk/builders/code_builder.py +36 -9
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +4 -0
- ksadk/cli/__init__.py +38 -3
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_plugin.py +662 -0
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +424 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +83 -283
- ksadk/common/auth.py +16 -10
- ksadk/configs/env_registry.py +59 -3
- ksadk/configs/settings.py +9 -0
- ksadk/context_engine/contributors.py +73 -8
- ksadk/conversations/__init__.py +19 -0
- ksadk/conversations/context.py +104 -24
- ksadk/conversations/contracts.py +266 -0
- ksadk/conversations/message_projection.py +154 -15
- ksadk/conversations/projector.py +614 -0
- ksadk/conversations/reducer.py +98 -0
- ksadk/conversations/runtime_invocation.py +5 -0
- ksadk/conversations/runtime_payloads.py +1 -0
- ksadk/conversations/runtime_preparation.py +30 -27
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +5 -0
- ksadk/conversations/runtime_streaming.py +25 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/_v1_compat/projection.py +2 -0
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/codex.py +190 -0
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/harness/__init__.py +45 -35
- ksadk/harness/config.py +2 -2
- ksadk/harness/runtime.py +75 -16
- ksadk/harness/tools.py +38 -13
- ksadk/interaction/provider.py +1 -0
- ksadk/interaction/providers/langgraph.py +1 -0
- ksadk/kernel/bootstrap.py +28 -4
- ksadk/kernel/contract_fingerprints.py +5 -4
- ksadk/kernel/contracts.py +8 -0
- ksadk/kernel/control.py +1 -0
- ksadk/kernel/ingress.py +36 -2
- ksadk/kernel/memory_store.py +1 -0
- ksadk/kernel/postgres_store.py +1 -0
- ksadk/kernel/sqlite_store.py +28 -0
- ksadk/kernel/store.py +3 -0
- ksadk/kernel/worker.py +76 -10
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/models.py +7 -4
- ksadk/memory/provider_resolver.py +3 -0
- ksadk/memory/providers/local_sqlite.py +7 -0
- ksadk/model_proxy/server.py +10 -5
- ksadk/plugins/__init__.py +171 -0
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +47 -0
- ksadk/plugins/bridges/codex.py +659 -0
- ksadk/plugins/bridges/dsh.py +1300 -0
- ksadk/plugins/builtins.py +746 -0
- ksadk/plugins/bundle.py +246 -0
- ksadk/plugins/bundle_security.py +191 -0
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/composition.py +537 -0
- ksadk/plugins/context_contributor.py +437 -0
- ksadk/plugins/contracts.py +569 -0
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_toolchain.py +1024 -0
- ksadk/plugins/ecosystem_bridge.py +1105 -0
- ksadk/plugins/ecosystem_probe.py +191 -0
- ksadk/plugins/host.py +787 -0
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +108 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- ksadk/plugins/providers/bundles/ksadk-codex/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +18 -0
- ksadk/plugins/providers/bundles/ksadk-codex/package.json +19 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/bundles/ksadk-harness/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-harness/package.json +19 -0
- ksadk/plugins/providers/codex.py +988 -0
- ksadk/plugins/providers/codex_dsh.py +83 -0
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh.py +951 -0
- ksadk/plugins/providers/dsh_capabilities.py +1389 -0
- ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +632 -0
- ksadk/plugins/providers/harness_dsh.py +91 -0
- ksadk/plugins/providers/legacy.py +215 -0
- ksadk/plugins/providers/legacy_catalog.py +100 -0
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/providers/shipped_dsh.py +370 -0
- ksadk/plugins/resolver.py +338 -0
- ksadk/plugins/subagent_providers/__init__.py +12 -0
- ksadk/plugins/subagent_providers/codex.py +443 -0
- ksadk/plugins/subagents.py +333 -0
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +74 -6
- ksadk/runners/adk_runner.py +149 -11
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +475 -145
- ksadk/runtime/_runner_adapter/stream_mapping.py +193 -60
- ksadk/runtime/adapter.py +3 -0
- ksadk/runtime/conversation_execution.py +92 -16
- ksadk/runtime/executor.py +78 -2
- ksadk/runtime/factory.py +30 -200
- ksadk/runtime/framework_adapters.py +41 -0
- ksadk/runtime/preprocessing.py +10 -2
- ksadk/runtime/runner_adapter.py +78 -14
- ksadk/runtime_context.py +40 -2
- ksadk/sandbox/__init__.py +2 -1
- ksadk/sandbox/backends/e2b.py +52 -11
- ksadk/sandbox/backends/local_process.py +9 -0
- ksadk/sandbox/base.py +2 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/sandbox/factory.py +72 -0
- ksadk/scheduler/__init__.py +18 -0
- ksadk/scheduler/calendar.py +102 -0
- ksadk/scheduler/contracts.py +254 -0
- ksadk/scheduler/dispatcher.py +129 -0
- ksadk/scheduler/engine.py +416 -0
- ksadk/scheduler/sqlite_store.py +581 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/control.py +210 -46
- ksadk/server/routes/dependencies.py +15 -0
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/sessions.py +284 -107
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-b4C7upmO.js} +3 -3
- ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
- ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock-BEBN4Ksz.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
- ksadk/server/static/assets/{arc-C4FzinUA.js → arc-bTohInsS.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
- ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-UBpgon5q.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
- ksadk/server/static/assets/{dist-B7seoj3d.js → dist-B2_CVgKv.js} +1 -1
- ksadk/server/static/assets/{dist-CSh_DE14.js → dist-B3FR1SKK.js} +1 -1
- ksadk/server/static/assets/{dist-DUX-id_F.js → dist-BIr4DSRq.js} +1 -1
- ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-BgV_owcB.js} +1 -1
- ksadk/server/static/assets/{dist-W-TIVntx.js → dist-Bj730Ib4.js} +1 -1
- ksadk/server/static/assets/{dist-BytlxIDT.js → dist-BnaTiyzN.js} +1 -1
- ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C1NMAY5a.js} +1 -1
- ksadk/server/static/assets/{dist-dDdADKFA.js → dist-C5_ZAZsG.js} +1 -1
- ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-CB9iJrvg.js} +1 -1
- ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-CFzsn6BG.js} +1 -1
- ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-Cf125P_m.js} +1 -1
- ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-ClYUxfeK.js} +1 -1
- ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DFD6Qa6T.js} +1 -1
- ksadk/server/static/assets/{dist-BX8z72IC.js → dist-DVCOWtha.js} +1 -1
- ksadk/server/static/assets/{dist-dydu68Fl.js → dist-D_ctSS2i.js} +1 -1
- ksadk/server/static/assets/{dist-ClxGviKw.js → dist-DiixqL0J.js} +1 -1
- ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-DoVSwoDb.js} +1 -1
- ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-DvFK7p5S.js} +1 -1
- ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-QfkEHOlb.js} +1 -1
- ksadk/server/static/assets/{dist-CttYUqzS.js → dist-btbmmX5O.js} +1 -1
- ksadk/server/static/assets/{dist-DmldrHd_.js → dist-fBO2v5Kt.js} +1 -1
- ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-ufY3F5p6.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
- ksadk/server/static/assets/index-DcTML1Up.css +2 -0
- ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
- ksadk/server/static/assets/{katex-vFWytM5c.js → katex-B4weu383.js} +1 -1
- ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-V-MgYHW1.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-CBijEX_c.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/models.py +26 -4
- ksadk/skills/package_store.py +186 -38
- ksadk/skills/runtime/agent.py +31 -6
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/backends/e2b.py +98 -6
- ksadk/skills/runtime/backends/local.py +73 -8
- ksadk/skills/runtime/base.py +3 -0
- ksadk/skills/runtime/executor.py +2 -0
- ksadk/skills/runtime/loader.py +10 -2
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +31 -0
- ksadk/skills/service_client.py +211 -24
- ksadk/studio/agent_lifecycle.py +26 -20
- ksadk/studio/api.py +714 -90
- ksadk/studio/api_catalog_routes.py +23 -0
- ksadk/studio/api_contracts.py +34 -1
- ksadk/studio/api_plugin_routes.py +911 -0
- ksadk/studio/api_resource_connections.py +183 -0
- ksadk/studio/attachment_store.py +187 -0
- ksadk/studio/authoring.py +10 -4
- ksadk/studio/authoring_coordinator.py +31 -16
- ksadk/studio/builder.py +199 -43
- ksadk/studio/cloud.py +346 -104
- ksadk/studio/cloud_shared_web.py +565 -0
- ksadk/studio/codex_agent_service.py +140 -27
- ksadk/studio/codex_builder.py +294 -16
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +51 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +200 -29
- ksadk/studio/compatibility_report.py +456 -0
- ksadk/studio/compiler.py +84 -15
- ksadk/studio/contracts.py +249 -4
- ksadk/studio/dsh_application.py +137 -0
- ksadk/studio/dsh_capability_service.py +1107 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +1075 -0
- ksadk/studio/event_store.py +54 -6
- ksadk/studio/framework_run.py +37 -4
- ksadk/studio/hosted_kernel.py +89 -14
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +2 -2
- ksadk/studio/operations.py +12 -2
- ksadk/studio/plugin_composition.py +468 -0
- ksadk/studio/plugin_kernel_adapter.py +28 -0
- ksadk/studio/plugin_runtime.py +831 -0
- ksadk/studio/resource_authority.py +637 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +149 -3
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_service.py +1144 -96
- ksadk/studio/runtime_source.py +24 -8
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +383 -0
- ksadk/studio/scheduler_service.py +214 -0
- ksadk/studio/service.py +1131 -95
- ksadk/studio/shared_web.py +610 -87
- ksadk/studio/soul.py +52 -0
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
- ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
- ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
- ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/validator.py +1 -1
- ksadk/studio/workspace.py +1 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/workspace_files/path_utils.py +41 -0
- agentengine_sdk_python-0.8.2.dist-info/RECORD +0 -778
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +0 -1
- ksadk/server/static/assets/channel-4cQHKtx1.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +0 -1
- ksadk/server/static/assets/index-8ipRcQ-M.js +0 -240
- ksadk/server/static/assets/index-ByFCqjlh.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-BLpcdrgW.css +0 -1
- ksadk/studio/static/assets/index-CYekR2Xv.js +0 -260
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,988 @@
|
|
|
1
|
+
"""Runtime-native Codex AgentProvider for the controlled PluginHost.
|
|
2
|
+
|
|
3
|
+
The provider only projects an immutable AgentBundle into the existing Codex
|
|
4
|
+
RuntimeAdapter/RuntimeExecutor conversation path. Canonical SessionEvents and
|
|
5
|
+
native thread continuation remain owned by that path; no provider-local event
|
|
6
|
+
stream or transcript is created here.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
16
|
+
from dataclasses import dataclass, replace
|
|
17
|
+
from pathlib import Path, PurePosixPath
|
|
18
|
+
from typing import Any
|
|
19
|
+
from urllib.parse import urlparse
|
|
20
|
+
|
|
21
|
+
from ksadk.plugins.bundle import ResolvedPluginBundle
|
|
22
|
+
from ksadk.plugins.contracts import CompositionProfile, PluginManifest
|
|
23
|
+
from ksadk.plugins.host import PluginExecutionContext, PluginHostError
|
|
24
|
+
from ksadk.plugins.providers.codex_native import codex_runtime_registry
|
|
25
|
+
from ksadk.plugins.providers.mcp_projection import (
|
|
26
|
+
MCPProjectionLease,
|
|
27
|
+
project_mcp_capabilities,
|
|
28
|
+
)
|
|
29
|
+
from ksadk.runtime import (
|
|
30
|
+
RuntimeExecutor,
|
|
31
|
+
RuntimeLaunchContext,
|
|
32
|
+
RuntimeServices,
|
|
33
|
+
)
|
|
34
|
+
from ksadk.runtime.conversation_execution import invoke_runtime_conversation_once
|
|
35
|
+
from ksadk.sessions import create_session_service
|
|
36
|
+
from ksadk.sessions.base import BaseSessionService
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class CodexProviderInventory:
|
|
41
|
+
provider: str
|
|
42
|
+
model: str
|
|
43
|
+
mcp_servers: tuple[str, ...]
|
|
44
|
+
skills: tuple[str, ...]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class CodexTurnRequest:
|
|
49
|
+
user_id: str
|
|
50
|
+
session_id: str | None
|
|
51
|
+
messages: tuple[Mapping[str, Any], ...]
|
|
52
|
+
request_metadata: Mapping[str, Any] | None = None
|
|
53
|
+
invocation_id: str | None = None
|
|
54
|
+
model: str | None = None
|
|
55
|
+
collaboration_mode: str | None = None
|
|
56
|
+
goal_objective: str | None = None
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def parse(cls, value: Any) -> "CodexTurnRequest":
|
|
60
|
+
if isinstance(value, cls):
|
|
61
|
+
return value
|
|
62
|
+
if not isinstance(value, Mapping):
|
|
63
|
+
raise PluginHostError("codex_input_invalid", "Codex input must be an object")
|
|
64
|
+
allowed_fields = {
|
|
65
|
+
"user_id",
|
|
66
|
+
"userId",
|
|
67
|
+
"session_id",
|
|
68
|
+
"sessionId",
|
|
69
|
+
"messages",
|
|
70
|
+
"input",
|
|
71
|
+
"request_metadata",
|
|
72
|
+
"requestMetadata",
|
|
73
|
+
"invocation_id",
|
|
74
|
+
"invocationId",
|
|
75
|
+
"model",
|
|
76
|
+
"collaboration_mode",
|
|
77
|
+
"collaborationMode",
|
|
78
|
+
"goal_objective",
|
|
79
|
+
"goalObjective",
|
|
80
|
+
}
|
|
81
|
+
unsupported = sorted(str(field) for field in value if field not in allowed_fields)
|
|
82
|
+
if unsupported:
|
|
83
|
+
raise PluginHostError(
|
|
84
|
+
"codex_input_unsupported",
|
|
85
|
+
"Codex input contains undeclared fields: " + ", ".join(unsupported),
|
|
86
|
+
)
|
|
87
|
+
_reject_aliased_duplicates(
|
|
88
|
+
value,
|
|
89
|
+
("user_id", "userId"),
|
|
90
|
+
("session_id", "sessionId"),
|
|
91
|
+
("request_metadata", "requestMetadata"),
|
|
92
|
+
("invocation_id", "invocationId"),
|
|
93
|
+
("collaboration_mode", "collaborationMode"),
|
|
94
|
+
("goal_objective", "goalObjective"),
|
|
95
|
+
)
|
|
96
|
+
if "messages" in value and "input" in value:
|
|
97
|
+
raise PluginHostError(
|
|
98
|
+
"codex_input_invalid",
|
|
99
|
+
"Codex input must use exactly one of messages or input",
|
|
100
|
+
)
|
|
101
|
+
user_id = str(value.get("user_id") or value.get("userId") or "").strip()
|
|
102
|
+
if not user_id:
|
|
103
|
+
raise PluginHostError("codex_input_invalid", "Codex input requires user_id")
|
|
104
|
+
raw_messages = value.get("messages")
|
|
105
|
+
if raw_messages is None and value.get("input") is not None:
|
|
106
|
+
raw_messages = ({"role": "user", "content": value.get("input")},)
|
|
107
|
+
if not isinstance(raw_messages, Sequence) or isinstance(raw_messages, (str, bytes)):
|
|
108
|
+
raise PluginHostError("codex_input_invalid", "Codex input requires messages")
|
|
109
|
+
messages: list[Mapping[str, Any]] = []
|
|
110
|
+
for index, message in enumerate(raw_messages):
|
|
111
|
+
if not isinstance(message, Mapping):
|
|
112
|
+
raise PluginHostError(
|
|
113
|
+
"codex_input_invalid", f"Codex messages[{index}] must be an object"
|
|
114
|
+
)
|
|
115
|
+
role = str(message.get("role") or "").strip()
|
|
116
|
+
if role not in {"system", "user", "assistant", "tool"}:
|
|
117
|
+
raise PluginHostError(
|
|
118
|
+
"codex_input_invalid",
|
|
119
|
+
f"Codex messages[{index}] has unsupported role {role!r}",
|
|
120
|
+
)
|
|
121
|
+
messages.append(dict(message))
|
|
122
|
+
if not messages or messages[-1].get("role") != "user":
|
|
123
|
+
raise PluginHostError("codex_input_invalid", "Codex turn must end with a user message")
|
|
124
|
+
metadata = value.get("request_metadata") or value.get("requestMetadata")
|
|
125
|
+
if metadata is not None and not isinstance(metadata, Mapping):
|
|
126
|
+
raise PluginHostError("codex_input_invalid", "request_metadata must be an object")
|
|
127
|
+
session_id = str(value.get("session_id") or value.get("sessionId") or "").strip()
|
|
128
|
+
invocation_id = str(value.get("invocation_id") or value.get("invocationId") or "").strip()
|
|
129
|
+
if len(invocation_id) > 256:
|
|
130
|
+
raise PluginHostError(
|
|
131
|
+
"codex_input_invalid", "Codex invocation_id exceeds 256 characters"
|
|
132
|
+
)
|
|
133
|
+
model = str(value.get("model") or "").strip()
|
|
134
|
+
if len(model) > 256:
|
|
135
|
+
raise PluginHostError("codex_input_invalid", "Codex model exceeds 256 characters")
|
|
136
|
+
collaboration_mode = (
|
|
137
|
+
str(value.get("collaboration_mode") or value.get("collaborationMode") or "")
|
|
138
|
+
.strip()
|
|
139
|
+
.lower()
|
|
140
|
+
)
|
|
141
|
+
if collaboration_mode and collaboration_mode not in {"default", "plan"}:
|
|
142
|
+
raise PluginHostError(
|
|
143
|
+
"codex_input_unsupported",
|
|
144
|
+
"Codex collaboration_mode must be default or plan",
|
|
145
|
+
)
|
|
146
|
+
goal_objective = str(
|
|
147
|
+
value.get("goal_objective") or value.get("goalObjective") or ""
|
|
148
|
+
).strip()
|
|
149
|
+
if len(goal_objective) > 4096:
|
|
150
|
+
raise PluginHostError(
|
|
151
|
+
"codex_input_invalid", "Codex goal_objective exceeds 4096 characters"
|
|
152
|
+
)
|
|
153
|
+
return cls(
|
|
154
|
+
user_id=user_id,
|
|
155
|
+
session_id=session_id or None,
|
|
156
|
+
messages=tuple(messages),
|
|
157
|
+
request_metadata=dict(metadata) if metadata is not None else None,
|
|
158
|
+
invocation_id=invocation_id or None,
|
|
159
|
+
model=model or None,
|
|
160
|
+
collaboration_mode=collaboration_mode or None,
|
|
161
|
+
goal_objective=goal_objective or None,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@dataclass(frozen=True)
|
|
166
|
+
class CodexTurnResult:
|
|
167
|
+
session_id: str
|
|
168
|
+
output_text: str
|
|
169
|
+
usage: Mapping[str, Any]
|
|
170
|
+
metadata: Mapping[str, Any]
|
|
171
|
+
inventory: CodexProviderInventory
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@dataclass(frozen=True)
|
|
175
|
+
class _CodexBundleConfig:
|
|
176
|
+
model: str
|
|
177
|
+
allowed_models: tuple[str, ...]
|
|
178
|
+
prompt: str
|
|
179
|
+
project_dir: Path
|
|
180
|
+
launch_config: Mapping[str, Any]
|
|
181
|
+
inventory: CodexProviderInventory
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class CodexAgentProviderRuntime:
|
|
185
|
+
"""ExecutableAgentProvider that preserves Codex native loop ownership."""
|
|
186
|
+
|
|
187
|
+
def __init__(
|
|
188
|
+
self,
|
|
189
|
+
*,
|
|
190
|
+
plugin_id: str,
|
|
191
|
+
session_service: BaseSessionService,
|
|
192
|
+
codex_client_factory: Callable[..., Any] | None,
|
|
193
|
+
credential_resolver: Any = None,
|
|
194
|
+
runtime_state_root: Path | None = None,
|
|
195
|
+
local_launch_resolver: Callable[..., RuntimeLaunchContext | None] | None = None,
|
|
196
|
+
runtime_executor: RuntimeExecutor | None = None,
|
|
197
|
+
) -> None:
|
|
198
|
+
self._plugin_id = plugin_id
|
|
199
|
+
self._session_service = session_service
|
|
200
|
+
self._client_factory = codex_client_factory
|
|
201
|
+
self._credentials = credential_resolver
|
|
202
|
+
self._runtime_state_root = runtime_state_root
|
|
203
|
+
self._local_launch_resolver = local_launch_resolver
|
|
204
|
+
self._runtime_executor = runtime_executor
|
|
205
|
+
self._ready = False
|
|
206
|
+
self._disposed = False
|
|
207
|
+
self._last_activation: CodexAgentActivation | None = None
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def disposed(self) -> bool:
|
|
211
|
+
return self._disposed
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def last_activation(self) -> "CodexAgentActivation | None":
|
|
215
|
+
return self._last_activation
|
|
216
|
+
|
|
217
|
+
async def start(self) -> None:
|
|
218
|
+
if self._disposed:
|
|
219
|
+
raise RuntimeError("Codex provider is disposed")
|
|
220
|
+
self._ready = True
|
|
221
|
+
|
|
222
|
+
async def health(self) -> bool:
|
|
223
|
+
return self._ready and not self._disposed
|
|
224
|
+
|
|
225
|
+
async def drain(self) -> None:
|
|
226
|
+
self._ready = False
|
|
227
|
+
|
|
228
|
+
async def dispose(self) -> None:
|
|
229
|
+
self._ready = False
|
|
230
|
+
self._disposed = True
|
|
231
|
+
|
|
232
|
+
async def prepare(
|
|
233
|
+
self,
|
|
234
|
+
bundle: ResolvedPluginBundle,
|
|
235
|
+
*,
|
|
236
|
+
capabilities: PluginExecutionContext,
|
|
237
|
+
) -> "CodexAgentActivation":
|
|
238
|
+
if not self._ready or self._disposed:
|
|
239
|
+
raise PluginHostError("codex_provider_unavailable", "Codex provider is not ready")
|
|
240
|
+
_reject_external_execution(bundle, capabilities)
|
|
241
|
+
projection = await project_mcp_capabilities(
|
|
242
|
+
capabilities,
|
|
243
|
+
bundle,
|
|
244
|
+
activation_only=True,
|
|
245
|
+
)
|
|
246
|
+
marker = bundle.composition.profile.agent_provider.config.get("studioManifestDigest")
|
|
247
|
+
launch = self._local_launch_resolver(bundle) if self._local_launch_resolver else None
|
|
248
|
+
if marker is not None and launch is None:
|
|
249
|
+
await projection.aclose()
|
|
250
|
+
raise PluginHostError("codex_local_build_required", "Local Codex Build is unavailable")
|
|
251
|
+
try:
|
|
252
|
+
config = _with_projected_mcp(
|
|
253
|
+
_resolve_bundle_config(
|
|
254
|
+
bundle,
|
|
255
|
+
plugin_id=self._plugin_id,
|
|
256
|
+
credential_resolver=self._credentials,
|
|
257
|
+
runtime_state_root=self._runtime_state_root,
|
|
258
|
+
local_launch=launch,
|
|
259
|
+
),
|
|
260
|
+
projection,
|
|
261
|
+
)
|
|
262
|
+
activation = CodexAgentActivation(
|
|
263
|
+
bundle=bundle,
|
|
264
|
+
config=config,
|
|
265
|
+
session_service=self._session_service,
|
|
266
|
+
codex_client_factory=self._client_factory,
|
|
267
|
+
mcp_projection=projection,
|
|
268
|
+
runtime_executor=self._runtime_executor,
|
|
269
|
+
)
|
|
270
|
+
except BaseException:
|
|
271
|
+
await projection.aclose()
|
|
272
|
+
raise
|
|
273
|
+
self._last_activation = activation
|
|
274
|
+
return activation
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class CodexAgentProviderFactory:
|
|
278
|
+
def __init__(
|
|
279
|
+
self,
|
|
280
|
+
*,
|
|
281
|
+
session_service: BaseSessionService | None = None,
|
|
282
|
+
codex_client_factory: Callable[..., Any] | None = None,
|
|
283
|
+
credential_resolver: Any = None,
|
|
284
|
+
) -> None:
|
|
285
|
+
self._session_service = session_service
|
|
286
|
+
self._client_factory = codex_client_factory
|
|
287
|
+
self._credentials = credential_resolver
|
|
288
|
+
self.runtime: CodexAgentProviderRuntime | None = None
|
|
289
|
+
|
|
290
|
+
async def stage(
|
|
291
|
+
self,
|
|
292
|
+
manifest: PluginManifest,
|
|
293
|
+
*,
|
|
294
|
+
profile: CompositionProfile,
|
|
295
|
+
services: Mapping[str, Any],
|
|
296
|
+
) -> CodexAgentProviderRuntime:
|
|
297
|
+
del profile
|
|
298
|
+
service = self._session_service or services.get("session_service")
|
|
299
|
+
if service is None:
|
|
300
|
+
service = create_session_service(backend="memory")
|
|
301
|
+
if not isinstance(service, BaseSessionService):
|
|
302
|
+
raise PluginHostError(
|
|
303
|
+
"codex_session_service_invalid",
|
|
304
|
+
"Codex provider requires a BaseSessionService",
|
|
305
|
+
)
|
|
306
|
+
client_factory = self._client_factory or services.get("codex_client_factory")
|
|
307
|
+
credentials = self._credentials or services.get("credential_resolver")
|
|
308
|
+
raw_state_root = services.get("runtime_state_root")
|
|
309
|
+
runtime_state_root = (
|
|
310
|
+
Path(str(raw_state_root)).expanduser().resolve() if raw_state_root is not None else None
|
|
311
|
+
)
|
|
312
|
+
runtime_executor = services.get("runtime_executor")
|
|
313
|
+
if runtime_executor is not None and not isinstance(runtime_executor, RuntimeExecutor):
|
|
314
|
+
raise PluginHostError(
|
|
315
|
+
"codex_runtime_executor_invalid",
|
|
316
|
+
"Codex provider requires a RuntimeExecutor",
|
|
317
|
+
)
|
|
318
|
+
self.runtime = CodexAgentProviderRuntime(
|
|
319
|
+
plugin_id=manifest.metadata.id,
|
|
320
|
+
session_service=service,
|
|
321
|
+
codex_client_factory=client_factory,
|
|
322
|
+
credential_resolver=credentials,
|
|
323
|
+
runtime_state_root=runtime_state_root,
|
|
324
|
+
local_launch_resolver=services.get("codex_local_launch_resolver"),
|
|
325
|
+
runtime_executor=runtime_executor,
|
|
326
|
+
)
|
|
327
|
+
return self.runtime
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class CodexAgentActivation:
|
|
331
|
+
def __init__(
|
|
332
|
+
self,
|
|
333
|
+
*,
|
|
334
|
+
bundle: ResolvedPluginBundle,
|
|
335
|
+
config: _CodexBundleConfig,
|
|
336
|
+
session_service: BaseSessionService,
|
|
337
|
+
codex_client_factory: Callable[..., Any] | None,
|
|
338
|
+
mcp_projection: MCPProjectionLease,
|
|
339
|
+
runtime_executor: RuntimeExecutor | None = None,
|
|
340
|
+
) -> None:
|
|
341
|
+
self._bundle = bundle
|
|
342
|
+
self._config = config
|
|
343
|
+
self._session_service = session_service
|
|
344
|
+
self._mcp_projection = mcp_projection
|
|
345
|
+
self._executor = runtime_executor or RuntimeExecutor(codex_runtime_registry())
|
|
346
|
+
self._launch_context = RuntimeLaunchContext(
|
|
347
|
+
runtime_type="codex",
|
|
348
|
+
project_dir=config.project_dir,
|
|
349
|
+
config=config.launch_config,
|
|
350
|
+
services=RuntimeServices(codex_client_factory=codex_client_factory),
|
|
351
|
+
)
|
|
352
|
+
self._ready = False
|
|
353
|
+
self._disposed = False
|
|
354
|
+
self._kernel_adapters: list[Any] = []
|
|
355
|
+
|
|
356
|
+
@property
|
|
357
|
+
def disposed(self) -> bool:
|
|
358
|
+
return self._disposed
|
|
359
|
+
|
|
360
|
+
async def start(self) -> None:
|
|
361
|
+
if self._disposed:
|
|
362
|
+
raise RuntimeError("Codex activation is disposed")
|
|
363
|
+
self._ready = True
|
|
364
|
+
|
|
365
|
+
async def health(self) -> bool:
|
|
366
|
+
return self._ready and not self._disposed
|
|
367
|
+
|
|
368
|
+
async def execute(self, request: Any) -> CodexTurnResult:
|
|
369
|
+
if not self._ready or self._disposed:
|
|
370
|
+
raise PluginHostError("codex_activation_unavailable", "Codex activation is not ready")
|
|
371
|
+
turn = CodexTurnRequest.parse(request)
|
|
372
|
+
selected_model = turn.model or self._config.model
|
|
373
|
+
if selected_model not in self._config.allowed_models:
|
|
374
|
+
raise PluginHostError(
|
|
375
|
+
"codex_model_unsupported",
|
|
376
|
+
f"Codex model {selected_model!r} is not declared by the immutable Bundle",
|
|
377
|
+
)
|
|
378
|
+
launch_context = self._turn_launch_context(turn)
|
|
379
|
+
preparation = await self._executor.prepare_start(launch_context)
|
|
380
|
+
session_id, result = await invoke_runtime_conversation_once(
|
|
381
|
+
executor=self._executor,
|
|
382
|
+
launch_context=launch_context,
|
|
383
|
+
agent_id=self._bundle.manifest.agent_id,
|
|
384
|
+
user_id=turn.user_id,
|
|
385
|
+
messages=[dict(item) for item in turn.messages],
|
|
386
|
+
session_id=turn.session_id,
|
|
387
|
+
model=selected_model,
|
|
388
|
+
instructions=self._config.prompt,
|
|
389
|
+
request_metadata=turn.request_metadata,
|
|
390
|
+
invocation_id=turn.invocation_id,
|
|
391
|
+
session_service_provider=lambda: self._session_service,
|
|
392
|
+
runtime_preparation=preparation,
|
|
393
|
+
)
|
|
394
|
+
return CodexTurnResult(
|
|
395
|
+
session_id=session_id,
|
|
396
|
+
output_text=str(result.get("output_text") or ""),
|
|
397
|
+
usage=dict(result.get("usage") or {}),
|
|
398
|
+
metadata=dict(result.get("metadata") or {}),
|
|
399
|
+
inventory=CodexProviderInventory(
|
|
400
|
+
provider=self._config.inventory.provider,
|
|
401
|
+
model=selected_model,
|
|
402
|
+
mcp_servers=self._config.inventory.mcp_servers,
|
|
403
|
+
skills=self._config.inventory.skills,
|
|
404
|
+
),
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
def runtime_adapter(self) -> Any:
|
|
408
|
+
"""Create one activation-owned native adapter for AgentKernel.
|
|
409
|
+
|
|
410
|
+
Each Kernel command receives a fresh App Server transport. Durable
|
|
411
|
+
SessionEvent metadata reconnects the next command to the same Codex
|
|
412
|
+
Thread, while retaining adapters here lets activation disposal close a
|
|
413
|
+
command that is still active during Profile drain.
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
if not self._ready or self._disposed:
|
|
417
|
+
raise PluginHostError("codex_activation_unavailable", "Codex activation is not ready")
|
|
418
|
+
adapter = self._executor.create_adapter(self._launch_context)
|
|
419
|
+
self._kernel_adapters.append(adapter)
|
|
420
|
+
return adapter
|
|
421
|
+
|
|
422
|
+
def _turn_launch_context(self, turn: CodexTurnRequest) -> RuntimeLaunchContext:
|
|
423
|
+
config = dict(self._config.launch_config)
|
|
424
|
+
if turn.model:
|
|
425
|
+
config["model"] = turn.model
|
|
426
|
+
if turn.collaboration_mode:
|
|
427
|
+
config["collaboration_mode"] = turn.collaboration_mode
|
|
428
|
+
if turn.goal_objective:
|
|
429
|
+
config["goal_objective"] = turn.goal_objective
|
|
430
|
+
return RuntimeLaunchContext(
|
|
431
|
+
runtime_type=self._launch_context.runtime_type,
|
|
432
|
+
project_dir=self._launch_context.project_dir,
|
|
433
|
+
config=config,
|
|
434
|
+
services=self._launch_context.services,
|
|
435
|
+
deployment_mode=self._launch_context.deployment_mode,
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
async def drain(self) -> None:
|
|
439
|
+
self._ready = False
|
|
440
|
+
|
|
441
|
+
async def abort(self) -> None:
|
|
442
|
+
await self._mcp_projection.aclose()
|
|
443
|
+
|
|
444
|
+
async def dispose(self) -> None:
|
|
445
|
+
self._ready = False
|
|
446
|
+
first_error: BaseException | None = None
|
|
447
|
+
for adapter in reversed(self._kernel_adapters):
|
|
448
|
+
close_all = getattr(adapter, "close_all", None)
|
|
449
|
+
if not callable(close_all):
|
|
450
|
+
continue
|
|
451
|
+
try:
|
|
452
|
+
await close_all()
|
|
453
|
+
except BaseException as error: # cleanup must continue
|
|
454
|
+
if first_error is None:
|
|
455
|
+
first_error = error
|
|
456
|
+
self._kernel_adapters.clear()
|
|
457
|
+
try:
|
|
458
|
+
await self._executor.close_all()
|
|
459
|
+
except BaseException as error: # cleanup must continue
|
|
460
|
+
if first_error is None:
|
|
461
|
+
first_error = error
|
|
462
|
+
try:
|
|
463
|
+
await self._mcp_projection.aclose()
|
|
464
|
+
except BaseException as error: # security cleanup must still finish
|
|
465
|
+
if first_error is None:
|
|
466
|
+
first_error = error
|
|
467
|
+
self._disposed = True
|
|
468
|
+
if first_error is not None:
|
|
469
|
+
raise first_error
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _reject_aliased_duplicates(
|
|
473
|
+
value: Mapping[str, Any],
|
|
474
|
+
*aliases: tuple[str, str],
|
|
475
|
+
) -> None:
|
|
476
|
+
for snake_case, camel_case in aliases:
|
|
477
|
+
if snake_case in value and camel_case in value:
|
|
478
|
+
raise PluginHostError(
|
|
479
|
+
"codex_input_invalid",
|
|
480
|
+
f"Codex input cannot contain both {snake_case} and {camel_case}",
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def _with_projected_mcp(
|
|
485
|
+
config: _CodexBundleConfig,
|
|
486
|
+
projection: MCPProjectionLease,
|
|
487
|
+
) -> _CodexBundleConfig:
|
|
488
|
+
"""Add activation-scoped connectors to Codex's generic launch config."""
|
|
489
|
+
|
|
490
|
+
launch = dict(config.launch_config)
|
|
491
|
+
servers = [dict(item) for item in launch.get("mcp_servers") or []]
|
|
492
|
+
environment = dict(launch.get("env") or {})
|
|
493
|
+
names = {str(item.get("name") or "") for item in servers}
|
|
494
|
+
for spec in projection.specs:
|
|
495
|
+
parsed = urlparse(spec.url)
|
|
496
|
+
if (
|
|
497
|
+
parsed.scheme not in {"http", "https"}
|
|
498
|
+
or not parsed.hostname
|
|
499
|
+
or parsed.username is not None
|
|
500
|
+
or parsed.password is not None
|
|
501
|
+
or parsed.fragment
|
|
502
|
+
):
|
|
503
|
+
raise PluginHostError(
|
|
504
|
+
"codex_mcp_projection_invalid",
|
|
505
|
+
f"projected MCP connector {spec.name!r} has an invalid endpoint",
|
|
506
|
+
)
|
|
507
|
+
if spec.name in names:
|
|
508
|
+
raise PluginHostError(
|
|
509
|
+
"codex_mcp_projection_ambiguous",
|
|
510
|
+
f"projected MCP connector {spec.name!r} conflicts with the Bundle",
|
|
511
|
+
)
|
|
512
|
+
server: dict[str, Any] = {
|
|
513
|
+
"name": spec.name,
|
|
514
|
+
"transport": "http",
|
|
515
|
+
"url": spec.url,
|
|
516
|
+
}
|
|
517
|
+
if spec.api_key is not None:
|
|
518
|
+
suffix = hashlib.sha256(spec.name.encode()).hexdigest()[:16].upper()
|
|
519
|
+
env_key = f"KSADK_ACTIVATION_MCP_TOKEN_{suffix}"
|
|
520
|
+
if env_key in environment:
|
|
521
|
+
raise PluginHostError(
|
|
522
|
+
"codex_mcp_projection_ambiguous",
|
|
523
|
+
f"projected MCP connector {spec.name!r} has an environment collision",
|
|
524
|
+
)
|
|
525
|
+
environment[env_key] = spec.api_key
|
|
526
|
+
server["env_key"] = env_key
|
|
527
|
+
servers.append(server)
|
|
528
|
+
names.add(spec.name)
|
|
529
|
+
launch["mcp_servers"] = servers
|
|
530
|
+
launch["env"] = environment
|
|
531
|
+
inventory = replace(
|
|
532
|
+
config.inventory,
|
|
533
|
+
mcp_servers=tuple(item["name"] for item in servers),
|
|
534
|
+
)
|
|
535
|
+
return replace(config, launch_config=launch, inventory=inventory)
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
def _reject_external_execution(
|
|
539
|
+
bundle: ResolvedPluginBundle,
|
|
540
|
+
capabilities: PluginExecutionContext,
|
|
541
|
+
) -> None:
|
|
542
|
+
del capabilities
|
|
543
|
+
profile_config = bundle.composition.profile.agent_provider.config
|
|
544
|
+
allowed_config = {
|
|
545
|
+
"runtimeType", "runtimeVersion", "studioManifestDigest", "studioBuildFingerprint",
|
|
546
|
+
}
|
|
547
|
+
unsupported_config = sorted(set(profile_config) - allowed_config)
|
|
548
|
+
execution = bundle.resolved_agent_spec.get("execution")
|
|
549
|
+
strategy = (
|
|
550
|
+
str(execution.get("strategy") or "direct").strip()
|
|
551
|
+
if isinstance(execution, Mapping)
|
|
552
|
+
else "direct"
|
|
553
|
+
)
|
|
554
|
+
if unsupported_config:
|
|
555
|
+
raise PluginHostError(
|
|
556
|
+
"codex_provider_config_unsupported",
|
|
557
|
+
"Codex AgentProvider received unsupported configuration: "
|
|
558
|
+
+ ", ".join(unsupported_config),
|
|
559
|
+
)
|
|
560
|
+
if strategy != "direct":
|
|
561
|
+
raise PluginHostError(
|
|
562
|
+
"codex_external_execution_unsupported",
|
|
563
|
+
f"Codex AgentProvider owns its execution semantics and does not support {strategy!r}",
|
|
564
|
+
)
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def _resolve_bundle_config(
|
|
568
|
+
bundle: ResolvedPluginBundle,
|
|
569
|
+
*,
|
|
570
|
+
plugin_id: str,
|
|
571
|
+
credential_resolver: Any,
|
|
572
|
+
runtime_state_root: Path | None,
|
|
573
|
+
local_launch: RuntimeLaunchContext | None = None,
|
|
574
|
+
) -> _CodexBundleConfig:
|
|
575
|
+
spec = bundle.resolved_agent_spec
|
|
576
|
+
raw_model = spec.get("model")
|
|
577
|
+
if not isinstance(raw_model, Mapping):
|
|
578
|
+
raise PluginHostError(
|
|
579
|
+
"codex_bundle_model_invalid", "Bundle resolved model must be an object"
|
|
580
|
+
)
|
|
581
|
+
model = str(raw_model.get("model") or "").strip()
|
|
582
|
+
if not model:
|
|
583
|
+
raise PluginHostError(
|
|
584
|
+
"codex_bundle_model_missing", "Bundle resolved Agent spec has no model"
|
|
585
|
+
)
|
|
586
|
+
allowed_models = _resolve_allowed_models(bundle, default_model=model)
|
|
587
|
+
if local_launch is not None:
|
|
588
|
+
# The trusted host verified the original Codex manifest referenced by
|
|
589
|
+
# this Bundle. YAML-only model names may have no Catalog profile IDs.
|
|
590
|
+
model = str(local_launch.config["model"])
|
|
591
|
+
allowed_models = tuple(local_launch.config["models"])
|
|
592
|
+
if not allowed_models or model not in allowed_models:
|
|
593
|
+
raise PluginHostError("codex_bundle_model_inventory_invalid", "Invalid local models")
|
|
594
|
+
instructions = spec.get("instructions")
|
|
595
|
+
if not isinstance(instructions, Mapping):
|
|
596
|
+
raise PluginHostError(
|
|
597
|
+
"codex_bundle_prompt_invalid", "Bundle instructions must be an object"
|
|
598
|
+
)
|
|
599
|
+
prompt = "\n\n".join(
|
|
600
|
+
part
|
|
601
|
+
for part in (
|
|
602
|
+
str(instructions.get("system") or "").strip(),
|
|
603
|
+
str(instructions.get("task") or "").strip(),
|
|
604
|
+
)
|
|
605
|
+
if part
|
|
606
|
+
)
|
|
607
|
+
if not prompt:
|
|
608
|
+
raise PluginHostError(
|
|
609
|
+
"codex_bundle_prompt_missing", "Bundle resolved Agent spec has no instructions"
|
|
610
|
+
)
|
|
611
|
+
capabilities = spec.get("capabilities")
|
|
612
|
+
if not isinstance(capabilities, Mapping):
|
|
613
|
+
raise PluginHostError(
|
|
614
|
+
"codex_bundle_capabilities_invalid", "Bundle capabilities must be an object"
|
|
615
|
+
)
|
|
616
|
+
if capabilities.get("tools"):
|
|
617
|
+
raise PluginHostError(
|
|
618
|
+
"codex_tools_unsupported", "Codex only accepts its native tools, MCP, and Skills"
|
|
619
|
+
)
|
|
620
|
+
skills = _resolve_skills(bundle.root, capabilities.get("skills"))
|
|
621
|
+
mcp_servers, mcp_env = _resolve_mcp(
|
|
622
|
+
capabilities.get("mcpServers") or capabilities.get("mcp_servers"),
|
|
623
|
+
credential_resolver=credential_resolver,
|
|
624
|
+
)
|
|
625
|
+
# Local Studio has already resolved its original Codex credential policy.
|
|
626
|
+
# A second, stricter generic Bundle lookup would reject native-auth builds
|
|
627
|
+
# before their approved launch environment can be applied below.
|
|
628
|
+
model_env = {} if local_launch is not None else _resolve_model_env(
|
|
629
|
+
raw_model,
|
|
630
|
+
model=model,
|
|
631
|
+
credential_resolver=credential_resolver,
|
|
632
|
+
)
|
|
633
|
+
execution = spec.get("execution")
|
|
634
|
+
execution = execution if isinstance(execution, Mapping) else {}
|
|
635
|
+
project_dir = (
|
|
636
|
+
local_launch.project_dir if local_launch is not None
|
|
637
|
+
else _resolve_runtime_workspace(bundle, runtime_state_root=runtime_state_root)
|
|
638
|
+
)
|
|
639
|
+
launch_config: dict[str, Any] = {
|
|
640
|
+
"model": model,
|
|
641
|
+
"models": list(allowed_models),
|
|
642
|
+
"prompt": str(instructions.get("system") or "").strip(),
|
|
643
|
+
"task_prompt": str(instructions.get("task") or "").strip(),
|
|
644
|
+
# Match Studio's workspace default. A missing execution stanza should
|
|
645
|
+
# still allow ordinary project work while auto-reviewing risky actions;
|
|
646
|
+
# read-only remains available when the Bundle declares it explicitly.
|
|
647
|
+
"sandbox": str(execution.get("sandbox") or "workspace_write_auto"),
|
|
648
|
+
"approval_mode": str(execution.get("approvalMode") or execution.get("approval_mode") or ""),
|
|
649
|
+
"turn_timeout_seconds": int(
|
|
650
|
+
execution.get("timeoutSeconds") or execution.get("timeout_seconds") or 120
|
|
651
|
+
),
|
|
652
|
+
"mcp_servers": mcp_servers,
|
|
653
|
+
"skills": skills,
|
|
654
|
+
"env": {**mcp_env, **model_env},
|
|
655
|
+
}
|
|
656
|
+
if local_launch is not None:
|
|
657
|
+
launch_config.update(local_launch.config)
|
|
658
|
+
# Local launch compatibility never replaces immutable Bundle Skill bytes.
|
|
659
|
+
launch_config["skills"] = skills
|
|
660
|
+
launch_config["enforce_bound_skills"] = True
|
|
661
|
+
return _CodexBundleConfig(
|
|
662
|
+
model=model,
|
|
663
|
+
allowed_models=allowed_models,
|
|
664
|
+
prompt=prompt,
|
|
665
|
+
project_dir=project_dir,
|
|
666
|
+
launch_config=launch_config,
|
|
667
|
+
inventory=CodexProviderInventory(
|
|
668
|
+
provider=plugin_id,
|
|
669
|
+
model=model,
|
|
670
|
+
mcp_servers=tuple(item["name"] for item in mcp_servers),
|
|
671
|
+
skills=tuple(item["name"] for item in skills),
|
|
672
|
+
),
|
|
673
|
+
)
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def _resolve_runtime_workspace(
|
|
677
|
+
bundle: ResolvedPluginBundle,
|
|
678
|
+
*,
|
|
679
|
+
runtime_state_root: Path | None,
|
|
680
|
+
) -> Path:
|
|
681
|
+
"""Keep Codex state and generated files outside the immutable Bundle.
|
|
682
|
+
|
|
683
|
+
A Bundle is integrity-checked again whenever a session opens. Using it as
|
|
684
|
+
Codex's working directory lets CODEX_HOME and ordinary workspace writes add
|
|
685
|
+
undeclared files, which makes the next open look like bundle corruption.
|
|
686
|
+
"""
|
|
687
|
+
|
|
688
|
+
state_root = (
|
|
689
|
+
runtime_state_root
|
|
690
|
+
if runtime_state_root is not None
|
|
691
|
+
else bundle.root.parent / ".runtime-state"
|
|
692
|
+
).resolve()
|
|
693
|
+
safe_agent_id = (
|
|
694
|
+
"".join(
|
|
695
|
+
character if character.isalnum() or character in {"-", "_", "."} else "-"
|
|
696
|
+
for character in bundle.manifest.agent_id
|
|
697
|
+
).strip("-.")
|
|
698
|
+
or "agent"
|
|
699
|
+
)
|
|
700
|
+
workspace = (state_root / "codex-workspaces" / safe_agent_id).resolve()
|
|
701
|
+
try:
|
|
702
|
+
workspace.relative_to(bundle.root)
|
|
703
|
+
except ValueError:
|
|
704
|
+
pass
|
|
705
|
+
else:
|
|
706
|
+
raise PluginHostError(
|
|
707
|
+
"codex_runtime_state_invalid",
|
|
708
|
+
"Codex runtime state must be outside the immutable Bundle",
|
|
709
|
+
)
|
|
710
|
+
try:
|
|
711
|
+
workspace.mkdir(parents=True, exist_ok=True)
|
|
712
|
+
except OSError as error:
|
|
713
|
+
raise PluginHostError(
|
|
714
|
+
"codex_runtime_state_unavailable",
|
|
715
|
+
"Codex runtime workspace could not be initialized",
|
|
716
|
+
) from error
|
|
717
|
+
return workspace
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def _resolve_model_env(
|
|
721
|
+
value: Mapping[str, Any],
|
|
722
|
+
*,
|
|
723
|
+
model: str,
|
|
724
|
+
credential_resolver: Any,
|
|
725
|
+
) -> dict[str, str]:
|
|
726
|
+
"""Resolve the Bundle-pinned model connection for the Codex subprocess."""
|
|
727
|
+
|
|
728
|
+
endpoint = str(
|
|
729
|
+
value.get("endpointUrl")
|
|
730
|
+
or value.get("endpoint_url")
|
|
731
|
+
or value.get("baseUrl")
|
|
732
|
+
or value.get("base_url")
|
|
733
|
+
or ""
|
|
734
|
+
).strip()
|
|
735
|
+
for suffix in ("/chat/completions", "/responses"):
|
|
736
|
+
if endpoint.endswith(suffix):
|
|
737
|
+
endpoint = endpoint[: -len(suffix)]
|
|
738
|
+
break
|
|
739
|
+
|
|
740
|
+
env = {"OPENAI_MODEL_NAME": model}
|
|
741
|
+
if endpoint:
|
|
742
|
+
env["OPENAI_BASE_URL"] = endpoint.rstrip("/")
|
|
743
|
+
env["OPENAI_API_BASE"] = endpoint.rstrip("/")
|
|
744
|
+
|
|
745
|
+
wire_api = str(value.get("wireApi") or value.get("wire_api") or "").strip().lower()
|
|
746
|
+
host = (urlparse(endpoint).hostname or "").lower() if endpoint else ""
|
|
747
|
+
if "KSADK_CODEX_USE_PROXY" not in os.environ and (
|
|
748
|
+
wire_api == "chat" or host == "kspmas.ksyun.com" or host.endswith(".kspmas.ksyun.com")
|
|
749
|
+
):
|
|
750
|
+
# Codex speaks Responses natively. Known chat-only gateways need the
|
|
751
|
+
# local protocol bridge and must not spend the first turn probing an
|
|
752
|
+
# endpoint whose protocol is already declared by the immutable Bundle.
|
|
753
|
+
env["KSADK_CODEX_USE_PROXY"] = "1"
|
|
754
|
+
|
|
755
|
+
reference = str(value.get("credentialRef") or value.get("credential_ref") or "").strip()
|
|
756
|
+
if not reference:
|
|
757
|
+
return env
|
|
758
|
+
if credential_resolver is None:
|
|
759
|
+
raise PluginHostError(
|
|
760
|
+
"codex_model_credential_unavailable",
|
|
761
|
+
"Codex Bundle model requires a credential resolver",
|
|
762
|
+
)
|
|
763
|
+
try:
|
|
764
|
+
credential = (
|
|
765
|
+
credential_resolver.resolve(reference)
|
|
766
|
+
if hasattr(credential_resolver, "resolve")
|
|
767
|
+
else credential_resolver(reference)
|
|
768
|
+
)
|
|
769
|
+
except Exception as error:
|
|
770
|
+
raise PluginHostError(
|
|
771
|
+
"codex_model_credential_unavailable",
|
|
772
|
+
"Codex Bundle model credential could not be resolved",
|
|
773
|
+
) from error
|
|
774
|
+
if not str(credential):
|
|
775
|
+
raise PluginHostError(
|
|
776
|
+
"codex_model_credential_unavailable",
|
|
777
|
+
"Codex Bundle model credential is empty",
|
|
778
|
+
)
|
|
779
|
+
# Model connection keys are reserved for the model. An MCP binding may use
|
|
780
|
+
# arbitrary environment names, but it must not replace the model gateway's
|
|
781
|
+
# credential or endpoint in the child process.
|
|
782
|
+
env["OPENAI_API_KEY"] = str(credential)
|
|
783
|
+
return env
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
def _resolve_allowed_models(
|
|
787
|
+
bundle: ResolvedPluginBundle,
|
|
788
|
+
*,
|
|
789
|
+
default_model: str,
|
|
790
|
+
) -> tuple[str, ...]:
|
|
791
|
+
"""Read the immutable model allowlist produced by the Bundle compiler.
|
|
792
|
+
|
|
793
|
+
Older Bundle fixtures without ``runtime-lock.json`` remain pinned to their
|
|
794
|
+
resolved default. A declared lock is already digest-verified by
|
|
795
|
+
``PluginBundleResolver``; malformed model inventory must fail activation
|
|
796
|
+
instead of silently widening run-level model selection.
|
|
797
|
+
"""
|
|
798
|
+
|
|
799
|
+
if not any(entry.path == "runtime-lock.json" for entry in bundle.manifest.files):
|
|
800
|
+
return (default_model,)
|
|
801
|
+
try:
|
|
802
|
+
payload = json.loads((bundle.root / "runtime-lock.json").read_text(encoding="utf-8"))
|
|
803
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as error:
|
|
804
|
+
raise PluginHostError(
|
|
805
|
+
"codex_bundle_model_inventory_invalid",
|
|
806
|
+
"Bundle runtime-lock.json is not a valid model inventory",
|
|
807
|
+
) from error
|
|
808
|
+
if not isinstance(payload, Mapping):
|
|
809
|
+
raise PluginHostError(
|
|
810
|
+
"codex_bundle_model_inventory_invalid",
|
|
811
|
+
"Bundle runtime-lock.json must be an object",
|
|
812
|
+
)
|
|
813
|
+
raw_models = payload.get("models")
|
|
814
|
+
if not isinstance(raw_models, Sequence) or isinstance(raw_models, (str, bytes)):
|
|
815
|
+
raise PluginHostError(
|
|
816
|
+
"codex_bundle_model_inventory_invalid",
|
|
817
|
+
"Bundle runtime-lock.json must declare models as a list",
|
|
818
|
+
)
|
|
819
|
+
models = tuple(dict.fromkeys(str(item).strip() for item in raw_models if str(item).strip()))
|
|
820
|
+
if not models or default_model not in models:
|
|
821
|
+
raise PluginHostError(
|
|
822
|
+
"codex_bundle_model_inventory_invalid",
|
|
823
|
+
"Bundle model inventory must include its resolved default model",
|
|
824
|
+
)
|
|
825
|
+
return models
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
def _resolve_skills(root: Path, value: Any) -> list[dict[str, str]]:
|
|
829
|
+
if value is None:
|
|
830
|
+
return []
|
|
831
|
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes)):
|
|
832
|
+
raise PluginHostError("codex_skill_invalid", "Bundle Skills must be a list")
|
|
833
|
+
resolved: list[dict[str, str]] = []
|
|
834
|
+
seen: set[str] = set()
|
|
835
|
+
for index, item in enumerate(value):
|
|
836
|
+
if not isinstance(item, Mapping):
|
|
837
|
+
raise PluginHostError(
|
|
838
|
+
"codex_skill_invalid", f"Bundle Skills[{index}] must be an object"
|
|
839
|
+
)
|
|
840
|
+
name = str(item.get("name") or "").strip()
|
|
841
|
+
relative = PurePosixPath(str(item.get("bundlePath") or item.get("bundle_path") or ""))
|
|
842
|
+
if not name or not relative.parts or relative.is_absolute() or ".." in relative.parts:
|
|
843
|
+
raise PluginHostError(
|
|
844
|
+
"codex_skill_invalid", f"Bundle Skills[{index}] has an invalid native path"
|
|
845
|
+
)
|
|
846
|
+
path = (root / Path(*relative.parts)).resolve()
|
|
847
|
+
try:
|
|
848
|
+
path.relative_to(root)
|
|
849
|
+
except ValueError as error:
|
|
850
|
+
raise PluginHostError(
|
|
851
|
+
"codex_skill_invalid", f"Bundle Skill {name!r} escapes the Bundle root"
|
|
852
|
+
) from error
|
|
853
|
+
if not (path / "SKILL.md").is_file():
|
|
854
|
+
raise PluginHostError("codex_skill_missing", f"Bundle Skill {name!r} has no SKILL.md")
|
|
855
|
+
if name in seen:
|
|
856
|
+
raise PluginHostError("codex_skill_invalid", f"duplicate Bundle Skill {name!r}")
|
|
857
|
+
seen.add(name)
|
|
858
|
+
# Codex's native SkillInput expects the concrete SKILL.md source, not
|
|
859
|
+
# its containing directory. A directory is accepted by the Python
|
|
860
|
+
# model but silently omitted by the real App Server turn projection.
|
|
861
|
+
resolved.append({"name": name, "path": str(path / "SKILL.md")})
|
|
862
|
+
return resolved
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
def _resolve_mcp(
|
|
866
|
+
value: Any,
|
|
867
|
+
*,
|
|
868
|
+
credential_resolver: Any,
|
|
869
|
+
) -> tuple[list[dict[str, Any]], dict[str, str]]:
|
|
870
|
+
if value is None:
|
|
871
|
+
return [], {}
|
|
872
|
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes)):
|
|
873
|
+
raise PluginHostError("codex_mcp_invalid", "Bundle MCP servers must be a list")
|
|
874
|
+
servers: list[dict[str, Any]] = []
|
|
875
|
+
env: dict[str, str] = {}
|
|
876
|
+
seen: set[str] = set()
|
|
877
|
+
for index, item in enumerate(value):
|
|
878
|
+
if not isinstance(item, Mapping):
|
|
879
|
+
raise PluginHostError(
|
|
880
|
+
"codex_mcp_invalid", f"Bundle MCP servers[{index}] must be an object"
|
|
881
|
+
)
|
|
882
|
+
name = str(item.get("name") or "").strip()
|
|
883
|
+
transport = str(item.get("transport") or "").strip().lower()
|
|
884
|
+
url = str(item.get("endpointUrl") or item.get("endpoint_url") or "").strip()
|
|
885
|
+
if not name or name in seen:
|
|
886
|
+
raise PluginHostError("codex_mcp_invalid", "Bundle MCP names must be unique")
|
|
887
|
+
env_refs = item.get("envRefs") or item.get("env_refs") or {}
|
|
888
|
+
if not isinstance(env_refs, Mapping):
|
|
889
|
+
raise PluginHostError(
|
|
890
|
+
"codex_mcp_invalid", f"Bundle MCP {name!r} envRefs must be an object"
|
|
891
|
+
)
|
|
892
|
+
if transport in {"http", "sse"} and len(env_refs) > 1:
|
|
893
|
+
raise PluginHostError(
|
|
894
|
+
"codex_mcp_credentials_unsupported",
|
|
895
|
+
f"Codex HTTP MCP {name!r} accepts at most one bearer credential",
|
|
896
|
+
)
|
|
897
|
+
if transport == "stdio":
|
|
898
|
+
command = str(item.get("command") or "").strip()
|
|
899
|
+
raw_args = item.get("args") or []
|
|
900
|
+
if (
|
|
901
|
+
not command
|
|
902
|
+
or not isinstance(raw_args, Sequence)
|
|
903
|
+
or isinstance(raw_args, (str, bytes))
|
|
904
|
+
or len(raw_args) > 128
|
|
905
|
+
or any(
|
|
906
|
+
not isinstance(argument, str) or len(argument) > 4096 or "\x00" in argument
|
|
907
|
+
for argument in raw_args
|
|
908
|
+
)
|
|
909
|
+
):
|
|
910
|
+
raise PluginHostError(
|
|
911
|
+
"codex_mcp_invalid",
|
|
912
|
+
f"Codex Bundle stdio MCP {name!r} has an invalid command or args",
|
|
913
|
+
)
|
|
914
|
+
executable = Path(command).name.casefold()
|
|
915
|
+
if executable in {"sh", "bash", "zsh", "cmd", "cmd.exe", "powershell", "pwsh"}:
|
|
916
|
+
raise PluginHostError(
|
|
917
|
+
"codex_mcp_command_denied",
|
|
918
|
+
f"Codex Bundle stdio MCP {name!r} cannot launch a shell",
|
|
919
|
+
)
|
|
920
|
+
if any(argument in {"-c", "-e", "--eval"} for argument in raw_args):
|
|
921
|
+
raise PluginHostError(
|
|
922
|
+
"codex_mcp_command_denied",
|
|
923
|
+
f"Codex Bundle stdio MCP {name!r} cannot use inline evaluation",
|
|
924
|
+
)
|
|
925
|
+
server: dict[str, Any] = {
|
|
926
|
+
"name": name,
|
|
927
|
+
"transport": "stdio",
|
|
928
|
+
"command": command,
|
|
929
|
+
"args": list(raw_args),
|
|
930
|
+
}
|
|
931
|
+
elif transport in {"http", "sse"} and url:
|
|
932
|
+
server = {"name": name, "transport": transport, "url": url}
|
|
933
|
+
else:
|
|
934
|
+
raise PluginHostError(
|
|
935
|
+
"codex_mcp_transport_unsupported",
|
|
936
|
+
f"Codex Bundle MCP {name!r} requires stdio or an http/sse endpoint",
|
|
937
|
+
)
|
|
938
|
+
forwarded_env: dict[str, str] = {}
|
|
939
|
+
for env_name, reference in env_refs.items():
|
|
940
|
+
env_key = str(env_name).strip()
|
|
941
|
+
ref = str(reference).strip()
|
|
942
|
+
if not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", env_key) or not ref.startswith(
|
|
943
|
+
("env://", "secret://", "credential://", "vault://")
|
|
944
|
+
):
|
|
945
|
+
raise PluginHostError(
|
|
946
|
+
"codex_mcp_credential_invalid",
|
|
947
|
+
f"Bundle MCP {name!r} contains an invalid credential reference",
|
|
948
|
+
)
|
|
949
|
+
if credential_resolver is None:
|
|
950
|
+
raise PluginHostError(
|
|
951
|
+
"codex_mcp_credential_unavailable",
|
|
952
|
+
f"Bundle MCP {name!r} requires a credential resolver",
|
|
953
|
+
)
|
|
954
|
+
try:
|
|
955
|
+
value = (
|
|
956
|
+
credential_resolver.resolve(ref)
|
|
957
|
+
if hasattr(credential_resolver, "resolve")
|
|
958
|
+
else credential_resolver(ref)
|
|
959
|
+
)
|
|
960
|
+
except Exception as error:
|
|
961
|
+
raise PluginHostError(
|
|
962
|
+
"codex_mcp_credential_unavailable",
|
|
963
|
+
f"Bundle MCP {name!r} credential could not be resolved",
|
|
964
|
+
) from error
|
|
965
|
+
if not str(value):
|
|
966
|
+
raise PluginHostError(
|
|
967
|
+
"codex_mcp_credential_unavailable",
|
|
968
|
+
f"Bundle MCP {name!r} credential is empty",
|
|
969
|
+
)
|
|
970
|
+
env[env_key] = str(value)
|
|
971
|
+
if transport == "stdio":
|
|
972
|
+
forwarded_env[env_key] = ref
|
|
973
|
+
else:
|
|
974
|
+
server["env_key"] = env_key
|
|
975
|
+
if forwarded_env:
|
|
976
|
+
server["env_refs"] = forwarded_env
|
|
977
|
+
servers.append(server)
|
|
978
|
+
seen.add(name)
|
|
979
|
+
return servers, env
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
__all__ = [
|
|
983
|
+
"CodexAgentProviderFactory",
|
|
984
|
+
"CodexAgentProviderRuntime",
|
|
985
|
+
"CodexProviderInventory",
|
|
986
|
+
"CodexTurnRequest",
|
|
987
|
+
"CodexTurnResult",
|
|
988
|
+
]
|