agentengine-sdk-python 0.8.2__py3-none-any.whl → 0.8.3__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.3.dist-info}/METADATA +18 -25
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/RECORD +224 -169
- ksadk/_build_provenance.json +1 -0
- ksadk/agui/_agent_helpers.py +4 -0
- ksadk/api/client.py +3 -0
- ksadk/builders/managed_runtime_builder.py +3 -0
- ksadk/cli/__init__.py +6 -0
- ksadk/cli/cmd_plugin.py +657 -0
- ksadk/codex/runtime.py +50 -8
- ksadk/configs/env_registry.py +31 -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 +19 -1
- ksadk/conversations/projector.py +616 -0
- ksadk/conversations/reducer.py +98 -0
- ksadk/events/_v1_compat/projection.py +2 -0
- ksadk/events/adapters/codex.py +190 -0
- ksadk/harness/__init__.py +45 -35
- ksadk/harness/runtime.py +60 -1
- ksadk/kernel/contract_fingerprints.py +5 -4
- ksadk/kernel/contracts.py +8 -0
- ksadk/kernel/control.py +1 -0
- ksadk/kernel/ingress.py +21 -0
- ksadk/kernel/memory_store.py +1 -0
- ksadk/kernel/postgres_store.py +1 -0
- ksadk/kernel/sqlite_store.py +1 -0
- ksadk/kernel/worker.py +11 -0
- ksadk/memory/providers/local_sqlite.py +7 -0
- ksadk/plugins/__init__.py +167 -0
- ksadk/plugins/bridges/__init__.py +45 -0
- ksadk/plugins/bridges/codex.py +552 -0
- ksadk/plugins/bridges/dsh.py +1116 -0
- ksadk/plugins/builtins.py +747 -0
- ksadk/plugins/bundle.py +246 -0
- ksadk/plugins/bundle_security.py +167 -0
- ksadk/plugins/composition.py +529 -0
- ksadk/plugins/context_contributor.py +437 -0
- ksadk/plugins/contracts.py +451 -0
- ksadk/plugins/dsh_toolchain.py +935 -0
- ksadk/plugins/ecosystem_bridge.py +1105 -0
- ksadk/plugins/ecosystem_probe.py +191 -0
- ksadk/plugins/host.py +724 -0
- ksadk/plugins/providers/__init__.py +85 -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-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 +722 -0
- ksadk/plugins/providers/codex_dsh.py +83 -0
- ksadk/plugins/providers/dsh.py +951 -0
- ksadk/plugins/providers/dsh_descriptor_host.py +226 -0
- ksadk/plugins/providers/harness.py +627 -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/shipped_dsh.py +370 -0
- ksadk/plugins/resolver.py +331 -0
- ksadk/plugins/subagent_providers/__init__.py +12 -0
- ksadk/plugins/subagent_providers/codex.py +443 -0
- ksadk/plugins/subagents.py +333 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +51 -42
- ksadk/runtime/adapter.py +1 -0
- ksadk/runtime/factory.py +76 -2
- ksadk/runtime/framework_adapters.py +18 -0
- ksadk/runtime/runner_adapter.py +5 -0
- ksadk/sandbox/__init__.py +2 -1
- 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 +563 -0
- ksadk/server/static/assets/{ArtifactsPanel-DSU1sWD_.js → ArtifactsPanel-10GPXIJ6.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-DOH6MVcn.js → CodeBlock-BXk1l-G1.js} +1 -1
- ksadk/server/static/assets/{MathMessageMarkdown-BL8my1R2.js → MathMessageMarkdown-D9uB55Oh.js} +1 -1
- ksadk/server/static/assets/{MermaidBlock-Dz4IP-Tx.js → MermaidBlock--OEYoXIJ.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DUrK0JpZ.js → NativeTerminalPanel-DrEe1syq.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-g20pFzNV.js → abnfDiagram-VCTEODGH-eeTFJLvo.js} +1 -1
- ksadk/server/static/assets/{arc-C4FzinUA.js → arc-S3ZNbIAd.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-DpIqL5h4.js → architectureDiagram-5GKGNRK7-CRjgEJDX.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-BjkljTNz.js → blockDiagram-NRAW4CY4-C7bsBoNH.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-Dk_ieq2X.js → c4Diagram-UCG6FXSJ-BX3c33Ob.js} +1 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-BVHAchFb.js → chunk-5VM5RSS4-bZ7ws-8m.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-C-ipQzuS.js → chunk-F27PBJKO-D2r0pvhY.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-C2EyJbIK.js → chunk-G27WJ6UU-CZwF3oUP.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-vYvVJb_M.js → chunk-JWPE2WC7-DigFYCML.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-BcI6ysPT.js → chunk-LCL6LL3I-CnorGV5q.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-C030x_Z1.js → chunk-POPQ4Y6H-CexntQA-.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-yyGpsz4n.js → chunk-RHFEMEQ7-CHTC7UxA.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BLTlmMU7.js → chunk-SVP7TREG-BC1EWt_-.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-C_32ArgP.js → chunk-XXDRQBXY-BTG24xN0.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-9YQYwdl0.js → cose-bilkent-JH36ORCC-CkonRdAS.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-ErLF5N13.js → cynefinDiagram-5FMLGOSQ-DEOCBe15.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DFiQF-6f.js → dagre-3AP2YEHR-DBThPuLa.js} +1 -1
- ksadk/server/static/assets/{dagre-BuhGnRI1.js → dagre-ClTPrTht.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-Bt1v8-GC.js → diagram-S7CK7UJ4-DsZHrnpJ.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-DSCxJdBK.js → diagram-UQ7AKVKN-BJR4nhVr.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-DHfYwp_9.js → diagram-VSXAHHWV-xzcERX0a.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-DdzD-4Le.js → diagram-VX7I27RA-tn2xM1xu.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-Du-nAJ9F.js → diagram-Z3DM3KII-BZPGBkw5.js} +1 -1
- ksadk/server/static/assets/{dist-ClxGviKw.js → dist-4zN1_tq5.js} +1 -1
- ksadk/server/static/assets/{dist-BE7bu-DL.js → dist-8VWI-2bZ.js} +1 -1
- ksadk/server/static/assets/{dist-BX8z72IC.js → dist-B-46q3Hk.js} +1 -1
- ksadk/server/static/assets/{dist-BjU6y-A2.js → dist-B0gdk4rl.js} +1 -1
- ksadk/server/static/assets/{dist-C_wsv-Qd.js → dist-B1oWRmrH.js} +1 -1
- ksadk/server/static/assets/{dist-ngtN0DJB.js → dist-BI1qQH4n.js} +1 -1
- ksadk/server/static/assets/{dist-dydu68Fl.js → dist-BJLUwH6W.js} +1 -1
- ksadk/server/static/assets/{dist-Dq9gLD7L.js → dist-Bbwqa8TG.js} +1 -1
- ksadk/server/static/assets/{dist-CttYUqzS.js → dist-Btyo4vX4.js} +1 -1
- ksadk/server/static/assets/{dist-CXYYBw3_.js → dist-C71CsujO.js} +1 -1
- ksadk/server/static/assets/{dist-dDdADKFA.js → dist-CXpH_Rdd.js} +1 -1
- ksadk/server/static/assets/{dist-CSh_DE14.js → dist-Cq4OL6nO.js} +1 -1
- ksadk/server/static/assets/{dist-8hqcx0sU.js → dist-D1V3f1B4.js} +1 -1
- ksadk/server/static/assets/{dist-BVDffZ0U.js → dist-DJmCPRVB.js} +1 -1
- ksadk/server/static/assets/{dist-DnfXs8Vn.js → dist-DQAB0qn_.js} +1 -1
- ksadk/server/static/assets/{dist-DNp6rLRA.js → dist-DUwKa_l6.js} +1 -1
- ksadk/server/static/assets/{dist-B7seoj3d.js → dist-DdRBIceA.js} +1 -1
- ksadk/server/static/assets/{dist-BytlxIDT.js → dist-DfGFrb0v.js} +1 -1
- ksadk/server/static/assets/{dist-Bf2M8m3N.js → dist-DjhwGUgZ.js} +1 -1
- ksadk/server/static/assets/{dist-W-TIVntx.js → dist-DyqV4fL4.js} +1 -1
- ksadk/server/static/assets/{dist-DUX-id_F.js → dist-M67Hwu0n.js} +1 -1
- ksadk/server/static/assets/{dist-DmldrHd_.js → dist-u8tVH5Ak.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Da9C9NO1.js → ebnfDiagram-PWID7BFC-DVfMsLge.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-EAGqqR79.js → erDiagram-SSCWMZ5O-CWEZSYaw.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DqJsKb59.js → ganttDiagram-EL5Y4UJY-TWIxoyYL.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-B6g4dtDi.js → gitGraphDiagram-WWUBYQGX-DDh2hd2S.js} +1 -1
- ksadk/server/static/assets/index-B2k_urY8.js +241 -0
- ksadk/server/static/assets/index-ILPt6IWF.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-Djm_nbd5.js → infoDiagram-RXCK75RN-CgoyWiDR.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-DWya9SG2.js → ishikawaDiagram-5VMMS53U-CyRIu_om.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DutxhSNI.js → journeyDiagram-EYS64GPL-DN5JXHzN.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-DJdOF8Fm.js → kanban-definition-3QL26DDD-CNP3ui66.js} +1 -1
- ksadk/server/static/assets/{katex-vFWytM5c.js → katex-DWEzQy1d.js} +1 -1
- ksadk/server/static/assets/{linear-BHjG8b-J.js → linear-C-qHp7d2.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-KGSy4jWT.js → mermaid-parser.core-Cl-K943T.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-9-HC88D4.js → mindmap-definition-FBJOCRG2-D5DB5mYm.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-DrEZd4fD.js → pegDiagram-XKGWAZYB-BQVc9ia_.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-DpjqOFFp.js → pieDiagram-E7YTZNPT-B6UCAvtY.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BiNhgOXX.js → quadrantDiagram-AXDQQJYC-mIr2d3eb.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-_Y3Ojg6G.js → railroadDiagram-O6MQD6OU-Dt3FFDmK.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-DeCFdg9K.js → requirementDiagram-EFPCY7ZU-Cz_vQtgF.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-CPH75rhw.js → sankeyDiagram-P5KCCOFB-wlO1TsH5.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-OEpQQdr4.js → sequenceDiagram-WJ2MYXX4-CHRbElYq.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-heUErzhI.js → sizeCapture-X5ZJPWSS-DXX54iyO.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DvA3jSMB.js → stateDiagram-HBIQ2CUA-Dp_lw9II.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-CR-dfN_t.js → swimlanes-XN3QIQJK-D8O5UlLG.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-DAVJf1TX.js → timeline-definition-24CTP7MA-8mfKcxvG.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-DwM8eDkh.js → vennDiagram-4TSXK5OY-EnNl0DE7.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DZL-Zz2t.js → wardleyDiagram-VM6X3IG4-DBu5fbYr.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js → xychartDiagram-S5SC5T6Z-BSVXs4IY.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/skills/service_client.py +48 -0
- ksadk/studio/agent_lifecycle.py +26 -20
- ksadk/studio/api.py +513 -71
- ksadk/studio/api_catalog_routes.py +5 -0
- ksadk/studio/api_contracts.py +34 -1
- ksadk/studio/api_plugin_routes.py +480 -0
- ksadk/studio/attachment_store.py +187 -0
- ksadk/studio/authoring.py +10 -4
- ksadk/studio/authoring_coordinator.py +12 -2
- ksadk/studio/builder.py +123 -43
- ksadk/studio/cloud.py +4 -0
- ksadk/studio/codex_agent_service.py +12 -1
- ksadk/studio/codex_builder.py +54 -15
- ksadk/studio/codex_manifest.py +21 -1
- ksadk/studio/codex_run.py +16 -4
- ksadk/studio/compatibility_report.py +445 -0
- ksadk/studio/compiler.py +6 -1
- ksadk/studio/contracts.py +123 -4
- ksadk/studio/dsh_provider_registration.py +768 -0
- ksadk/studio/event_store.py +54 -6
- ksadk/studio/framework_run.py +37 -4
- ksadk/studio/hosted_kernel.py +1 -1
- ksadk/studio/operations.py +12 -2
- ksadk/studio/plugin_composition.py +301 -0
- ksadk/studio/plugin_kernel_adapter.py +128 -0
- ksadk/studio/plugin_runtime.py +652 -0
- ksadk/studio/resource_catalog.py +6 -1
- ksadk/studio/run_service.py +713 -75
- ksadk/studio/runtime_source.py +9 -1
- ksadk/studio/scheduler_runtime.py +374 -0
- ksadk/studio/scheduler_service.py +211 -0
- ksadk/studio/service.py +672 -82
- ksadk/studio/shared_web.py +167 -28
- ksadk/studio/soul.py +52 -0
- ksadk/studio/static/assets/index-DXs1Eq4M.css +1 -0
- ksadk/studio/static/assets/index-DeDqwTsD.js +283 -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
- 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/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.3.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.2.dist-info → agentengine_sdk_python-0.8.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Optional SubagentProvider implementations.
|
|
2
|
+
|
|
3
|
+
Subagents are child executions selected by a parent agent. They are not
|
|
4
|
+
top-level AgentProviders and therefore live outside ``plugins.providers``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from ksadk.plugins.subagent_providers.codex import (
|
|
8
|
+
DEFAULT_CODEX_CHILD_PROVIDER_REF,
|
|
9
|
+
CodexOneShotSubagentProvider,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = ["CodexOneShotSubagentProvider", "DEFAULT_CODEX_CHILD_PROVIDER_REF"]
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"""Isolated one-shot Codex implementation of ``SubagentProvider/v1``.
|
|
2
|
+
|
|
3
|
+
Each child owns one App Server client, one native thread, and one temporary
|
|
4
|
+
``CODEX_HOME``. The provider deliberately exposes no follow-up or resume
|
|
5
|
+
surface: a parent may stream, cancel, interrupt, inspect, and dispose exactly
|
|
6
|
+
one bounded read-only turn.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
import hashlib
|
|
13
|
+
import json
|
|
14
|
+
import shutil
|
|
15
|
+
import tempfile
|
|
16
|
+
import uuid
|
|
17
|
+
from collections.abc import AsyncIterator, Callable, Mapping
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from datetime import datetime, timezone
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from ksadk.plugins.subagents import (
|
|
24
|
+
ChildHandle,
|
|
25
|
+
SpawnSubagentRequest,
|
|
26
|
+
SubagentEvent,
|
|
27
|
+
SubagentProviderError,
|
|
28
|
+
SubagentResult,
|
|
29
|
+
SubagentStatus,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
DEFAULT_CODEX_CHILD_PROVIDER_REF = "plugin://io.ksadk.codex-child@1.0.0"
|
|
33
|
+
_CAPABILITIES = ("cancel", "interrupt", "streaming")
|
|
34
|
+
_TERMINAL_STATES = frozenset({"succeeded", "failed", "cancelled", "interrupted"})
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _now() -> datetime:
|
|
38
|
+
return datetime.now(timezone.utc)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class _ChildState:
|
|
43
|
+
handle: ChildHandle
|
|
44
|
+
client: Any
|
|
45
|
+
native_thread_id: str
|
|
46
|
+
home: Path
|
|
47
|
+
timeout_seconds: int
|
|
48
|
+
task_text: str
|
|
49
|
+
thread_config: dict[str, Any]
|
|
50
|
+
events: list[SubagentEvent] = field(default_factory=list)
|
|
51
|
+
condition: asyncio.Condition = field(default_factory=asyncio.Condition)
|
|
52
|
+
task: asyncio.Task[None] | None = None
|
|
53
|
+
state: str = "accepted"
|
|
54
|
+
reason: str | None = None
|
|
55
|
+
updated_at: datetime = field(default_factory=_now)
|
|
56
|
+
requested_terminal: str | None = None
|
|
57
|
+
result_value: SubagentResult | None = None
|
|
58
|
+
final_text: str = ""
|
|
59
|
+
closed: bool = False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class CodexOneShotSubagentProvider:
|
|
63
|
+
"""Run bounded Codex children without sharing process or conversation state."""
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
*,
|
|
68
|
+
project_dir: str | Path,
|
|
69
|
+
provider_ref: str = DEFAULT_CODEX_CHILD_PROVIDER_REF,
|
|
70
|
+
model: str | None = None,
|
|
71
|
+
base_instructions: str | None = None,
|
|
72
|
+
client_factory: Callable[[Path], Any] | None = None,
|
|
73
|
+
) -> None:
|
|
74
|
+
self._project_dir = Path(project_dir).resolve()
|
|
75
|
+
self._provider_ref = provider_ref
|
|
76
|
+
self._model = model
|
|
77
|
+
self._base_instructions = base_instructions
|
|
78
|
+
self._client_factory = client_factory
|
|
79
|
+
self._states: dict[str, _ChildState] = {}
|
|
80
|
+
|
|
81
|
+
async def describe(self) -> Mapping[str, Any]:
|
|
82
|
+
return {
|
|
83
|
+
"providerRef": self._provider_ref,
|
|
84
|
+
"mode": "one-shot",
|
|
85
|
+
"capabilities": list(_CAPABILITIES),
|
|
86
|
+
"sandbox": "read-only",
|
|
87
|
+
"resumable": False,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async def available(self) -> bool:
|
|
91
|
+
if self._client_factory is not None:
|
|
92
|
+
return True
|
|
93
|
+
try:
|
|
94
|
+
import openai_codex # noqa: F401
|
|
95
|
+
except ImportError:
|
|
96
|
+
return False
|
|
97
|
+
return True
|
|
98
|
+
|
|
99
|
+
async def spawn(self, request: SpawnSubagentRequest) -> ChildHandle:
|
|
100
|
+
if request.provider_ref != self._provider_ref:
|
|
101
|
+
raise SubagentProviderError(
|
|
102
|
+
"subagent_provider_mismatch",
|
|
103
|
+
"Codex child request does not target this exact provider version",
|
|
104
|
+
)
|
|
105
|
+
if request.policy.background:
|
|
106
|
+
raise SubagentProviderError(
|
|
107
|
+
"codex_child_policy_unsupported",
|
|
108
|
+
"One-shot Codex children do not support detached background execution",
|
|
109
|
+
)
|
|
110
|
+
if request.policy.allowed_tools or request.policy.allowed_permissions:
|
|
111
|
+
raise SubagentProviderError(
|
|
112
|
+
"codex_child_policy_unsupported",
|
|
113
|
+
"Codex child tool and permission allowlists require an enforceable native mapping",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
home = Path(tempfile.mkdtemp(prefix="ksadk-codex-child-"))
|
|
117
|
+
client: Any = None
|
|
118
|
+
try:
|
|
119
|
+
client = self._new_client(home)
|
|
120
|
+
thread_config = self._thread_config()
|
|
121
|
+
native_thread_id = str(await client.start_thread(thread_config))
|
|
122
|
+
except Exception:
|
|
123
|
+
if client is not None:
|
|
124
|
+
await client.close()
|
|
125
|
+
shutil.rmtree(home, ignore_errors=True)
|
|
126
|
+
raise
|
|
127
|
+
|
|
128
|
+
handle_id = f"codex-child-{uuid.uuid4().hex}"
|
|
129
|
+
digest = hashlib.sha256(
|
|
130
|
+
json.dumps(
|
|
131
|
+
{
|
|
132
|
+
"providerRef": self._provider_ref,
|
|
133
|
+
"mode": "one-shot",
|
|
134
|
+
"capabilities": _CAPABILITIES,
|
|
135
|
+
"sandbox": "read-only",
|
|
136
|
+
},
|
|
137
|
+
sort_keys=True,
|
|
138
|
+
separators=(",", ":"),
|
|
139
|
+
).encode("utf-8")
|
|
140
|
+
).hexdigest()
|
|
141
|
+
handle = ChildHandle(
|
|
142
|
+
handle_id=handle_id,
|
|
143
|
+
provider_ref=self._provider_ref,
|
|
144
|
+
parent_session_id=request.parent_session_id,
|
|
145
|
+
parent_run_id=request.parent_run_id,
|
|
146
|
+
child_session_id=native_thread_id,
|
|
147
|
+
child_run_id=f"codex-turn-{uuid.uuid4().hex}",
|
|
148
|
+
depth=request.depth,
|
|
149
|
+
capabilities=_CAPABILITIES,
|
|
150
|
+
capability_digest=f"sha256:{digest}",
|
|
151
|
+
created_at=_now(),
|
|
152
|
+
resumable=False,
|
|
153
|
+
)
|
|
154
|
+
state = _ChildState(
|
|
155
|
+
handle=handle,
|
|
156
|
+
client=client,
|
|
157
|
+
native_thread_id=native_thread_id,
|
|
158
|
+
home=home,
|
|
159
|
+
timeout_seconds=request.policy.timeout_seconds,
|
|
160
|
+
task_text=request.task,
|
|
161
|
+
thread_config=thread_config,
|
|
162
|
+
)
|
|
163
|
+
self._states[handle_id] = state
|
|
164
|
+
await self._append_event(
|
|
165
|
+
state,
|
|
166
|
+
"progress",
|
|
167
|
+
{"state": "accepted"},
|
|
168
|
+
{"threadId": native_thread_id},
|
|
169
|
+
)
|
|
170
|
+
state.task = asyncio.create_task(self._drive(state), name=f"ksadk-{handle_id}")
|
|
171
|
+
return handle
|
|
172
|
+
|
|
173
|
+
async def followup(self, handle: ChildHandle, input: Any) -> None:
|
|
174
|
+
del input
|
|
175
|
+
self._state(handle)
|
|
176
|
+
raise SubagentProviderError(
|
|
177
|
+
"codex_child_one_shot",
|
|
178
|
+
"Codex one-shot children do not accept follow-up input",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
async def status(self, handle: ChildHandle) -> SubagentStatus:
|
|
182
|
+
state = self._state(handle)
|
|
183
|
+
return SubagentStatus(
|
|
184
|
+
handle_id=handle.handle_id,
|
|
185
|
+
state=state.state,
|
|
186
|
+
last_seq=len(state.events),
|
|
187
|
+
updated_at=state.updated_at,
|
|
188
|
+
reason=state.reason,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
async def interrupt(self, handle: ChildHandle) -> None:
|
|
192
|
+
await self._stop(self._state(handle), "interrupted")
|
|
193
|
+
|
|
194
|
+
async def cancel(self, handle: ChildHandle) -> None:
|
|
195
|
+
await self._stop(self._state(handle), "cancelled")
|
|
196
|
+
|
|
197
|
+
def subscribe(self, handle: ChildHandle, *, after_seq: int = 0) -> AsyncIterator[SubagentEvent]:
|
|
198
|
+
if after_seq < 0:
|
|
199
|
+
raise SubagentProviderError(
|
|
200
|
+
"subagent_cursor_invalid", "subagent after_seq cannot be negative"
|
|
201
|
+
)
|
|
202
|
+
state = self._state(handle)
|
|
203
|
+
return self._subscribe(state, after_seq)
|
|
204
|
+
|
|
205
|
+
async def result(self, handle: ChildHandle) -> SubagentResult:
|
|
206
|
+
state = self._state(handle)
|
|
207
|
+
if state.task is not None and not state.task.done():
|
|
208
|
+
await asyncio.shield(state.task)
|
|
209
|
+
if state.result_value is None:
|
|
210
|
+
raise SubagentProviderError(
|
|
211
|
+
"codex_child_result_unavailable", "Codex child has no terminal result"
|
|
212
|
+
)
|
|
213
|
+
return state.result_value
|
|
214
|
+
|
|
215
|
+
async def dispose(self, handle: ChildHandle) -> None:
|
|
216
|
+
state = self._state(handle)
|
|
217
|
+
if state.state not in _TERMINAL_STATES and state.state != "disposed":
|
|
218
|
+
await self._stop(state, "cancelled")
|
|
219
|
+
if not state.closed:
|
|
220
|
+
state.closed = True
|
|
221
|
+
try:
|
|
222
|
+
await state.client.close()
|
|
223
|
+
finally:
|
|
224
|
+
shutil.rmtree(state.home, ignore_errors=True)
|
|
225
|
+
state.state = "disposed"
|
|
226
|
+
state.updated_at = _now()
|
|
227
|
+
async with state.condition:
|
|
228
|
+
state.condition.notify_all()
|
|
229
|
+
|
|
230
|
+
def _new_client(self, home: Path) -> Any:
|
|
231
|
+
if self._client_factory is not None:
|
|
232
|
+
return self._client_factory(home)
|
|
233
|
+
import openai_codex
|
|
234
|
+
|
|
235
|
+
from ksadk.codex.client import AsyncCodexClient
|
|
236
|
+
|
|
237
|
+
return AsyncCodexClient(openai_codex.CodexConfig(env={"CODEX_HOME": str(home)}))
|
|
238
|
+
|
|
239
|
+
def _thread_config(self) -> dict[str, Any]:
|
|
240
|
+
config: dict[str, Any] = {
|
|
241
|
+
"cwd": str(self._project_dir),
|
|
242
|
+
"sandbox_read_only": True,
|
|
243
|
+
"approval_mode": "deny_all",
|
|
244
|
+
"ephemeral": True,
|
|
245
|
+
}
|
|
246
|
+
if self._model:
|
|
247
|
+
config["model"] = self._model
|
|
248
|
+
if self._base_instructions:
|
|
249
|
+
config["base_instructions"] = self._base_instructions
|
|
250
|
+
return config
|
|
251
|
+
|
|
252
|
+
def _state(self, handle: ChildHandle) -> _ChildState:
|
|
253
|
+
state = self._states.get(handle.handle_id)
|
|
254
|
+
if state is None or state.handle != handle:
|
|
255
|
+
raise SubagentProviderError(
|
|
256
|
+
"subagent_handle_unknown", "Codex child handle is unknown or was modified"
|
|
257
|
+
)
|
|
258
|
+
return state
|
|
259
|
+
|
|
260
|
+
async def _drive(self, state: _ChildState) -> None:
|
|
261
|
+
try:
|
|
262
|
+
await asyncio.wait_for(self._consume_turn(state), timeout=state.timeout_seconds)
|
|
263
|
+
except asyncio.CancelledError:
|
|
264
|
+
terminal = state.requested_terminal or "cancelled"
|
|
265
|
+
await self._finish(state, terminal)
|
|
266
|
+
except asyncio.TimeoutError:
|
|
267
|
+
try:
|
|
268
|
+
await state.client.interrupt_active_turn(state.native_thread_id)
|
|
269
|
+
finally:
|
|
270
|
+
await self._finish(
|
|
271
|
+
state,
|
|
272
|
+
"failed",
|
|
273
|
+
error_code="codex_child_timeout",
|
|
274
|
+
error_message="Codex child exceeded its parent-owned timeout",
|
|
275
|
+
)
|
|
276
|
+
except Exception as error:
|
|
277
|
+
await self._finish(
|
|
278
|
+
state,
|
|
279
|
+
"failed",
|
|
280
|
+
error_code="codex_child_failed",
|
|
281
|
+
error_message=str(error)[:2048],
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
async def _consume_turn(self, state: _ChildState) -> None:
|
|
285
|
+
state.state = "running"
|
|
286
|
+
state.updated_at = _now()
|
|
287
|
+
await self._append_event(
|
|
288
|
+
state,
|
|
289
|
+
"progress",
|
|
290
|
+
{"state": "running"},
|
|
291
|
+
{"threadId": state.native_thread_id},
|
|
292
|
+
)
|
|
293
|
+
async for raw in state.client.run_turn(
|
|
294
|
+
state.native_thread_id,
|
|
295
|
+
state.task_text,
|
|
296
|
+
config=state.thread_config,
|
|
297
|
+
):
|
|
298
|
+
await self._project_native_event(state, raw)
|
|
299
|
+
await self._finish(state, "succeeded", output=state.final_text)
|
|
300
|
+
|
|
301
|
+
async def _project_native_event(self, state: _ChildState, raw: Mapping[str, Any]) -> None:
|
|
302
|
+
method = str(raw.get("method") or "")
|
|
303
|
+
params = raw.get("params")
|
|
304
|
+
if not isinstance(params, Mapping):
|
|
305
|
+
params = {}
|
|
306
|
+
native_ref = {
|
|
307
|
+
key: str(value)
|
|
308
|
+
for key, value in {
|
|
309
|
+
"method": method,
|
|
310
|
+
"threadId": params.get("threadId") or state.native_thread_id,
|
|
311
|
+
"turnId": params.get("turnId") or _mapping_value(params.get("turn"), "id"),
|
|
312
|
+
"itemId": params.get("itemId") or _mapping_value(params.get("item"), "id"),
|
|
313
|
+
}.items()
|
|
314
|
+
if value
|
|
315
|
+
}
|
|
316
|
+
if method in {"turn/started", "thread/tokenUsage/updated"}:
|
|
317
|
+
await self._append_event(state, "progress", {"method": method}, native_ref)
|
|
318
|
+
return
|
|
319
|
+
if method == "item/agentMessage/delta":
|
|
320
|
+
delta = str(params.get("delta") or "")
|
|
321
|
+
state.final_text += delta
|
|
322
|
+
if delta:
|
|
323
|
+
await self._append_event(
|
|
324
|
+
state, "item", {"type": "agent_message_delta", "text": delta}, native_ref
|
|
325
|
+
)
|
|
326
|
+
return
|
|
327
|
+
if method == "item/completed":
|
|
328
|
+
item = params.get("item")
|
|
329
|
+
item_type = _mapping_value(item, "type") or "item"
|
|
330
|
+
text = _item_text(item)
|
|
331
|
+
if item_type in {"agentMessage", "message"} and text:
|
|
332
|
+
state.final_text = text
|
|
333
|
+
await self._append_event(
|
|
334
|
+
state,
|
|
335
|
+
"item",
|
|
336
|
+
{"type": str(item_type), **({"text": text} if text else {})},
|
|
337
|
+
native_ref,
|
|
338
|
+
)
|
|
339
|
+
return
|
|
340
|
+
if method == "error":
|
|
341
|
+
message = str(params.get("message") or params.get("error") or "Codex error")
|
|
342
|
+
raise RuntimeError(message)
|
|
343
|
+
|
|
344
|
+
async def _stop(self, state: _ChildState, terminal: str) -> None:
|
|
345
|
+
if state.state in _TERMINAL_STATES or state.state == "disposed":
|
|
346
|
+
return
|
|
347
|
+
state.requested_terminal = terminal
|
|
348
|
+
try:
|
|
349
|
+
await state.client.interrupt_active_turn(state.native_thread_id)
|
|
350
|
+
except Exception as error:
|
|
351
|
+
# A dead or already-finished native process must not prevent local
|
|
352
|
+
# cancellation and, critically, must not prevent ``dispose`` from
|
|
353
|
+
# closing the client and deleting its isolated CODEX_HOME.
|
|
354
|
+
state.reason = f"native interrupt failed: {error}"[:2048]
|
|
355
|
+
finally:
|
|
356
|
+
if state.task is not None and not state.task.done():
|
|
357
|
+
state.task.cancel()
|
|
358
|
+
await asyncio.gather(state.task, return_exceptions=True)
|
|
359
|
+
if state.result_value is None:
|
|
360
|
+
await self._finish(state, terminal)
|
|
361
|
+
|
|
362
|
+
async def _finish(
|
|
363
|
+
self,
|
|
364
|
+
state: _ChildState,
|
|
365
|
+
terminal: str,
|
|
366
|
+
*,
|
|
367
|
+
output: Any = None,
|
|
368
|
+
error_code: str | None = None,
|
|
369
|
+
error_message: str | None = None,
|
|
370
|
+
) -> None:
|
|
371
|
+
if state.result_value is not None:
|
|
372
|
+
return
|
|
373
|
+
state.state = terminal
|
|
374
|
+
if error_message is not None:
|
|
375
|
+
state.reason = error_message
|
|
376
|
+
state.updated_at = _now()
|
|
377
|
+
state.result_value = SubagentResult(
|
|
378
|
+
handle_id=state.handle.handle_id,
|
|
379
|
+
state=terminal,
|
|
380
|
+
output=output,
|
|
381
|
+
error_code=error_code,
|
|
382
|
+
error_message=error_message,
|
|
383
|
+
)
|
|
384
|
+
await self._append_event(
|
|
385
|
+
state,
|
|
386
|
+
"terminal",
|
|
387
|
+
{"state": terminal, **({"errorCode": error_code} if error_code else {})},
|
|
388
|
+
{"threadId": state.native_thread_id},
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
async def _append_event(
|
|
392
|
+
self,
|
|
393
|
+
state: _ChildState,
|
|
394
|
+
kind: str,
|
|
395
|
+
payload: dict[str, Any],
|
|
396
|
+
native_ref: dict[str, str],
|
|
397
|
+
) -> None:
|
|
398
|
+
seq = len(state.events) + 1
|
|
399
|
+
state.events.append(
|
|
400
|
+
SubagentEvent(
|
|
401
|
+
handle_id=state.handle.handle_id,
|
|
402
|
+
event_id=f"{state.handle.handle_id}:{seq}",
|
|
403
|
+
seq=seq,
|
|
404
|
+
kind=kind,
|
|
405
|
+
payload=payload,
|
|
406
|
+
native_ref=native_ref,
|
|
407
|
+
)
|
|
408
|
+
)
|
|
409
|
+
state.updated_at = _now()
|
|
410
|
+
async with state.condition:
|
|
411
|
+
state.condition.notify_all()
|
|
412
|
+
|
|
413
|
+
async def _subscribe(self, state: _ChildState, after_seq: int) -> AsyncIterator[SubagentEvent]:
|
|
414
|
+
cursor = after_seq
|
|
415
|
+
while True:
|
|
416
|
+
while cursor < len(state.events):
|
|
417
|
+
event = state.events[cursor]
|
|
418
|
+
cursor = event.seq
|
|
419
|
+
yield event
|
|
420
|
+
if state.result_value is not None or state.state == "disposed":
|
|
421
|
+
return
|
|
422
|
+
async with state.condition:
|
|
423
|
+
if cursor >= len(state.events) and state.result_value is None:
|
|
424
|
+
await state.condition.wait()
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
def _mapping_value(value: Any, key: str) -> Any:
|
|
428
|
+
return value.get(key) if isinstance(value, Mapping) else None
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
def _item_text(item: Any) -> str:
|
|
432
|
+
if not isinstance(item, Mapping):
|
|
433
|
+
return ""
|
|
434
|
+
direct = item.get("text")
|
|
435
|
+
if isinstance(direct, str):
|
|
436
|
+
return direct
|
|
437
|
+
content = item.get("content")
|
|
438
|
+
if not isinstance(content, list):
|
|
439
|
+
return ""
|
|
440
|
+
return "".join(str(part.get("text") or "") for part in content if isinstance(part, Mapping))
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
__all__ = ["CodexOneShotSubagentProvider", "DEFAULT_CODEX_CHILD_PROVIDER_REF"]
|