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
ksadk/studio/service.py
CHANGED
|
@@ -4,8 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import hashlib
|
|
7
|
+
import json
|
|
7
8
|
import logging
|
|
8
9
|
import os
|
|
10
|
+
import zipfile
|
|
11
|
+
from collections.abc import Mapping, Sequence
|
|
9
12
|
from dataclasses import dataclass
|
|
10
13
|
from pathlib import Path
|
|
11
14
|
from typing import Any, Callable, Literal, cast
|
|
@@ -13,6 +16,7 @@ from urllib.parse import urlparse
|
|
|
13
16
|
from uuid import uuid4
|
|
14
17
|
|
|
15
18
|
from ksadk.api import AgentEngineClient
|
|
19
|
+
from ksadk.conversations.contracts import ConversationCapability, ConversationSurface
|
|
16
20
|
from ksadk.evaluation import (
|
|
17
21
|
EvaluationConfig as PublicEvaluationConfig,
|
|
18
22
|
)
|
|
@@ -39,10 +43,22 @@ from ksadk.evaluation.studio_build_adapter import (
|
|
|
39
43
|
from ksadk.events.store import RuntimeEventStore
|
|
40
44
|
from ksadk.observability.session_log import SessionLogError, export_session_log
|
|
41
45
|
from ksadk.observability.trajectory import encode_sse, project_trajectory_event
|
|
46
|
+
from ksadk.plugins.contracts import PluginManifest
|
|
47
|
+
from ksadk.plugins.providers.legacy import LegacyHarnessSource
|
|
48
|
+
from ksadk.plugins.providers.legacy_catalog import (
|
|
49
|
+
KSADK_HARNESS_AGENT_PROVIDER_PLUGIN_ID,
|
|
50
|
+
)
|
|
42
51
|
from ksadk.runtime import RuntimeExecutor, build_default_runtime_registry
|
|
52
|
+
from ksadk.scheduler.contracts import (
|
|
53
|
+
ScheduleCommandTemplate,
|
|
54
|
+
ScheduledTask,
|
|
55
|
+
ScheduledTaskTarget,
|
|
56
|
+
ScheduleSpec,
|
|
57
|
+
)
|
|
43
58
|
from ksadk.sessions.local_service import LocalSessionService
|
|
44
59
|
from ksadk.studio.agent_avatar_assets import AgentAvatarAssetStore
|
|
45
60
|
from ksadk.studio.agent_lifecycle import delete_framework_agent
|
|
61
|
+
from ksadk.studio.attachment_store import ConversationAttachmentStore
|
|
46
62
|
from ksadk.studio.authoring_coordinator import StudioAuthoringCoordinator
|
|
47
63
|
from ksadk.studio.builder import AgentBundleBuilder
|
|
48
64
|
from ksadk.studio.capabilities import builtin_tool_contracts
|
|
@@ -84,6 +100,10 @@ from ksadk.studio.contracts import (
|
|
|
84
100
|
RuntimeRef,
|
|
85
101
|
ToolContract,
|
|
86
102
|
)
|
|
103
|
+
from ksadk.studio.dsh_provider_registration import (
|
|
104
|
+
StudioDshProviderRegistrationError,
|
|
105
|
+
StudioDshProviderRegistrationManager,
|
|
106
|
+
)
|
|
87
107
|
from ksadk.studio.errors import StudioError
|
|
88
108
|
from ksadk.studio.event_store import RunEventStore
|
|
89
109
|
from ksadk.studio.framework_run import FrameworkRunSpecResolver
|
|
@@ -91,11 +111,19 @@ from ksadk.studio.mcp_runtime import MCPRuntimeAdapter
|
|
|
91
111
|
from ksadk.studio.model_client import CredentialResolver, OpenAICompatibleModelClient
|
|
92
112
|
from ksadk.studio.model_profile_service import test_model_profile_connection
|
|
93
113
|
from ksadk.studio.operations import OperationManager
|
|
114
|
+
from ksadk.studio.plugin_composition import StudioPluginCompositionCompiler
|
|
115
|
+
from ksadk.studio.plugin_runtime import StudioPluginRuntime
|
|
94
116
|
from ksadk.studio.repository import AgentDraftRepository, BuildRepository, load_yaml_file
|
|
95
117
|
from ksadk.studio.resource_catalog import LocalResourceCatalog
|
|
96
|
-
from ksadk.studio.run_service import StudioRunService
|
|
118
|
+
from ksadk.studio.run_service import StudioRunService, StudioRunSpec
|
|
97
119
|
from ksadk.studio.runtime_catalog import inspect_runtime_catalog
|
|
98
120
|
from ksadk.studio.runtime_source import materialize_generated_runtime_source
|
|
121
|
+
from ksadk.studio.scheduler_runtime import (
|
|
122
|
+
StudioScheduledKernelRegistry,
|
|
123
|
+
StudioSchedulerRuntimeError,
|
|
124
|
+
)
|
|
125
|
+
from ksadk.studio.scheduler_service import StudioSchedulerService
|
|
126
|
+
from ksadk.studio.soul import soul_digest
|
|
99
127
|
from ksadk.studio.templates import (
|
|
100
128
|
compose_blank_agent,
|
|
101
129
|
compose_research_agent,
|
|
@@ -129,11 +157,34 @@ class StudioService:
|
|
|
129
157
|
cloud_gateway: CloudDeploymentGateway | None = None,
|
|
130
158
|
codex_runtime_inspector: RuntimeInspector | None = None,
|
|
131
159
|
runtime_executor: RuntimeExecutor | None = None,
|
|
160
|
+
harness_reasoner: Any | None = None,
|
|
161
|
+
plugin_provider_manifests: Mapping[str, PluginManifest] | None = None,
|
|
162
|
+
plugin_provider_factories: Mapping[str, Any] | None = None,
|
|
163
|
+
legacy_harness_sources: Sequence[LegacyHarnessSource] = (),
|
|
164
|
+
dsh_provider_registration_manager: StudioDshProviderRegistrationManager | None = None,
|
|
132
165
|
) -> None:
|
|
166
|
+
provider_manifests = dict(plugin_provider_manifests or {})
|
|
167
|
+
provider_factories = dict(plugin_provider_factories or {})
|
|
168
|
+
if provider_manifests.keys() != provider_factories.keys():
|
|
169
|
+
raise ValueError(
|
|
170
|
+
"plugin provider manifests and factories must use the same exact references"
|
|
171
|
+
)
|
|
133
172
|
self.workspace = Workspace(root)
|
|
134
173
|
self.workspace.initialize()
|
|
174
|
+
self._startup_provider_manifests = provider_manifests
|
|
175
|
+
self._startup_provider_factories = provider_factories
|
|
176
|
+
self._active_provider_manifests = dict(provider_manifests)
|
|
177
|
+
self._dsh_provider_registration_manager = (
|
|
178
|
+
dsh_provider_registration_manager
|
|
179
|
+
or StudioDshProviderRegistrationManager.discover_or_create_workspace_default(
|
|
180
|
+
self.workspace.root
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
self._start_lock = asyncio.Lock()
|
|
184
|
+
self._started = False
|
|
135
185
|
self._apply_persisted_settings()
|
|
136
186
|
self.avatar_assets = AgentAvatarAssetStore(self.workspace)
|
|
187
|
+
self.conversation_attachments = ConversationAttachmentStore(self.workspace)
|
|
137
188
|
self.drafts = AgentDraftRepository(self.workspace)
|
|
138
189
|
self.catalog = LocalResourceCatalog(self.workspace)
|
|
139
190
|
self.builds = BuildRepository(self.workspace)
|
|
@@ -147,6 +198,11 @@ class StudioService:
|
|
|
147
198
|
),
|
|
148
199
|
repository=self.builds,
|
|
149
200
|
)
|
|
201
|
+
self.plugin_compositions = StudioPluginCompositionCompiler(
|
|
202
|
+
self.workspace,
|
|
203
|
+
self.catalog,
|
|
204
|
+
provider_manifests=provider_manifests,
|
|
205
|
+
)
|
|
150
206
|
self.event_store = RunEventStore(self.workspace)
|
|
151
207
|
self.session_service = LocalSessionService(project_dir=str(self.workspace.root))
|
|
152
208
|
self.runtime_events = RuntimeEventStore(self.session_service)
|
|
@@ -194,6 +250,28 @@ class StudioService:
|
|
|
194
250
|
credential_resolver=self.credentials
|
|
195
251
|
)
|
|
196
252
|
self.model_client = runtime_model_client
|
|
253
|
+
self.plugin_runs = StudioPluginRuntime(
|
|
254
|
+
self.workspace,
|
|
255
|
+
build_repository=self.builds,
|
|
256
|
+
session_service=self.session_service,
|
|
257
|
+
model_client=self.model_client,
|
|
258
|
+
secret_resolver=self.credentials,
|
|
259
|
+
harness_reasoner=harness_reasoner,
|
|
260
|
+
provider_manifests=provider_manifests,
|
|
261
|
+
provider_factories=provider_factories,
|
|
262
|
+
legacy_harness_sources=legacy_harness_sources,
|
|
263
|
+
)
|
|
264
|
+
self.run_service.plugin_runtime = self.plugin_runs
|
|
265
|
+
self.scheduler_runtimes = StudioScheduledKernelRegistry(
|
|
266
|
+
resolve_build=self.resolve_run_spec,
|
|
267
|
+
resolve_adapter_provider=self._scheduler_adapter_provider,
|
|
268
|
+
session_service=self.session_service,
|
|
269
|
+
runtime_executor=self.runtime_executor,
|
|
270
|
+
)
|
|
271
|
+
self.scheduler = StudioSchedulerService(
|
|
272
|
+
self.workspace,
|
|
273
|
+
runtime_registry=self.scheduler_runtimes,
|
|
274
|
+
)
|
|
197
275
|
self.mcp_runtime = MCPRuntimeAdapter(self.workspace, credentials=self.credentials)
|
|
198
276
|
self._cloud_gateway_override = cloud_gateway
|
|
199
277
|
self.cloud = CloudDeploymentService(
|
|
@@ -202,15 +280,535 @@ class StudioService:
|
|
|
202
280
|
build_repository=self.builds,
|
|
203
281
|
)
|
|
204
282
|
self.operations = OperationManager(self.workspace)
|
|
205
|
-
self.evaluation_storage = EvaluationStorage(
|
|
206
|
-
self.workspace.resolve(".agentkit/evaluations")
|
|
207
|
-
)
|
|
283
|
+
self.evaluation_storage = EvaluationStorage(self.workspace.resolve(".agentkit/evaluations"))
|
|
208
284
|
self.authoring = StudioAuthoringCoordinator(self)
|
|
209
285
|
self.codex_agents = CodexAgentService(self)
|
|
210
286
|
|
|
287
|
+
async def start(self) -> None:
|
|
288
|
+
"""Bind ready managed DSH registrations before build or execution."""
|
|
289
|
+
|
|
290
|
+
async with self._start_lock:
|
|
291
|
+
if self._started:
|
|
292
|
+
return
|
|
293
|
+
await self._bootstrap_official_dsh_defaults()
|
|
294
|
+
manifests, factories, manager_refs = await self._provider_snapshot(refresh=False)
|
|
295
|
+
self.plugin_compositions.replace_provider_registrations(manifests)
|
|
296
|
+
self.plugin_runs.replace_provider_registrations(manifests, factories)
|
|
297
|
+
self._active_provider_manifests = manifests
|
|
298
|
+
manager = self._dsh_provider_registration_manager
|
|
299
|
+
if manager is not None and manager_refs is not None:
|
|
300
|
+
manager.mark_bound(manager_refs)
|
|
301
|
+
self._started = True
|
|
302
|
+
|
|
303
|
+
async def refresh_dsh_provider_registrations(self) -> None:
|
|
304
|
+
"""Rebind the exact current DSH Profile and release stale activations."""
|
|
305
|
+
|
|
306
|
+
async with self._start_lock:
|
|
307
|
+
if self._dsh_provider_registration_manager is None:
|
|
308
|
+
self._dsh_provider_registration_manager = (
|
|
309
|
+
StudioDshProviderRegistrationManager.discover_or_create_workspace_default(
|
|
310
|
+
self.workspace.root
|
|
311
|
+
)
|
|
312
|
+
)
|
|
313
|
+
await self._bootstrap_official_dsh_defaults()
|
|
314
|
+
if self._started:
|
|
315
|
+
await self.plugin_runs.aclose()
|
|
316
|
+
manifests, factories, manager_refs = await self._provider_snapshot(refresh=True)
|
|
317
|
+
self.plugin_compositions.replace_provider_registrations(manifests)
|
|
318
|
+
self.plugin_runs.replace_provider_registrations(manifests, factories)
|
|
319
|
+
self._active_provider_manifests = manifests
|
|
320
|
+
manager = self._dsh_provider_registration_manager
|
|
321
|
+
if manager is not None and manager_refs is not None:
|
|
322
|
+
manager.mark_bound(manager_refs)
|
|
323
|
+
self._started = True
|
|
324
|
+
|
|
325
|
+
async def _bootstrap_official_dsh_defaults(self) -> None:
|
|
326
|
+
manager = self._dsh_provider_registration_manager
|
|
327
|
+
if manager is None:
|
|
328
|
+
return
|
|
329
|
+
try:
|
|
330
|
+
result = await manager.bootstrap_official_codex_provider()
|
|
331
|
+
except Exception as error: # optional DSH must fail closed to legacy paths
|
|
332
|
+
logging.getLogger(__name__).warning(
|
|
333
|
+
"official DSH provider bootstrap skipped: %s", error
|
|
334
|
+
)
|
|
335
|
+
return
|
|
336
|
+
if result in {"installed", "already_enabled"}:
|
|
337
|
+
logging.getLogger(__name__).info("official Codex DSH provider bootstrap: %s", result)
|
|
338
|
+
|
|
339
|
+
async def _provider_snapshot(
|
|
340
|
+
self, *, refresh: bool
|
|
341
|
+
) -> tuple[dict[str, PluginManifest], dict[str, Any], tuple[str, ...] | None]:
|
|
342
|
+
manifests = dict(self._startup_provider_manifests)
|
|
343
|
+
factories = dict(self._startup_provider_factories)
|
|
344
|
+
manager = self._dsh_provider_registration_manager
|
|
345
|
+
if manager is None:
|
|
346
|
+
return manifests, factories, None
|
|
347
|
+
try:
|
|
348
|
+
registrations = await (manager.refresh() if refresh else manager.start())
|
|
349
|
+
except StudioDshProviderRegistrationError as error:
|
|
350
|
+
logging.getLogger(__name__).warning(
|
|
351
|
+
"DSH AgentProvider discovery failed closed: %s", error.code
|
|
352
|
+
)
|
|
353
|
+
return manifests, factories, None
|
|
354
|
+
if registrations.manifests.keys() != registrations.factories.keys():
|
|
355
|
+
logging.getLogger(__name__).warning(
|
|
356
|
+
"DSH AgentProvider discovery returned a partial registration set"
|
|
357
|
+
)
|
|
358
|
+
return manifests, factories, None
|
|
359
|
+
for provider_ref, manifest in registrations.manifests.items():
|
|
360
|
+
if provider_ref in manifests and (
|
|
361
|
+
manifests[provider_ref] != manifest
|
|
362
|
+
or factories[provider_ref] is not registrations.factories[provider_ref]
|
|
363
|
+
):
|
|
364
|
+
logging.getLogger(__name__).warning(
|
|
365
|
+
"DSH AgentProvider registration conflicts with startup provider: %s",
|
|
366
|
+
provider_ref,
|
|
367
|
+
)
|
|
368
|
+
return (
|
|
369
|
+
dict(self._startup_provider_manifests),
|
|
370
|
+
dict(self._startup_provider_factories),
|
|
371
|
+
None,
|
|
372
|
+
)
|
|
373
|
+
manifests[provider_ref] = manifest
|
|
374
|
+
factories[provider_ref] = registrations.factories[provider_ref]
|
|
375
|
+
return manifests, factories, tuple(registrations.manifests)
|
|
376
|
+
|
|
377
|
+
def agent_provider_catalog(self) -> list[dict[str, Any]]:
|
|
378
|
+
"""Return only external providers that reached Studio's bound selector."""
|
|
379
|
+
|
|
380
|
+
reserved = {
|
|
381
|
+
KSADK_HARNESS_AGENT_PROVIDER_PLUGIN_ID,
|
|
382
|
+
}
|
|
383
|
+
package_by_ref: dict[str, str] = {}
|
|
384
|
+
display_name_by_ref: dict[str, str] = {}
|
|
385
|
+
manager = self._dsh_provider_registration_manager
|
|
386
|
+
if manager is not None:
|
|
387
|
+
package_by_ref = {
|
|
388
|
+
item.provider_ref: item.package_name
|
|
389
|
+
for item in manager.inventory.packages
|
|
390
|
+
if item.state == "bound" and item.provider_ref is not None
|
|
391
|
+
}
|
|
392
|
+
display_name_by_ref = {
|
|
393
|
+
item.provider_ref: item.display_name
|
|
394
|
+
for item in manager.inventory.packages
|
|
395
|
+
if item.state == "bound" and item.provider_ref is not None and item.display_name
|
|
396
|
+
}
|
|
397
|
+
items = []
|
|
398
|
+
for provider_ref, manifest in sorted(self._active_provider_manifests.items()):
|
|
399
|
+
if manifest.metadata.id in reserved:
|
|
400
|
+
continue
|
|
401
|
+
items.append(
|
|
402
|
+
{
|
|
403
|
+
"providerRef": provider_ref,
|
|
404
|
+
"pluginId": package_by_ref.get(provider_ref, manifest.metadata.id),
|
|
405
|
+
"resolvedVersion": manifest.metadata.version,
|
|
406
|
+
"displayName": display_name_by_ref.get(provider_ref, manifest.metadata.id),
|
|
407
|
+
"state": "enabled",
|
|
408
|
+
"compatible": True,
|
|
409
|
+
"selectable": True,
|
|
410
|
+
"reason": None,
|
|
411
|
+
"permissions": list(manifest.spec.permissions),
|
|
412
|
+
"isolation": manifest.spec.isolation,
|
|
413
|
+
"configSchemaDeclared": manifest.spec.config_schema is not None,
|
|
414
|
+
"secretFields": list(manifest.spec.secret_fields),
|
|
415
|
+
}
|
|
416
|
+
)
|
|
417
|
+
return items
|
|
418
|
+
|
|
419
|
+
def dsh_provider_runtime_state(self, package_name: str) -> dict[str, Any] | None:
|
|
420
|
+
"""Project one manager-owned package lifecycle state for plugin APIs."""
|
|
421
|
+
|
|
422
|
+
manager = self._dsh_provider_registration_manager
|
|
423
|
+
if manager is None:
|
|
424
|
+
return None
|
|
425
|
+
status = next(
|
|
426
|
+
(item for item in manager.inventory.packages if item.package_name == package_name),
|
|
427
|
+
None,
|
|
428
|
+
)
|
|
429
|
+
if status is None:
|
|
430
|
+
return None
|
|
431
|
+
return {
|
|
432
|
+
"state": status.state,
|
|
433
|
+
"providerRef": status.provider_ref,
|
|
434
|
+
"errorCode": status.error_code,
|
|
435
|
+
}
|
|
436
|
+
|
|
211
437
|
def runtime_catalog(self) -> list[dict]:
|
|
212
438
|
return inspect_runtime_catalog(self.runtime_executor)
|
|
213
439
|
|
|
440
|
+
def _scheduler_adapter_provider(self, spec: StudioRunSpec): # type: ignore[no-untyped-def]
|
|
441
|
+
if spec.plugin_bundle_root is not None:
|
|
442
|
+
return self.plugin_runs.kernel_adapter_provider(spec)
|
|
443
|
+
return lambda: self.runtime_executor.create_adapter(spec.launch_context)
|
|
444
|
+
|
|
445
|
+
def resolve_run_spec(
|
|
446
|
+
self,
|
|
447
|
+
build_id: str,
|
|
448
|
+
*,
|
|
449
|
+
model: str | None = None,
|
|
450
|
+
sandbox: str | None = None,
|
|
451
|
+
approval_mode: str | None = None,
|
|
452
|
+
) -> StudioRunSpec:
|
|
453
|
+
"""Resolve one immutable Build through its only compatible resolver."""
|
|
454
|
+
|
|
455
|
+
try:
|
|
456
|
+
return self.codex_runs.resolve(
|
|
457
|
+
build_id,
|
|
458
|
+
model=model,
|
|
459
|
+
sandbox=sandbox,
|
|
460
|
+
approval_mode=approval_mode,
|
|
461
|
+
)
|
|
462
|
+
except Exception as exc:
|
|
463
|
+
if getattr(exc, "status_code", None) != 404:
|
|
464
|
+
raise
|
|
465
|
+
framework_build = self.builds.get(build_id)
|
|
466
|
+
runtime_type = framework_build.runtime_type.strip().lower()
|
|
467
|
+
if runtime_type in {"harness", "plugin"}:
|
|
468
|
+
return self.plugin_runs.resolve(build_id, model=model)
|
|
469
|
+
return self.framework_runs.resolve(
|
|
470
|
+
build_id,
|
|
471
|
+
model=model,
|
|
472
|
+
approval_mode=approval_mode,
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
def validate_schedule_build(
|
|
476
|
+
self,
|
|
477
|
+
build_ref: str | None,
|
|
478
|
+
*,
|
|
479
|
+
agent_id: str | None = None,
|
|
480
|
+
) -> None:
|
|
481
|
+
"""Reject a ScheduledTask target build that is not a real immutable Build.
|
|
482
|
+
|
|
483
|
+
The agent-scoped authoring path resolves the Build server-side via
|
|
484
|
+
:meth:`ensure_current_build`, so this guard is primarily for the raw
|
|
485
|
+
``/api/v1/schedules`` surface that accepts a caller-supplied
|
|
486
|
+
``agent_version_ref``. A version name or tag (for example "v1") is
|
|
487
|
+
not an immutable Build id and must fail at admission with an actionable
|
|
488
|
+
error instead of collapsing into a later opaque DISPATCH_FAILED.
|
|
489
|
+
"""
|
|
490
|
+
ref = (build_ref or "").strip()
|
|
491
|
+
if not ref:
|
|
492
|
+
raise StudioError(
|
|
493
|
+
"SCHEDULE_BUILD_REQUIRED",
|
|
494
|
+
"定时任务必须绑定一个已成功构建的 Build id(不能为空或使用版本名)",
|
|
495
|
+
status_code=422,
|
|
496
|
+
field="target.agentVersionRef",
|
|
497
|
+
)
|
|
498
|
+
try:
|
|
499
|
+
spec = self.resolve_run_spec(ref)
|
|
500
|
+
except StudioError as error:
|
|
501
|
+
if error.status_code == 404:
|
|
502
|
+
raise StudioError(
|
|
503
|
+
"SCHEDULE_BUILD_UNAVAILABLE",
|
|
504
|
+
f"定时任务绑定的 Build {ref!r} 不可用:请使用已成功构建的 Build id,而非版本名",
|
|
505
|
+
status_code=422,
|
|
506
|
+
field="target.agentVersionRef",
|
|
507
|
+
details={"buildId": ref},
|
|
508
|
+
) from error
|
|
509
|
+
raise
|
|
510
|
+
except Exception as error:
|
|
511
|
+
raise StudioError(
|
|
512
|
+
"SCHEDULE_BUILD_UNAVAILABLE",
|
|
513
|
+
f"定时任务绑定的 Build {ref!r} 不可用:{error}",
|
|
514
|
+
status_code=422,
|
|
515
|
+
field="target.agentVersionRef",
|
|
516
|
+
details={"buildId": ref},
|
|
517
|
+
) from error
|
|
518
|
+
if agent_id and spec.agent_id != agent_id:
|
|
519
|
+
raise StudioError(
|
|
520
|
+
"SCHEDULE_AGENT_MISMATCH",
|
|
521
|
+
"定时任务绑定的 Build 与所选 Agent 不一致",
|
|
522
|
+
status_code=422,
|
|
523
|
+
field="target.agentVersionRef",
|
|
524
|
+
details={"buildId": ref, "agentId": agent_id},
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
def conversation_surface(
|
|
528
|
+
self,
|
|
529
|
+
build_id: str,
|
|
530
|
+
*,
|
|
531
|
+
session_id: str,
|
|
532
|
+
) -> ConversationSurface:
|
|
533
|
+
"""Describe the actual local composer contract for one Build/session.
|
|
534
|
+
|
|
535
|
+
This is intentionally conservative. It derives the declaration from
|
|
536
|
+
the resolved Build, rather than guessing support from a model name or
|
|
537
|
+
sending provider-specific fields to every Runtime.
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
spec = self.resolve_run_spec(build_id)
|
|
541
|
+
runtime_type = spec.launch_context.runtime_type.strip().lower()
|
|
542
|
+
runtime_mode: Literal["native", "translated"] = (
|
|
543
|
+
"native" if runtime_type == "codex" else "translated"
|
|
544
|
+
)
|
|
545
|
+
inputs = [ConversationCapability(name="text", mode="native")]
|
|
546
|
+
if spec.model:
|
|
547
|
+
inputs.append(ConversationCapability(name="model.select", mode=runtime_mode))
|
|
548
|
+
inputs.append(ConversationCapability(name="approval", mode=runtime_mode))
|
|
549
|
+
if runtime_type == "codex":
|
|
550
|
+
inputs.extend(
|
|
551
|
+
(
|
|
552
|
+
# Studio projects image data URLs to native Codex ImageInput.
|
|
553
|
+
ConversationCapability(name="attachment.image", mode="native"),
|
|
554
|
+
# Bounded UTF-8/code attachments are made model-visible as
|
|
555
|
+
# deterministic text parts by the Responses compatibility
|
|
556
|
+
# adapter. Binary files remain unavailable in Phase 2.
|
|
557
|
+
ConversationCapability(name="attachment.file", mode="translated"),
|
|
558
|
+
ConversationCapability(name="reasoning.effort", mode="native"),
|
|
559
|
+
ConversationCapability(name="goal", mode="native"),
|
|
560
|
+
ConversationCapability(name="plan", mode="native"),
|
|
561
|
+
)
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
outputs = [
|
|
565
|
+
ConversationCapability(name="text", mode="native"),
|
|
566
|
+
ConversationCapability(name="streaming", mode=runtime_mode),
|
|
567
|
+
]
|
|
568
|
+
if runtime_type == "codex":
|
|
569
|
+
outputs.extend(
|
|
570
|
+
(
|
|
571
|
+
ConversationCapability(name="reasoning", mode="native"),
|
|
572
|
+
ConversationCapability(name="tool.inspect", mode="native"),
|
|
573
|
+
ConversationCapability(name="approval", mode="native"),
|
|
574
|
+
ConversationCapability(name="goal", mode="native"),
|
|
575
|
+
ConversationCapability(name="plan", mode="native"),
|
|
576
|
+
ConversationCapability(name="cancel", mode="native"),
|
|
577
|
+
)
|
|
578
|
+
)
|
|
579
|
+
return ConversationSurface(
|
|
580
|
+
surface_id=f"studio.build.{spec.build_id}",
|
|
581
|
+
session_id=session_id,
|
|
582
|
+
provider_ref=f"studio.runtime.{runtime_type}",
|
|
583
|
+
inputs=tuple(inputs),
|
|
584
|
+
outputs=tuple(outputs),
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
async def ensure_current_build(self, agent_id: str):
|
|
588
|
+
"""Return the Build that is eligible for a local Studio turn.
|
|
589
|
+
|
|
590
|
+
This is deliberately one shared resolver for Web chat and Scheduler
|
|
591
|
+
authoring. A Scheduler must never select a mutable Draft or a stale
|
|
592
|
+
Codex manifest merely because a UI happened to show it as an Agent.
|
|
593
|
+
"""
|
|
594
|
+
|
|
595
|
+
await self.start()
|
|
596
|
+
if self.is_codex_agent(agent_id):
|
|
597
|
+
self.codex_agent_detail(agent_id)
|
|
598
|
+
builds = [
|
|
599
|
+
record
|
|
600
|
+
for record in self.codex_builds.list()
|
|
601
|
+
if record.agent_name == agent_id and self.codex_builder.is_current(record)
|
|
602
|
+
]
|
|
603
|
+
if builds:
|
|
604
|
+
return builds[0]
|
|
605
|
+
return await asyncio.to_thread(self.codex_builder.build, agent_id)
|
|
606
|
+
draft = self.drafts.get(agent_id)
|
|
607
|
+
composition_required = self.plugin_compositions.required_for(draft)
|
|
608
|
+
for record in self.builds.list_for_agent(agent_id):
|
|
609
|
+
if record.status == BuildStatus.SUCCEEDED:
|
|
610
|
+
if composition_required and (
|
|
611
|
+
record.source_revision != draft.metadata.revision
|
|
612
|
+
or not self._build_has_composition(record)
|
|
613
|
+
):
|
|
614
|
+
continue
|
|
615
|
+
if composition_required:
|
|
616
|
+
composition = self.plugin_compositions.compile_if_required(draft)
|
|
617
|
+
if composition is None: # pragma: no cover - guarded by required_for
|
|
618
|
+
raise StudioError(
|
|
619
|
+
"PLUGIN_COMPOSITION_REQUIRED",
|
|
620
|
+
"当前 Agent 需要插件组合,但无法生成 Composition",
|
|
621
|
+
status_code=409,
|
|
622
|
+
)
|
|
623
|
+
self.plugin_compositions.bind_build(
|
|
624
|
+
composition,
|
|
625
|
+
agent_id=draft.metadata.id,
|
|
626
|
+
build_id=record.id,
|
|
627
|
+
)
|
|
628
|
+
return record
|
|
629
|
+
if draft.spec.model is None and not draft.spec.bindings.model_profile_id:
|
|
630
|
+
raise StudioError(
|
|
631
|
+
"AGENT_MODEL_REQUIRED",
|
|
632
|
+
"当前 Agent 未绑定 Model Profile,请先在 Agent 配置中选择模型;"
|
|
633
|
+
"API Key 只提供访问凭证,不会自动绑定模型。",
|
|
634
|
+
status_code=422,
|
|
635
|
+
field="spec.bindings.modelProfileId",
|
|
636
|
+
)
|
|
637
|
+
return await asyncio.to_thread(self._build_agent_bundle, draft)
|
|
638
|
+
|
|
639
|
+
def _build_agent_bundle(self, draft: AgentDraft):
|
|
640
|
+
composition = self.plugin_compositions.compile_if_required(draft)
|
|
641
|
+
record = self.builder.build(draft, composition=composition)
|
|
642
|
+
if composition is not None:
|
|
643
|
+
self.plugin_compositions.bind_build(
|
|
644
|
+
composition,
|
|
645
|
+
agent_id=draft.metadata.id,
|
|
646
|
+
build_id=record.id,
|
|
647
|
+
)
|
|
648
|
+
return record
|
|
649
|
+
|
|
650
|
+
def _build_has_composition(self, record: Any) -> bool:
|
|
651
|
+
"""Reject stale pre-Phase-2 builds for a composed runtime.
|
|
652
|
+
|
|
653
|
+
This check is intentionally scoped to Harness/plugin runtimes. Legacy
|
|
654
|
+
ADK/LangGraph build selection retains its existing behavior.
|
|
655
|
+
"""
|
|
656
|
+
|
|
657
|
+
if not record.artifact_path:
|
|
658
|
+
return False
|
|
659
|
+
try:
|
|
660
|
+
archive = self.workspace.resolve(record.artifact_path, must_exist=True)
|
|
661
|
+
with zipfile.ZipFile(archive) as bundle:
|
|
662
|
+
manifest = json.loads(bundle.read("manifest.json"))
|
|
663
|
+
names = frozenset(bundle.namelist())
|
|
664
|
+
return bool(
|
|
665
|
+
isinstance(manifest, dict)
|
|
666
|
+
and manifest.get("compositionProfileDigest")
|
|
667
|
+
and "composition-profile.json" in names
|
|
668
|
+
and "plugin-lock.json" in names
|
|
669
|
+
)
|
|
670
|
+
except (KeyError, OSError, UnicodeError, ValueError, zipfile.BadZipFile):
|
|
671
|
+
return False
|
|
672
|
+
|
|
673
|
+
async def create_agent_schedule(
|
|
674
|
+
self,
|
|
675
|
+
agent_id: str,
|
|
676
|
+
*,
|
|
677
|
+
display_name: str,
|
|
678
|
+
prompt: str,
|
|
679
|
+
schedule: ScheduleSpec,
|
|
680
|
+
enabled: bool = True,
|
|
681
|
+
continuity: Literal["new_session", "continue_session"] = "new_session",
|
|
682
|
+
session_id: str | None = None,
|
|
683
|
+
) -> ScheduledTask:
|
|
684
|
+
"""Create a local-only schedule for the Kernel Runtime that owns it.
|
|
685
|
+
|
|
686
|
+
The browser provides only human intent (prompt/calendar/continuity).
|
|
687
|
+
The trusted Studio process resolves the immutable Build and concrete
|
|
688
|
+
Kernel instance. Thus a task cannot be pointed at another Agent
|
|
689
|
+
Instance, smuggle a permit reference, or claim cloud scheduling.
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
await self.start()
|
|
693
|
+
build = await self.ensure_current_build(agent_id)
|
|
694
|
+
spec = self.resolve_run_spec(build.id)
|
|
695
|
+
await self.scheduler_runtimes.start()
|
|
696
|
+
try:
|
|
697
|
+
target = await self.scheduler_runtimes.ensure_build(
|
|
698
|
+
build.id,
|
|
699
|
+
expected_agent_id=agent_id,
|
|
700
|
+
)
|
|
701
|
+
runtime = self.scheduler_runtimes.runtime_for_build(build.id)
|
|
702
|
+
except StudioSchedulerRuntimeError as error:
|
|
703
|
+
raise StudioError(
|
|
704
|
+
error.code,
|
|
705
|
+
str(error),
|
|
706
|
+
status_code=409,
|
|
707
|
+
details={"agentId": agent_id, "buildId": build.id},
|
|
708
|
+
) from error
|
|
709
|
+
if continuity == "continue_session" and not session_id:
|
|
710
|
+
raise StudioError(
|
|
711
|
+
"SCHEDULE_SESSION_REQUIRED",
|
|
712
|
+
"继续会话的定时任务必须选择一个已有会话。",
|
|
713
|
+
status_code=422,
|
|
714
|
+
field="sessionId",
|
|
715
|
+
)
|
|
716
|
+
if continuity == "continue_session":
|
|
717
|
+
self._require_schedule_continuation(runtime, spec.launch_context.runtime_type)
|
|
718
|
+
task = ScheduledTask(
|
|
719
|
+
task_id=f"sched-{uuid4().hex[:20]}",
|
|
720
|
+
display_name=display_name,
|
|
721
|
+
target=ScheduledTaskTarget(
|
|
722
|
+
agent_id=agent_id,
|
|
723
|
+
tenant_id=target.tenant_id,
|
|
724
|
+
agent_instance_id=target.agent_instance_id,
|
|
725
|
+
agent_version_ref=str(build.id),
|
|
726
|
+
session_id=session_id,
|
|
727
|
+
# This is an opaque local authority marker, never a browser
|
|
728
|
+
# supplied credential. The dispatcher obtains a short-lived
|
|
729
|
+
# in-process permit at the AgentControl ingress boundary.
|
|
730
|
+
authorization_ref="runtime://local-kernel-ingress",
|
|
731
|
+
),
|
|
732
|
+
schedule=schedule,
|
|
733
|
+
command=ScheduleCommandTemplate(payload={"content": prompt}),
|
|
734
|
+
enabled=enabled,
|
|
735
|
+
continuity=continuity,
|
|
736
|
+
)
|
|
737
|
+
return self.scheduler.create_task(task)
|
|
738
|
+
|
|
739
|
+
@staticmethod
|
|
740
|
+
def _require_schedule_continuation(runtime: Any, runtime_type: str) -> None:
|
|
741
|
+
"""Fail closed unless the bound Provider can preserve one conversation.
|
|
742
|
+
|
|
743
|
+
Harness owns process-local Session history without exposing the generic
|
|
744
|
+
checkpoint ``resume`` verb. Codex and external adapters must declare
|
|
745
|
+
the typed resume capability. An older Runtime that lacks either proof
|
|
746
|
+
remains usable for normal conversations and ``new_session`` schedules;
|
|
747
|
+
only the optional follow-up mode is rejected.
|
|
748
|
+
"""
|
|
749
|
+
|
|
750
|
+
if runtime_type.strip().lower() == "harness":
|
|
751
|
+
return
|
|
752
|
+
kernel = getattr(runtime, "kernel", None)
|
|
753
|
+
describe = getattr(kernel, "capabilities", None)
|
|
754
|
+
matrix = describe() if callable(describe) else None
|
|
755
|
+
resume = getattr(matrix, "resume", None)
|
|
756
|
+
if not bool(getattr(resume, "supported", False)):
|
|
757
|
+
raise StudioError(
|
|
758
|
+
"SCHEDULE_CONTINUATION_UNAVAILABLE",
|
|
759
|
+
"当前 Runtime 未声明可恢复的会话续接能力;可改用新会话定时任务。",
|
|
760
|
+
status_code=409,
|
|
761
|
+
field="continuity",
|
|
762
|
+
details={"runtimeType": runtime_type},
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
def list_agent_schedules(self, agent_id: str) -> list[ScheduledTask]:
|
|
766
|
+
return [task for task in self.scheduler.list_tasks() if task.target.agent_id == agent_id]
|
|
767
|
+
|
|
768
|
+
def get_agent_schedule(self, agent_id: str, task_id: str) -> ScheduledTask:
|
|
769
|
+
task = self.scheduler.get_task(task_id)
|
|
770
|
+
if task.target.agent_id != agent_id:
|
|
771
|
+
from ksadk.studio.errors import not_found
|
|
772
|
+
|
|
773
|
+
raise not_found("schedule", task_id)
|
|
774
|
+
return task
|
|
775
|
+
|
|
776
|
+
def update_agent_schedule(
|
|
777
|
+
self,
|
|
778
|
+
agent_id: str,
|
|
779
|
+
task_id: str,
|
|
780
|
+
*,
|
|
781
|
+
display_name: str,
|
|
782
|
+
prompt: str,
|
|
783
|
+
schedule: ScheduleSpec,
|
|
784
|
+
enabled: bool,
|
|
785
|
+
continuity: Literal["new_session", "continue_session"],
|
|
786
|
+
session_id: str | None,
|
|
787
|
+
) -> ScheduledTask:
|
|
788
|
+
existing = self.get_agent_schedule(agent_id, task_id)
|
|
789
|
+
if continuity == "continue_session" and not session_id:
|
|
790
|
+
raise StudioError(
|
|
791
|
+
"SCHEDULE_SESSION_REQUIRED",
|
|
792
|
+
"继续会话的定时任务必须选择一个已有会话。",
|
|
793
|
+
status_code=422,
|
|
794
|
+
field="sessionId",
|
|
795
|
+
)
|
|
796
|
+
task = existing.model_copy(
|
|
797
|
+
update={
|
|
798
|
+
"display_name": display_name,
|
|
799
|
+
"schedule": schedule,
|
|
800
|
+
"command": ScheduleCommandTemplate(payload={"content": prompt}),
|
|
801
|
+
"enabled": enabled,
|
|
802
|
+
"continuity": continuity,
|
|
803
|
+
"target": existing.target.model_copy(update={"session_id": session_id}),
|
|
804
|
+
}
|
|
805
|
+
)
|
|
806
|
+
return self.scheduler.update_task(task_id, task)
|
|
807
|
+
|
|
808
|
+
async def run_agent_schedule_now(self, agent_id: str, task_id: str):
|
|
809
|
+
self.get_agent_schedule(agent_id, task_id)
|
|
810
|
+
return await self.scheduler.run_now(task_id)
|
|
811
|
+
|
|
214
812
|
def codex_manifest_state(self, agent_id: str | None = None) -> dict:
|
|
215
813
|
return self.codex_agents.manifest_state(agent_id)
|
|
216
814
|
|
|
@@ -315,9 +913,17 @@ class StudioService:
|
|
|
315
913
|
status_code=409,
|
|
316
914
|
details={"sessionId": session_id},
|
|
317
915
|
)
|
|
916
|
+
await self.plugin_runs.close_session(session_id)
|
|
318
917
|
await self.session_service.delete_session(session_id)
|
|
319
918
|
self.event_store.delete_session(session_id)
|
|
320
919
|
|
|
920
|
+
async def aclose(self) -> None:
|
|
921
|
+
"""Release local provider activations and supervised plugin processes."""
|
|
922
|
+
|
|
923
|
+
await self.plugin_runs.aclose()
|
|
924
|
+
if self._dsh_provider_registration_manager is not None:
|
|
925
|
+
await self._dsh_provider_registration_manager.aclose()
|
|
926
|
+
|
|
321
927
|
async def _require_runtime_session(self, session_id: str) -> None:
|
|
322
928
|
if await self.session_service.get_session_metadata(session_id) is None:
|
|
323
929
|
raise StudioError(
|
|
@@ -842,12 +1448,36 @@ class StudioService:
|
|
|
842
1448
|
|
|
843
1449
|
def agent_detail(self, agent_id: str) -> dict:
|
|
844
1450
|
if self.is_codex_agent(agent_id):
|
|
845
|
-
|
|
1451
|
+
detail = self.codex_agent_detail(agent_id)
|
|
1452
|
+
detail["soulProjection"] = self._soul_projection(detail["draft"])
|
|
1453
|
+
return detail
|
|
846
1454
|
draft = self.drafts.get(agent_id)
|
|
847
1455
|
return {
|
|
848
1456
|
"draft": draft,
|
|
849
1457
|
"builds": self.builds.list_for_agent(agent_id)[:10],
|
|
850
1458
|
"validation": self.validator.validate(draft),
|
|
1459
|
+
"soulProjection": self._soul_projection(draft),
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
@staticmethod
|
|
1463
|
+
def _soul_projection(draft: AgentDraft) -> dict[str, object]:
|
|
1464
|
+
"""Describe the reviewed Soul source without claiming runtime learning."""
|
|
1465
|
+
|
|
1466
|
+
soul = draft.spec.soul
|
|
1467
|
+
runtime_type = draft.spec.runtime.type if draft.spec.runtime is not None else ""
|
|
1468
|
+
compile_target = {
|
|
1469
|
+
"codex": "managed-runtime.base_instructions",
|
|
1470
|
+
"plugin": "instructions/soul.md",
|
|
1471
|
+
}.get(runtime_type, "resolved-agent-spec.instructions.system")
|
|
1472
|
+
return {
|
|
1473
|
+
"present": soul is not None,
|
|
1474
|
+
"source": "AgentSpec.soul",
|
|
1475
|
+
"sourceRevision": draft.metadata.revision,
|
|
1476
|
+
"schemaVersion": soul.schema_version if soul is not None else "agentkit.soul/v1",
|
|
1477
|
+
"digest": soul_digest(soul) if soul is not None else None,
|
|
1478
|
+
"digestAlgorithm": "sha256-canonical-json",
|
|
1479
|
+
"compileTarget": compile_target,
|
|
1480
|
+
"compileOrder": "before-instructions.system",
|
|
851
1481
|
}
|
|
852
1482
|
|
|
853
1483
|
def create_studio_agent(
|
|
@@ -1000,32 +1630,11 @@ class StudioService:
|
|
|
1000
1630
|
revision: int,
|
|
1001
1631
|
idempotency_key: str,
|
|
1002
1632
|
) -> Operation:
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
if runtime is None:
|
|
1009
|
-
from ksadk.studio.errors import StudioError
|
|
1010
|
-
|
|
1011
|
-
raise StudioError(
|
|
1012
|
-
"RUNTIME_NOT_REGISTERED",
|
|
1013
|
-
"Agent 引用的 RuntimeAdapter 未注册",
|
|
1014
|
-
status_code=422,
|
|
1015
|
-
details={"runtimeType": runtime_type},
|
|
1016
|
-
)
|
|
1017
|
-
if runtime["status"] != "ready":
|
|
1018
|
-
from ksadk.studio.errors import StudioError
|
|
1019
|
-
|
|
1020
|
-
raise StudioError(
|
|
1021
|
-
"RUNTIME_DEPENDENCY_MISSING",
|
|
1022
|
-
f"{runtime['displayName']} Runtime 依赖未安装",
|
|
1023
|
-
status_code=422,
|
|
1024
|
-
details={
|
|
1025
|
-
"runtimeType": runtime_type,
|
|
1026
|
-
"installCommand": runtime["installCommand"],
|
|
1027
|
-
},
|
|
1028
|
-
)
|
|
1633
|
+
# Codex build admission already runs the injected runtime inspector and
|
|
1634
|
+
# pins its result into the immutable build. Checking package metadata
|
|
1635
|
+
# first would reject an explicitly supplied RuntimeExecutor/inspector
|
|
1636
|
+
# (including an out-of-process Codex runtime) merely because the local
|
|
1637
|
+
# Studio interpreter does not have the optional wheel installed.
|
|
1029
1638
|
if self.is_codex_agent(agent_id):
|
|
1030
1639
|
detail = self.agent_detail(agent_id)
|
|
1031
1640
|
if revision != detail["draft"].metadata.revision:
|
|
@@ -1040,6 +1649,12 @@ class StudioService:
|
|
|
1040
1649
|
idempotency_key=idempotency_key,
|
|
1041
1650
|
agent_id=agent_id,
|
|
1042
1651
|
)
|
|
1652
|
+
|
|
1653
|
+
# A framework Build compiles and seals source/configuration only. Its
|
|
1654
|
+
# optional Runtime dependency belongs to run preflight, and may live in
|
|
1655
|
+
# a different process or deployment image. Rejecting the Build from
|
|
1656
|
+
# this Studio interpreter's package metadata would make portable
|
|
1657
|
+
# bundles impossible and incorrectly couple authoring to execution.
|
|
1043
1658
|
return self.submit_build(
|
|
1044
1659
|
agent_id,
|
|
1045
1660
|
revision=revision,
|
|
@@ -1271,8 +1886,7 @@ class StudioService:
|
|
|
1271
1886
|
resolved.model_profile_ids = [
|
|
1272
1887
|
resource_id
|
|
1273
1888
|
for resource_id in resolved.model_profile_ids
|
|
1274
|
-
if resource_id in known
|
|
1275
|
-
or resource_id not in current.model_profile_ids
|
|
1889
|
+
if resource_id in known or resource_id not in current.model_profile_ids
|
|
1276
1890
|
]
|
|
1277
1891
|
resolved.skills = selected_for_materialization(
|
|
1278
1892
|
candidate.skills,
|
|
@@ -1356,7 +1970,7 @@ class StudioService:
|
|
|
1356
1970
|
snapshot = draft.model_copy(deep=True)
|
|
1357
1971
|
|
|
1358
1972
|
async def runner(_operation_id: str):
|
|
1359
|
-
return await asyncio.to_thread(self.
|
|
1973
|
+
return await asyncio.to_thread(self._build_agent_bundle, snapshot)
|
|
1360
1974
|
|
|
1361
1975
|
return self.operations.submit(
|
|
1362
1976
|
kind=OperationKind.BUILD,
|
|
@@ -1420,21 +2034,13 @@ class StudioService:
|
|
|
1420
2034
|
):
|
|
1421
2035
|
"""Execute any immutable Studio Build through the canonical executor."""
|
|
1422
2036
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
except Exception as exc:
|
|
1431
|
-
if getattr(exc, "status_code", None) != 404:
|
|
1432
|
-
raise
|
|
1433
|
-
spec = self.framework_runs.resolve(
|
|
1434
|
-
build_id,
|
|
1435
|
-
model=model,
|
|
1436
|
-
approval_mode=approval_mode,
|
|
1437
|
-
)
|
|
2037
|
+
await self.start()
|
|
2038
|
+
spec = self.resolve_run_spec(
|
|
2039
|
+
build_id,
|
|
2040
|
+
model=model,
|
|
2041
|
+
sandbox=sandbox,
|
|
2042
|
+
approval_mode=approval_mode,
|
|
2043
|
+
)
|
|
1438
2044
|
if collaboration_mode or goal_objective or reasoning_effort:
|
|
1439
2045
|
from dataclasses import replace
|
|
1440
2046
|
|
|
@@ -1660,12 +2266,14 @@ class StudioService:
|
|
|
1660
2266
|
evalset = load_evalset(path)
|
|
1661
2267
|
except (EvalSetParseError, OSError):
|
|
1662
2268
|
continue
|
|
1663
|
-
evalsets.append(
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
2269
|
+
evalsets.append(
|
|
2270
|
+
{
|
|
2271
|
+
"path": path.relative_to(self.workspace.root).as_posix(),
|
|
2272
|
+
"name": evalset.name,
|
|
2273
|
+
"caseCount": len(evalset.cases),
|
|
2274
|
+
"contentDigest": evalset.content_digest,
|
|
2275
|
+
}
|
|
2276
|
+
)
|
|
1669
2277
|
evalsets.sort(key=lambda item: item["path"])
|
|
1670
2278
|
return {"builds": builds, "evalsets": evalsets}
|
|
1671
2279
|
|
|
@@ -1840,9 +2448,7 @@ class StudioService:
|
|
|
1840
2448
|
# this outbound control-plane request only, never in the Build or
|
|
1841
2449
|
# deployment receipt.
|
|
1842
2450
|
launch = self.codex_runs.resolve(build_id)
|
|
1843
|
-
runtime_environment = dict(
|
|
1844
|
-
(launch.launch_context.config or {}).get("env") or {}
|
|
1845
|
-
)
|
|
2451
|
+
runtime_environment = dict((launch.launch_context.config or {}).get("env") or {})
|
|
1846
2452
|
# Retrying a YAML deployment must update the Agent that the prior
|
|
1847
2453
|
# receipt already created. CreateAgent can have succeeded before
|
|
1848
2454
|
# a downstream Runtime-Service start failed; creating again would
|
|
@@ -2026,14 +2632,10 @@ class StudioService:
|
|
|
2026
2632
|
|
|
2027
2633
|
workspace_identity = str(self.workspace.root.resolve())
|
|
2028
2634
|
region = (
|
|
2029
|
-
os.environ.get("AGENTENGINE_REGION")
|
|
2030
|
-
or os.environ.get("KSYUN_REGION")
|
|
2031
|
-
or "cn-beijing-6"
|
|
2635
|
+
os.environ.get("AGENTENGINE_REGION") or os.environ.get("KSYUN_REGION") or "cn-beijing-6"
|
|
2032
2636
|
).strip()
|
|
2033
2637
|
access_key = (
|
|
2034
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2035
|
-
or os.environ.get("KS3_ACCESS_KEY")
|
|
2036
|
-
or "unsigned"
|
|
2638
|
+
os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY") or "unsigned"
|
|
2037
2639
|
).strip()
|
|
2038
2640
|
|
|
2039
2641
|
def opaque(value: str) -> str:
|
|
@@ -2060,29 +2662,19 @@ class StudioService:
|
|
|
2060
2662
|
"AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "cn-beijing-6")
|
|
2061
2663
|
),
|
|
2062
2664
|
"cloudBucket": os.environ.get("KS3_BUCKET", ""),
|
|
2063
|
-
"cloudAccountId": (
|
|
2064
|
-
os.environ.get("KSYUN_ACCOUNT_ID", "").strip()
|
|
2065
|
-
),
|
|
2665
|
+
"cloudAccountId": (os.environ.get("KSYUN_ACCOUNT_ID", "").strip()),
|
|
2066
2666
|
# AK/SK 不回显(避免本地 UI 回传 secret);只暴露配置状态。
|
|
2067
2667
|
# 已配置 = 启动环境或已持久化 settings 里 AK+SK 齐全。
|
|
2068
2668
|
"cloudAccountConfigured": bool(
|
|
2069
|
-
(
|
|
2070
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2071
|
-
or os.environ.get("KS3_ACCESS_KEY", "")
|
|
2072
|
-
).strip()
|
|
2669
|
+
(os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
|
|
2073
2670
|
and (
|
|
2074
|
-
os.environ.get("KSYUN_SECRET_KEY")
|
|
2075
|
-
or os.environ.get("KS3_SECRET_KEY", "")
|
|
2671
|
+
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2076
2672
|
).strip()
|
|
2077
2673
|
),
|
|
2078
2674
|
"cloudSignedAccountConfigured": bool(
|
|
2079
|
-
(
|
|
2080
|
-
os.environ.get("KSYUN_ACCESS_KEY")
|
|
2081
|
-
or os.environ.get("KS3_ACCESS_KEY", "")
|
|
2082
|
-
).strip()
|
|
2675
|
+
(os.environ.get("KSYUN_ACCESS_KEY") or os.environ.get("KS3_ACCESS_KEY", "")).strip()
|
|
2083
2676
|
and (
|
|
2084
|
-
os.environ.get("KSYUN_SECRET_KEY")
|
|
2085
|
-
or os.environ.get("KS3_SECRET_KEY", "")
|
|
2677
|
+
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2086
2678
|
).strip()
|
|
2087
2679
|
),
|
|
2088
2680
|
"traceContent": os.environ.get("KSADK_STUDIO_TRACE_CONTENT", "1") != "0",
|
|
@@ -2191,9 +2783,7 @@ class StudioService:
|
|
|
2191
2783
|
secret_key = (
|
|
2192
2784
|
os.environ.get("KSYUN_SECRET_KEY") or os.environ.get("KS3_SECRET_KEY", "")
|
|
2193
2785
|
).strip()
|
|
2194
|
-
region = os.environ.get(
|
|
2195
|
-
"AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "")
|
|
2196
|
-
).strip()
|
|
2786
|
+
region = os.environ.get("AGENTENGINE_REGION", os.environ.get("KSYUN_REGION", "")).strip()
|
|
2197
2787
|
if not all((access_key, secret_key, region)):
|
|
2198
2788
|
return UnavailableCloudGateway()
|
|
2199
2789
|
control_client = AgentEngineClient(
|