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,187 @@
|
|
|
1
|
+
"""Bounded, content-addressed local attachments for ConversationInput."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from ksadk.studio.errors import StudioError, not_found
|
|
12
|
+
from ksadk.studio.workspace import Workspace
|
|
13
|
+
|
|
14
|
+
_ATTACHMENT_REF = re.compile(r"^attachment://sha256/(?P<digest>[0-9a-f]{64})$")
|
|
15
|
+
_SAFE_FILENAME = re.compile(r"[^A-Za-z0-9._-]+")
|
|
16
|
+
_TEXT_MEDIA_TYPES = {
|
|
17
|
+
"application/json",
|
|
18
|
+
"application/toml",
|
|
19
|
+
"application/xml",
|
|
20
|
+
"application/x-httpd-php",
|
|
21
|
+
"application/x-sh",
|
|
22
|
+
"application/x-yaml",
|
|
23
|
+
}
|
|
24
|
+
_TEXT_SUFFIXES = {
|
|
25
|
+
".csv",
|
|
26
|
+
".css",
|
|
27
|
+
".go",
|
|
28
|
+
".html",
|
|
29
|
+
".ini",
|
|
30
|
+
".java",
|
|
31
|
+
".js",
|
|
32
|
+
".json",
|
|
33
|
+
".jsx",
|
|
34
|
+
".log",
|
|
35
|
+
".md",
|
|
36
|
+
".py",
|
|
37
|
+
".rs",
|
|
38
|
+
".sh",
|
|
39
|
+
".toml",
|
|
40
|
+
".ts",
|
|
41
|
+
".tsx",
|
|
42
|
+
".txt",
|
|
43
|
+
".xml",
|
|
44
|
+
".yaml",
|
|
45
|
+
".yml",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class StoredConversationAttachment:
|
|
51
|
+
attachment_ref: str
|
|
52
|
+
path: Path
|
|
53
|
+
name: str
|
|
54
|
+
media_type: str
|
|
55
|
+
size: int
|
|
56
|
+
digest: str
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ConversationAttachmentStore:
|
|
60
|
+
"""Persist only the small image/text inputs supported by local Studio."""
|
|
61
|
+
|
|
62
|
+
MAX_BYTES = 1_500_000
|
|
63
|
+
|
|
64
|
+
def __init__(self, workspace: Workspace) -> None:
|
|
65
|
+
self.workspace = workspace
|
|
66
|
+
self.root = self.workspace.resolve(".agentkit/assets/conversation-attachments")
|
|
67
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
|
|
69
|
+
def store(self, content: bytes, *, filename: str, media_type: str) -> dict[str, object]:
|
|
70
|
+
if not content:
|
|
71
|
+
raise StudioError(
|
|
72
|
+
"CONVERSATION_ATTACHMENT_EMPTY",
|
|
73
|
+
"会话附件不能为空",
|
|
74
|
+
status_code=422,
|
|
75
|
+
field="file",
|
|
76
|
+
)
|
|
77
|
+
if len(content) > self.MAX_BYTES:
|
|
78
|
+
raise StudioError(
|
|
79
|
+
"CONVERSATION_ATTACHMENT_TOO_LARGE",
|
|
80
|
+
"会话附件不能超过 1.5 MiB",
|
|
81
|
+
status_code=413,
|
|
82
|
+
field="file",
|
|
83
|
+
details={"maxBytes": self.MAX_BYTES},
|
|
84
|
+
)
|
|
85
|
+
normalized_type = media_type.split(";", 1)[0].strip().lower()
|
|
86
|
+
safe_name = _SAFE_FILENAME.sub("-", Path(filename).name).strip(".-")[:160]
|
|
87
|
+
safe_name = safe_name or "attachment"
|
|
88
|
+
if not self._supported(content, filename=safe_name, media_type=normalized_type):
|
|
89
|
+
raise StudioError(
|
|
90
|
+
"CONVERSATION_ATTACHMENT_TYPE_UNSUPPORTED",
|
|
91
|
+
"会话附件仅支持图片或 UTF-8 文本、代码文件",
|
|
92
|
+
status_code=415,
|
|
93
|
+
field="file",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
digest = hashlib.sha256(content).hexdigest()
|
|
97
|
+
content_path = self.root / f"{digest}.bin"
|
|
98
|
+
metadata_path = self.root / f"{digest}.json"
|
|
99
|
+
if not content_path.is_file():
|
|
100
|
+
self.workspace.atomic_write_bytes(content_path, content)
|
|
101
|
+
if not metadata_path.is_file():
|
|
102
|
+
self.workspace.atomic_write_text(
|
|
103
|
+
metadata_path,
|
|
104
|
+
json.dumps(
|
|
105
|
+
{
|
|
106
|
+
"digest": digest,
|
|
107
|
+
"name": safe_name,
|
|
108
|
+
"mediaType": normalized_type or "application/octet-stream",
|
|
109
|
+
"size": len(content),
|
|
110
|
+
},
|
|
111
|
+
ensure_ascii=False,
|
|
112
|
+
sort_keys=True,
|
|
113
|
+
separators=(",", ":"),
|
|
114
|
+
)
|
|
115
|
+
+ "\n",
|
|
116
|
+
)
|
|
117
|
+
# The reference identifies content, so its persisted metadata is the
|
|
118
|
+
# authority as well. Returning a second upload's conflicting name or
|
|
119
|
+
# media type would create a ref that immediately fails on resolution.
|
|
120
|
+
stored = self.resolve(f"attachment://sha256/{digest}")
|
|
121
|
+
return {
|
|
122
|
+
"attachmentRef": stored.attachment_ref,
|
|
123
|
+
"name": stored.name,
|
|
124
|
+
"mediaType": stored.media_type,
|
|
125
|
+
"size": stored.size,
|
|
126
|
+
"digest": stored.digest,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
def resolve(self, attachment_ref: str) -> StoredConversationAttachment:
|
|
130
|
+
match = _ATTACHMENT_REF.fullmatch(attachment_ref)
|
|
131
|
+
if match is None:
|
|
132
|
+
raise not_found("conversation-attachment", attachment_ref)
|
|
133
|
+
digest = match.group("digest")
|
|
134
|
+
content_path = self.root / f"{digest}.bin"
|
|
135
|
+
metadata_path = self.root / f"{digest}.json"
|
|
136
|
+
if not content_path.is_file() or not metadata_path.is_file():
|
|
137
|
+
raise not_found("conversation-attachment", attachment_ref)
|
|
138
|
+
try:
|
|
139
|
+
metadata = json.loads(metadata_path.read_text(encoding="utf-8"))
|
|
140
|
+
content = content_path.read_bytes()
|
|
141
|
+
content_size = len(content)
|
|
142
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
143
|
+
raise StudioError(
|
|
144
|
+
"CONVERSATION_ATTACHMENT_CORRUPT",
|
|
145
|
+
"会话附件元数据损坏",
|
|
146
|
+
status_code=409,
|
|
147
|
+
details={"attachmentRef": attachment_ref},
|
|
148
|
+
) from exc
|
|
149
|
+
actual_digest = hashlib.sha256(content).hexdigest()
|
|
150
|
+
if (
|
|
151
|
+
metadata.get("digest") != digest
|
|
152
|
+
or actual_digest != digest
|
|
153
|
+
or int(metadata.get("size") or -1) != content_size
|
|
154
|
+
):
|
|
155
|
+
raise StudioError(
|
|
156
|
+
"CONVERSATION_ATTACHMENT_CORRUPT",
|
|
157
|
+
"会话附件完整性校验失败",
|
|
158
|
+
status_code=409,
|
|
159
|
+
details={"attachmentRef": attachment_ref},
|
|
160
|
+
)
|
|
161
|
+
return StoredConversationAttachment(
|
|
162
|
+
attachment_ref=attachment_ref,
|
|
163
|
+
path=content_path,
|
|
164
|
+
name=str(metadata.get("name") or "attachment"),
|
|
165
|
+
media_type=str(metadata.get("mediaType") or "application/octet-stream"),
|
|
166
|
+
size=content_size,
|
|
167
|
+
digest=digest,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
@staticmethod
|
|
171
|
+
def _supported(content: bytes, *, filename: str, media_type: str) -> bool:
|
|
172
|
+
if media_type.startswith("image/"):
|
|
173
|
+
return True
|
|
174
|
+
if (
|
|
175
|
+
media_type.startswith("text/")
|
|
176
|
+
or media_type in _TEXT_MEDIA_TYPES
|
|
177
|
+
or Path(filename).suffix.lower() in _TEXT_SUFFIXES
|
|
178
|
+
):
|
|
179
|
+
try:
|
|
180
|
+
content.decode("utf-8")
|
|
181
|
+
except UnicodeDecodeError:
|
|
182
|
+
return False
|
|
183
|
+
return True
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
__all__ = ["ConversationAttachmentStore", "StoredConversationAttachment"]
|
ksadk/studio/authoring.py
CHANGED
|
@@ -694,6 +694,16 @@ class AgentAuthoringService:
|
|
|
694
694
|
ignored.add(".git")
|
|
695
695
|
entries: list[dict[str, Any]] = []
|
|
696
696
|
for path in sorted(root.rglob("*"), key=lambda item: item.as_posix()):
|
|
697
|
+
relative = path.relative_to(root).as_posix()
|
|
698
|
+
# Studio state and VCS internals may legitimately contain symlinks
|
|
699
|
+
# (for example managed Node dependencies). They are outside the
|
|
700
|
+
# imported project contract, so prune them before applying the
|
|
701
|
+
# source-tree symlink safety check.
|
|
702
|
+
if any(
|
|
703
|
+
relative == ignored_dir or relative.startswith(ignored_dir + "/")
|
|
704
|
+
for ignored_dir in (".agentkit", ".git")
|
|
705
|
+
):
|
|
706
|
+
continue
|
|
697
707
|
if path.is_symlink():
|
|
698
708
|
raise StudioError(
|
|
699
709
|
"AUTHORING_SOURCE_UNSAFE",
|
|
@@ -703,10 +713,6 @@ class AgentAuthoringService:
|
|
|
703
713
|
)
|
|
704
714
|
if not path.is_file() or path.name in ignored:
|
|
705
715
|
continue
|
|
706
|
-
# 跳过 .agentkit / .git 目录下的文件
|
|
707
|
-
relative = path.relative_to(root).as_posix()
|
|
708
|
-
if any(relative.startswith(ignored_dir + "/") for ignored_dir in (".agentkit", ".git")):
|
|
709
|
-
continue
|
|
710
716
|
content = path.read_bytes()
|
|
711
717
|
entries.append(
|
|
712
718
|
{
|
|
@@ -278,7 +278,6 @@ class StudioAuthoringCoordinator:
|
|
|
278
278
|
resolved = (spec or default_agent_spec(template, description=description)).model_copy(
|
|
279
279
|
deep=True
|
|
280
280
|
)
|
|
281
|
-
canonical_runtime = self.backend.runtime_ref(agent_id, runtime_type)
|
|
282
281
|
proposed_runtime = resolved.runtime
|
|
283
282
|
if proposed_runtime is not None and proposed_runtime.type != runtime_type:
|
|
284
283
|
raise StudioError(
|
|
@@ -291,7 +290,18 @@ class StudioAuthoringCoordinator:
|
|
|
291
290
|
"specRuntimeType": proposed_runtime.type,
|
|
292
291
|
},
|
|
293
292
|
)
|
|
294
|
-
if
|
|
293
|
+
if runtime_type == "plugin":
|
|
294
|
+
if proposed_runtime is None or proposed_runtime.provider_ref is None:
|
|
295
|
+
raise StudioError(
|
|
296
|
+
"AGENT_PROVIDER_REFERENCE_REQUIRED",
|
|
297
|
+
"外部 AgentProvider 必须选择一个已安装的精确版本",
|
|
298
|
+
status_code=422,
|
|
299
|
+
field="spec.runtime.providerRef",
|
|
300
|
+
)
|
|
301
|
+
canonical_runtime = proposed_runtime.model_copy(deep=True)
|
|
302
|
+
else:
|
|
303
|
+
canonical_runtime = self.backend.runtime_ref(agent_id, runtime_type)
|
|
304
|
+
if proposed_runtime is not None and runtime_type != "plugin":
|
|
295
305
|
if runtime_type == "codex" and proposed_runtime.version:
|
|
296
306
|
canonical_runtime.version = proposed_runtime.version
|
|
297
307
|
elif runtime_type in {"adk", "langgraph"}:
|
ksadk/studio/builder.py
CHANGED
|
@@ -10,7 +10,14 @@ from datetime import datetime, timezone
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
from uuid import uuid4
|
|
12
12
|
|
|
13
|
+
from ksadk.plugins.bundle_security import assert_bundle_security
|
|
14
|
+
from ksadk.plugins.contracts import CompositionProfile, PluginLock, plugin_lock_digest
|
|
15
|
+
from ksadk.plugins.resolver import ResolvedComposition
|
|
13
16
|
from ksadk.studio.capabilities import canonical_json, compute_bundle_digest, sha256_digest
|
|
17
|
+
from ksadk.studio.compatibility_report import (
|
|
18
|
+
build_bundle_compatibility_report,
|
|
19
|
+
compatibility_facts_digest,
|
|
20
|
+
)
|
|
14
21
|
from ksadk.studio.compiler import AgentCompiler
|
|
15
22
|
from ksadk.studio.contracts import (
|
|
16
23
|
AgentDraft,
|
|
@@ -24,6 +31,7 @@ from ksadk.studio.hosted_kernel import (
|
|
|
24
31
|
hosted_kernel_requirement_digest,
|
|
25
32
|
)
|
|
26
33
|
from ksadk.studio.repository import BuildRepository
|
|
34
|
+
from ksadk.studio.soul import render_soul_markdown
|
|
27
35
|
from ksadk.studio.workspace import Workspace
|
|
28
36
|
|
|
29
37
|
_ZIP_TIMESTAMP = (1980, 1, 1, 0, 0, 0)
|
|
@@ -43,29 +51,46 @@ class AgentBundleBuilder:
|
|
|
43
51
|
self.compiler = compiler or AgentCompiler(workspace)
|
|
44
52
|
self.repository = repository or BuildRepository(workspace)
|
|
45
53
|
|
|
46
|
-
def build(
|
|
54
|
+
def build(
|
|
55
|
+
self,
|
|
56
|
+
draft: AgentDraft,
|
|
57
|
+
*,
|
|
58
|
+
composition: ResolvedComposition | None = None,
|
|
59
|
+
) -> BuildRecord:
|
|
47
60
|
LOGGER.info(
|
|
48
61
|
"bundle build started: agent=%s revision=%s",
|
|
49
62
|
draft.metadata.id,
|
|
50
63
|
draft.metadata.revision,
|
|
51
64
|
)
|
|
52
65
|
compiled = self.compiler.compile(draft)
|
|
53
|
-
# Bundle v2
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
plugin_lock =
|
|
58
|
-
|
|
66
|
+
# Bundle v2 already carries a deterministic empty lock. P2-00A now
|
|
67
|
+
# validates that wire shape through PluginLock while deliberately not
|
|
68
|
+
# resolving or loading a PluginHost before P2-02/P2-03.
|
|
69
|
+
parsed_plugin_lock = composition.plugin_lock if composition else PluginLock()
|
|
70
|
+
plugin_lock = parsed_plugin_lock.model_dump(
|
|
71
|
+
by_alias=True,
|
|
72
|
+
exclude_none=True,
|
|
73
|
+
mode="json",
|
|
74
|
+
)
|
|
75
|
+
plugin_lock_digest_value = plugin_lock_digest(parsed_plugin_lock)
|
|
76
|
+
composition_profile = composition.profile if composition else None
|
|
77
|
+
composition_profile_digest_value = composition.profile_digest if composition else None
|
|
59
78
|
runtime_type, source_digest, runtime_lock = self._runtime_snapshot(draft, compiled)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"runtime": runtime_lock,
|
|
65
|
-
"sourceDigest": source_digest,
|
|
66
|
-
}
|
|
67
|
-
)
|
|
79
|
+
compatibility_facts_digest_value = compatibility_facts_digest(
|
|
80
|
+
draft=draft,
|
|
81
|
+
composition=composition,
|
|
82
|
+
runtime_lock=runtime_lock,
|
|
68
83
|
)
|
|
84
|
+
resolved_digest_payload = {
|
|
85
|
+
"compatibilityFactsDigest": compatibility_facts_digest_value,
|
|
86
|
+
"definitionDigest": compiled.resolved.resolved_digest,
|
|
87
|
+
"runtime": runtime_lock,
|
|
88
|
+
"sourceDigest": source_digest,
|
|
89
|
+
}
|
|
90
|
+
if composition is not None:
|
|
91
|
+
resolved_digest_payload["compositionProfileDigest"] = composition_profile_digest_value
|
|
92
|
+
resolved_digest_payload["pluginLockDigest"] = plugin_lock_digest_value
|
|
93
|
+
resolved_digest = sha256_digest(canonical_json(resolved_digest_payload))
|
|
69
94
|
short_digest = resolved_digest.removeprefix("sha256:")[:20]
|
|
70
95
|
build_id = f"build_{short_digest}"
|
|
71
96
|
final_dir = self.workspace.resolve(Path("dist") / draft.metadata.id / build_id)
|
|
@@ -98,13 +123,32 @@ class AgentBundleBuilder:
|
|
|
98
123
|
runtime_lock=runtime_lock,
|
|
99
124
|
resolved_digest=resolved_digest,
|
|
100
125
|
plugin_lock=plugin_lock,
|
|
126
|
+
composition_profile=composition_profile,
|
|
127
|
+
composition_profile_digest_value=composition_profile_digest_value,
|
|
101
128
|
hosted_kernel_requirement=hosted_kernel_requirement,
|
|
102
129
|
hosted_kernel_requirement_digest_value=hosted_kernel_requirement_digest_value,
|
|
130
|
+
compatibility_facts_digest_value=compatibility_facts_digest_value,
|
|
131
|
+
)
|
|
132
|
+
self._write_json(
|
|
133
|
+
bundle_root / "compatibility-report.json",
|
|
134
|
+
build_bundle_compatibility_report(
|
|
135
|
+
draft=draft,
|
|
136
|
+
composition=composition,
|
|
137
|
+
runtime_lock=runtime_lock,
|
|
138
|
+
resolved_digest=resolved_digest,
|
|
139
|
+
facts_digest=compatibility_facts_digest_value,
|
|
140
|
+
plugin_lock_digest=plugin_lock_digest_value,
|
|
141
|
+
composition_profile_digest=composition_profile_digest_value,
|
|
142
|
+
),
|
|
103
143
|
)
|
|
104
144
|
self._write_json(
|
|
105
145
|
bundle_root / "hosted-kernel-requirements.json",
|
|
106
146
|
hosted_kernel_requirement,
|
|
107
147
|
)
|
|
148
|
+
# Secrets are references at every declarative boundary. Scan the
|
|
149
|
+
# final materialized Bundle before its file manifest/digest are
|
|
150
|
+
# sealed, so an accidental literal cannot become a deployable ZIP.
|
|
151
|
+
assert_bundle_security(bundle_root)
|
|
108
152
|
# The manifest is a complete content declaration. Write this
|
|
109
153
|
# auxiliary checksum file first, then include it in the manifest
|
|
110
154
|
# entries; otherwise a Server-side full-membership check correctly
|
|
@@ -118,12 +162,21 @@ class AgentBundleBuilder:
|
|
|
118
162
|
resolved_digest=resolved_digest,
|
|
119
163
|
runtime_type=runtime_type,
|
|
120
164
|
source_digest=source_digest,
|
|
121
|
-
plugin_lock_digest=
|
|
165
|
+
plugin_lock_digest=plugin_lock_digest_value,
|
|
166
|
+
composition_mode="composed" if composition is not None else "legacy",
|
|
167
|
+
composition_profile_digest=composition_profile_digest_value,
|
|
122
168
|
hosted_kernel_requirement_digest=hosted_kernel_requirement_digest_value,
|
|
123
169
|
files=files,
|
|
124
170
|
)
|
|
125
171
|
manifest.bundle_digest = compute_bundle_digest(manifest)
|
|
126
|
-
|
|
172
|
+
# Keep the on-disk manifest on the same ``exclude_none`` wire
|
|
173
|
+
# projection used by ``compute_bundle_digest``. New v2 archives
|
|
174
|
+
# always state whether they select legacy or composed execution;
|
|
175
|
+
# only historical archives may omit that discriminator.
|
|
176
|
+
self._write_json(
|
|
177
|
+
bundle_root / "manifest.json",
|
|
178
|
+
manifest.model_dump(by_alias=True, exclude_none=True),
|
|
179
|
+
)
|
|
127
180
|
archive = staging / "agent-bundle.zip"
|
|
128
181
|
self._write_zip(bundle_root, archive)
|
|
129
182
|
final_dir.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -166,8 +219,11 @@ class AgentBundleBuilder:
|
|
|
166
219
|
runtime_lock: dict,
|
|
167
220
|
resolved_digest: str,
|
|
168
221
|
plugin_lock: dict,
|
|
222
|
+
composition_profile: CompositionProfile | None,
|
|
223
|
+
composition_profile_digest_value: str | None,
|
|
169
224
|
hosted_kernel_requirement: dict,
|
|
170
225
|
hosted_kernel_requirement_digest_value: str,
|
|
226
|
+
compatibility_facts_digest_value: str,
|
|
171
227
|
) -> None:
|
|
172
228
|
definition_digest = compiled.resolved.resolved_digest
|
|
173
229
|
resolved_payload = compiled.resolved.model_dump(
|
|
@@ -186,14 +242,30 @@ class AgentBundleBuilder:
|
|
|
186
242
|
self._write_json(root / "agentkit.lock", dependency_lock)
|
|
187
243
|
self._write_json(root / "runtime-lock.json", runtime_lock)
|
|
188
244
|
self._write_json(root / "plugin-lock.json", plugin_lock)
|
|
245
|
+
if composition_profile is not None:
|
|
246
|
+
# A resolved profile is an immutable composition input, not a
|
|
247
|
+
# second editable Agent spec. It is only written once its
|
|
248
|
+
# deterministic lock has already been resolved by PluginRegistry.
|
|
249
|
+
self._write_json(
|
|
250
|
+
root / "composition-profile.json",
|
|
251
|
+
composition_profile.model_dump(
|
|
252
|
+
by_alias=True,
|
|
253
|
+
exclude_none=True,
|
|
254
|
+
mode="json",
|
|
255
|
+
),
|
|
256
|
+
)
|
|
189
257
|
instructions = root / "instructions"
|
|
190
258
|
instructions.mkdir()
|
|
191
259
|
(instructions / "system.md").write_text(
|
|
192
|
-
|
|
260
|
+
compiled.resolved.instructions.system.rstrip() + "\n", encoding="utf-8"
|
|
193
261
|
)
|
|
194
262
|
(instructions / "task.md").write_text(
|
|
195
|
-
|
|
263
|
+
compiled.resolved.instructions.task.rstrip() + "\n", encoding="utf-8"
|
|
196
264
|
)
|
|
265
|
+
if compiled.resolved.soul is not None:
|
|
266
|
+
(instructions / "soul.md").write_text(
|
|
267
|
+
render_soul_markdown(compiled.resolved.soul), encoding="utf-8"
|
|
268
|
+
)
|
|
197
269
|
for skill in compiled.resolved.capabilities.skills:
|
|
198
270
|
source = self.workspace.resolve(
|
|
199
271
|
Path("capabilities/skills") / skill["name"],
|
|
@@ -238,25 +310,33 @@ class AgentBundleBuilder:
|
|
|
238
310
|
"components": components,
|
|
239
311
|
},
|
|
240
312
|
)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
"
|
|
252
|
-
"
|
|
253
|
-
"requirementsPath": "hosted-kernel-requirements.json",
|
|
254
|
-
"requirementDigest": hosted_kernel_requirement_digest_value,
|
|
255
|
-
"contractSet": hosted_kernel_requirement["kernelContract"]["set"],
|
|
256
|
-
"contractDigest": hosted_kernel_requirement["kernelContract"]["digest"],
|
|
257
|
-
},
|
|
313
|
+
provenance = {
|
|
314
|
+
"format": "agentkit.provenance/v1",
|
|
315
|
+
"agentId": draft.metadata.id,
|
|
316
|
+
"sourceRevision": draft.metadata.revision,
|
|
317
|
+
"sourceDigest": compiled.resolved.source_digest,
|
|
318
|
+
"definitionDigest": definition_digest,
|
|
319
|
+
"resolvedDigest": resolved_digest,
|
|
320
|
+
"compilerVersion": compiled.resolved.compiler_version,
|
|
321
|
+
"runtimeContract": "agentkit.runtime/v1",
|
|
322
|
+
"compatibility": {
|
|
323
|
+
"reportPath": "compatibility-report.json",
|
|
324
|
+
"factsDigest": compatibility_facts_digest_value,
|
|
258
325
|
},
|
|
259
|
-
|
|
326
|
+
"hostedKernel": {
|
|
327
|
+
"requirementsPath": "hosted-kernel-requirements.json",
|
|
328
|
+
"requirementDigest": hosted_kernel_requirement_digest_value,
|
|
329
|
+
"contractSet": hosted_kernel_requirement["kernelContract"]["set"],
|
|
330
|
+
"contractDigest": hosted_kernel_requirement["kernelContract"]["digest"],
|
|
331
|
+
},
|
|
332
|
+
}
|
|
333
|
+
if composition_profile is not None:
|
|
334
|
+
provenance["composition"] = {
|
|
335
|
+
"profilePath": "composition-profile.json",
|
|
336
|
+
"profileDigest": composition_profile_digest_value,
|
|
337
|
+
"pluginLockDigest": sha256_digest(canonical_json(plugin_lock)),
|
|
338
|
+
}
|
|
339
|
+
self._write_json(root / "provenance.json", provenance)
|
|
260
340
|
|
|
261
341
|
def _runtime_snapshot(self, draft: AgentDraft, compiled) -> tuple[str, str, dict]:
|
|
262
342
|
runtime = draft.spec.runtime
|
|
@@ -269,9 +349,7 @@ class AgentBundleBuilder:
|
|
|
269
349
|
content = path.read_bytes()
|
|
270
350
|
relative = path.relative_to(source_root).as_posix()
|
|
271
351
|
digest = f"sha256:{hashlib.sha256(content).hexdigest()}"
|
|
272
|
-
source_files.append(
|
|
273
|
-
{"path": relative, "sha256": digest, "size": len(content)}
|
|
274
|
-
)
|
|
352
|
+
source_files.append({"path": relative, "sha256": digest, "size": len(content)})
|
|
275
353
|
source_digest = sha256_digest(canonical_json(source_files))
|
|
276
354
|
bound_models = [
|
|
277
355
|
item.model for item in self.compiler.catalog.resolve_models(draft.spec.bindings)
|
|
@@ -290,9 +368,11 @@ class AgentBundleBuilder:
|
|
|
290
368
|
"model": compiled.resolved.model.model,
|
|
291
369
|
"models": list(dict.fromkeys(bound_models)),
|
|
292
370
|
}
|
|
293
|
-
return
|
|
294
|
-
|
|
295
|
-
|
|
371
|
+
return (
|
|
372
|
+
runtime_type,
|
|
373
|
+
source_digest,
|
|
374
|
+
{key: value for key, value in lock.items() if value is not None},
|
|
375
|
+
)
|
|
296
376
|
|
|
297
377
|
def _copy_runtime_source(self, bundle_root: Path, draft: AgentDraft) -> None:
|
|
298
378
|
runtime = draft.spec.runtime
|
ksadk/studio/cloud.py
CHANGED
|
@@ -1151,6 +1151,7 @@ class DirectAgentEngineCloudDeploymentGateway:
|
|
|
1151
1151
|
*,
|
|
1152
1152
|
session_id: str,
|
|
1153
1153
|
after_seq_id: int | None = None,
|
|
1154
|
+
offset: int | None = None,
|
|
1154
1155
|
limit: int = 200,
|
|
1155
1156
|
) -> dict[str, Any]:
|
|
1156
1157
|
"""Read canonical events, including public Interaction/v1 frames."""
|
|
@@ -1160,6 +1161,7 @@ class DirectAgentEngineCloudDeploymentGateway:
|
|
|
1160
1161
|
agent_id=self._chat_agent_id(deployment),
|
|
1161
1162
|
session_id=session_id,
|
|
1162
1163
|
after_seq_id=after_seq_id,
|
|
1164
|
+
offset=offset,
|
|
1163
1165
|
limit=limit,
|
|
1164
1166
|
)
|
|
1165
1167
|
except AgentEngineAPIError as exc:
|
|
@@ -1922,6 +1924,7 @@ class CloudDeploymentService:
|
|
|
1922
1924
|
*,
|
|
1923
1925
|
session_id: str,
|
|
1924
1926
|
after_seq_id: int | None = None,
|
|
1927
|
+
offset: int | None = None,
|
|
1925
1928
|
limit: int = 200,
|
|
1926
1929
|
) -> dict[str, Any]:
|
|
1927
1930
|
deployment = await self._chat_target(deployment_id)
|
|
@@ -1936,6 +1939,7 @@ class CloudDeploymentService:
|
|
|
1936
1939
|
deployment,
|
|
1937
1940
|
session_id=session_id,
|
|
1938
1941
|
after_seq_id=after_seq_id,
|
|
1942
|
+
offset=offset,
|
|
1939
1943
|
limit=limit,
|
|
1940
1944
|
)
|
|
1941
1945
|
|
|
@@ -377,9 +377,17 @@ class CodexAgentService:
|
|
|
377
377
|
def detail(self, agent_id: str | None = None) -> dict:
|
|
378
378
|
snapshot = self.studio.codex_manifests.load(agent_id)
|
|
379
379
|
_mcp_bindings, unresolved_mcp = self._mcp_bindings(snapshot.manifest)
|
|
380
|
+
builds_view: list[dict] = []
|
|
381
|
+
for item in self._builds(snapshot.manifest.name):
|
|
382
|
+
view = self.build_view(item)
|
|
383
|
+
try:
|
|
384
|
+
view["isCurrent"] = self.studio.codex_builder.is_current(item)
|
|
385
|
+
except Exception:
|
|
386
|
+
view["isCurrent"] = True
|
|
387
|
+
builds_view.append(view)
|
|
380
388
|
return {
|
|
381
389
|
"draft": self._project(snapshot),
|
|
382
|
-
"builds":
|
|
390
|
+
"builds": builds_view,
|
|
383
391
|
"validation": {"valid": True, "level": "build", "diagnostics": []},
|
|
384
392
|
"manifestSha256": snapshot.manifest_sha256,
|
|
385
393
|
"sourcePath": self.studio.workspace.relative(snapshot.source_path),
|
|
@@ -505,6 +513,7 @@ class CodexAgentService:
|
|
|
505
513
|
system=manifest.prompt,
|
|
506
514
|
task=manifest.task_prompt or "",
|
|
507
515
|
)
|
|
516
|
+
draft.spec.soul = manifest.soul
|
|
508
517
|
draft.spec.bindings.model_profile_id = bindings[0]
|
|
509
518
|
draft.spec.bindings.model_profile_ids = bindings[1]
|
|
510
519
|
draft.spec.bindings.skills = skill_bindings
|
|
@@ -527,6 +536,7 @@ class CodexAgentService:
|
|
|
527
536
|
system=manifest.prompt,
|
|
528
537
|
task=manifest.task_prompt or "",
|
|
529
538
|
),
|
|
539
|
+
soul=manifest.soul,
|
|
530
540
|
bindings=AgentBindings(
|
|
531
541
|
model_profile_id=default_profile,
|
|
532
542
|
model_profile_ids=profiles,
|
|
@@ -576,6 +586,7 @@ class CodexAgentService:
|
|
|
576
586
|
models=models if len(models) > 1 else None,
|
|
577
587
|
prompt=prompt,
|
|
578
588
|
task_prompt=task_prompt,
|
|
589
|
+
soul=spec.soul,
|
|
579
590
|
skills=skill_ids or None,
|
|
580
591
|
mcp_servers=mcp_servers or None,
|
|
581
592
|
sandbox=spec.execution.sandbox,
|