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,266 @@
|
|
|
1
|
+
"""Additive, provider-neutral conversation presentation contracts (v1)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _to_camel(value: str) -> str:
|
|
12
|
+
head, *tail = value.split("_")
|
|
13
|
+
return head + "".join(part.capitalize() for part in tail)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ConversationContractModel(BaseModel):
|
|
17
|
+
model_config = ConfigDict(
|
|
18
|
+
alias_generator=_to_camel,
|
|
19
|
+
populate_by_name=True,
|
|
20
|
+
extra="forbid",
|
|
21
|
+
frozen=True,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
_CAPABILITY = re.compile(r"^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$")
|
|
26
|
+
|
|
27
|
+
# Provider-neutral wire extensions. These keys are deliberately namespaced:
|
|
28
|
+
# the stable ConversationInput/v1 envelope must not grow a top-level field for
|
|
29
|
+
# every control exposed by Codex, DSH, or a future AgentProvider.
|
|
30
|
+
APPROVAL_MODE_EXTENSION = "ksadk.approval"
|
|
31
|
+
COLLABORATION_MODE_EXTENSION = "ksadk.collaboration"
|
|
32
|
+
GOAL_OBJECTIVE_EXTENSION = "ksadk.goal"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ConversationCapability(ConversationContractModel):
|
|
36
|
+
name: str = Field(min_length=1, max_length=128)
|
|
37
|
+
mode: Literal["native", "translated", "degraded", "unavailable"]
|
|
38
|
+
reason: str | None = Field(default=None, max_length=512)
|
|
39
|
+
|
|
40
|
+
@field_validator("name")
|
|
41
|
+
@classmethod
|
|
42
|
+
def validate_name(cls, value: str) -> str:
|
|
43
|
+
if not _CAPABILITY.fullmatch(value):
|
|
44
|
+
raise ValueError("capability name must be a namespaced identifier")
|
|
45
|
+
return value
|
|
46
|
+
|
|
47
|
+
@model_validator(mode="after")
|
|
48
|
+
def validate_reason(self) -> "ConversationCapability":
|
|
49
|
+
if self.mode in {"degraded", "unavailable"} and not self.reason:
|
|
50
|
+
raise ValueError("degraded or unavailable capability requires a reason")
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ConversationSurface(ConversationContractModel):
|
|
55
|
+
api_version: Literal["conversation.ksadk.io/v1"] = "conversation.ksadk.io/v1"
|
|
56
|
+
kind: Literal["ConversationSurface"] = "ConversationSurface"
|
|
57
|
+
surface_id: str = Field(min_length=1, max_length=256)
|
|
58
|
+
session_id: str = Field(min_length=1, max_length=256)
|
|
59
|
+
provider_ref: str = Field(min_length=1, max_length=256)
|
|
60
|
+
inputs: tuple[ConversationCapability, ...] = ()
|
|
61
|
+
outputs: tuple[ConversationCapability, ...] = ()
|
|
62
|
+
|
|
63
|
+
@model_validator(mode="after")
|
|
64
|
+
def validate_unique_capabilities(self) -> "ConversationSurface":
|
|
65
|
+
for capabilities, direction in ((self.inputs, "input"), (self.outputs, "output")):
|
|
66
|
+
names = [capability.name for capability in capabilities]
|
|
67
|
+
if len(names) != len(set(names)):
|
|
68
|
+
raise ValueError(
|
|
69
|
+
f"conversation surface must not repeat an {direction} capability"
|
|
70
|
+
)
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
def permits_input(self, field: str) -> bool:
|
|
74
|
+
return any(
|
|
75
|
+
capability.name == field and capability.mode in {"native", "translated"}
|
|
76
|
+
for capability in self.inputs
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class ConversationTextPart(ConversationContractModel):
|
|
81
|
+
kind: Literal["text"] = "text"
|
|
82
|
+
text: str = Field(min_length=1, max_length=131072)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class ConversationAttachmentPart(ConversationContractModel):
|
|
86
|
+
kind: Literal["attachment"] = "attachment"
|
|
87
|
+
attachment_ref: str = Field(min_length=1, max_length=2048)
|
|
88
|
+
media_type: str = Field(min_length=1, max_length=256)
|
|
89
|
+
name: str | None = Field(default=None, max_length=1024)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
ConversationInputPart = ConversationTextPart | ConversationAttachmentPart
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ConversationInput(ConversationContractModel):
|
|
96
|
+
"""A provider-neutral foreground turn submitted by a conversation client.
|
|
97
|
+
|
|
98
|
+
It deliberately carries only user intent. A Server/Runtime adapter maps
|
|
99
|
+
that intent to a provider-specific request after checking the active
|
|
100
|
+
ConversationSurface; browser clients never forward arbitrary provider
|
|
101
|
+
parameters.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
api_version: Literal["conversation.ksadk.io/v1"] = "conversation.ksadk.io/v1"
|
|
105
|
+
kind: Literal["ConversationInput"] = "ConversationInput"
|
|
106
|
+
input_id: str = Field(min_length=1, max_length=256)
|
|
107
|
+
session_id: str = Field(min_length=1, max_length=256)
|
|
108
|
+
idempotency_key: str = Field(min_length=1, max_length=512)
|
|
109
|
+
parts: tuple[ConversationInputPart, ...] = Field(min_length=1)
|
|
110
|
+
model_ref: str | None = Field(default=None, min_length=1, max_length=256)
|
|
111
|
+
reasoning: str | None = Field(default=None, min_length=1, max_length=64)
|
|
112
|
+
extensions: dict[str, Any] = Field(default_factory=dict)
|
|
113
|
+
|
|
114
|
+
@field_validator("extensions")
|
|
115
|
+
@classmethod
|
|
116
|
+
def validate_extensions(cls, value: dict[str, Any]) -> dict[str, Any]:
|
|
117
|
+
if any(not _CAPABILITY.fullmatch(key) or "." not in key for key in value):
|
|
118
|
+
raise ValueError("extensions must use namespaced capability keys")
|
|
119
|
+
approval = value.get(APPROVAL_MODE_EXTENSION)
|
|
120
|
+
if approval is not None and approval not in {"ask", "risk", "full"}:
|
|
121
|
+
raise ValueError("ksadk.approval must be ask, risk, or full")
|
|
122
|
+
collaboration = value.get(COLLABORATION_MODE_EXTENSION)
|
|
123
|
+
if collaboration is not None and collaboration not in {"default", "plan"}:
|
|
124
|
+
raise ValueError("ksadk.collaboration must be default or plan")
|
|
125
|
+
goal = value.get(GOAL_OBJECTIVE_EXTENSION)
|
|
126
|
+
if goal is not None and (
|
|
127
|
+
not isinstance(goal, str) or not goal.strip() or len(goal) > 4096
|
|
128
|
+
):
|
|
129
|
+
raise ValueError("ksadk.goal must be a non-empty string up to 4096 characters")
|
|
130
|
+
return value
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def approval_mode(self) -> Literal["ask", "risk", "full"] | None:
|
|
134
|
+
value = self.extensions.get(APPROVAL_MODE_EXTENSION)
|
|
135
|
+
return value if value in {"ask", "risk", "full"} else None
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def collaboration_mode(self) -> Literal["default", "plan"] | None:
|
|
139
|
+
value = self.extensions.get(COLLABORATION_MODE_EXTENSION)
|
|
140
|
+
return value if value in {"default", "plan"} else None
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def goal_objective(self) -> str | None:
|
|
144
|
+
value = self.extensions.get(GOAL_OBJECTIVE_EXTENSION)
|
|
145
|
+
return value if isinstance(value, str) and value else None
|
|
146
|
+
|
|
147
|
+
def required_capabilities(self) -> tuple[str, ...]:
|
|
148
|
+
required: list[str] = []
|
|
149
|
+
if any(isinstance(part, ConversationTextPart) for part in self.parts):
|
|
150
|
+
required.append("text")
|
|
151
|
+
for part in self.parts:
|
|
152
|
+
if not isinstance(part, ConversationAttachmentPart):
|
|
153
|
+
continue
|
|
154
|
+
required.append(
|
|
155
|
+
"attachment.image"
|
|
156
|
+
if part.media_type.lower().startswith("image/")
|
|
157
|
+
else "attachment.file"
|
|
158
|
+
)
|
|
159
|
+
if self.model_ref:
|
|
160
|
+
required.append("model.select")
|
|
161
|
+
if self.reasoning:
|
|
162
|
+
required.append("reasoning.effort")
|
|
163
|
+
if self.approval_mode:
|
|
164
|
+
required.append("approval")
|
|
165
|
+
if self.collaboration_mode == "plan":
|
|
166
|
+
required.append("plan")
|
|
167
|
+
if self.goal_objective:
|
|
168
|
+
required.append("goal")
|
|
169
|
+
extension_capabilities = {
|
|
170
|
+
APPROVAL_MODE_EXTENSION: "approval",
|
|
171
|
+
COLLABORATION_MODE_EXTENSION: "plan"
|
|
172
|
+
if self.collaboration_mode == "plan"
|
|
173
|
+
else None,
|
|
174
|
+
GOAL_OBJECTIVE_EXTENSION: "goal",
|
|
175
|
+
}
|
|
176
|
+
required.extend(
|
|
177
|
+
extension_capabilities.get(key, key)
|
|
178
|
+
for key in self.extensions
|
|
179
|
+
if extension_capabilities.get(key, key) is not None
|
|
180
|
+
)
|
|
181
|
+
return tuple(dict.fromkeys(required))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class ConversationItem(ConversationContractModel):
|
|
185
|
+
api_version: Literal["conversation.ksadk.io/v1"] = "conversation.ksadk.io/v1"
|
|
186
|
+
kind_version: Literal[1] = 1
|
|
187
|
+
item_id: str = Field(min_length=1, max_length=512)
|
|
188
|
+
parent_item_id: str | None = Field(default=None, min_length=1, max_length=512)
|
|
189
|
+
source_event_ids: tuple[str, ...] = Field(min_length=1)
|
|
190
|
+
session_id: str = Field(min_length=1, max_length=256)
|
|
191
|
+
run_id: str = Field(min_length=1, max_length=256)
|
|
192
|
+
kind: Literal[
|
|
193
|
+
"user_message",
|
|
194
|
+
"assistant_text",
|
|
195
|
+
"reasoning",
|
|
196
|
+
"tool_call",
|
|
197
|
+
"approval",
|
|
198
|
+
"progress",
|
|
199
|
+
"plan",
|
|
200
|
+
"goal",
|
|
201
|
+
"artifact",
|
|
202
|
+
"a2ui",
|
|
203
|
+
"error",
|
|
204
|
+
"unknown",
|
|
205
|
+
]
|
|
206
|
+
operation: Literal["append", "replace", "completed"]
|
|
207
|
+
lifecycle: Literal["pending", "streaming", "completed", "failed"]
|
|
208
|
+
visibility: Literal["public", "internal", "hidden"] = "public"
|
|
209
|
+
payload_schema_ref: str = Field(min_length=1, max_length=256)
|
|
210
|
+
payload: dict[str, Any] = Field(default_factory=dict)
|
|
211
|
+
capability_ref: str | None = Field(default=None, max_length=256)
|
|
212
|
+
native_ref: dict[str, Any] = Field(default_factory=dict)
|
|
213
|
+
|
|
214
|
+
@field_validator("source_event_ids")
|
|
215
|
+
@classmethod
|
|
216
|
+
def validate_source_event_ids(cls, value: tuple[str, ...]) -> tuple[str, ...]:
|
|
217
|
+
if any(not item for item in value) or len(value) != len(set(value)):
|
|
218
|
+
raise ValueError("sourceEventIds must be non-empty and unique")
|
|
219
|
+
return value
|
|
220
|
+
|
|
221
|
+
@model_validator(mode="after")
|
|
222
|
+
def validate_lifecycle(self) -> "ConversationItem":
|
|
223
|
+
if self.operation == "completed" and self.lifecycle not in {"completed", "failed"}:
|
|
224
|
+
raise ValueError("completed operation requires a terminal lifecycle")
|
|
225
|
+
return self
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def validate_surface_input(surface: ConversationSurface, payload: dict[str, Any]) -> None:
|
|
229
|
+
"""Reject UI input fields not declared by the active ConversationSurface."""
|
|
230
|
+
|
|
231
|
+
extensions = payload.get("extensions", {})
|
|
232
|
+
if extensions is not None and not isinstance(extensions, dict):
|
|
233
|
+
raise ValueError("extensions must be an object")
|
|
234
|
+
for field in payload:
|
|
235
|
+
if field == "extensions":
|
|
236
|
+
continue
|
|
237
|
+
if not surface.permits_input(field):
|
|
238
|
+
raise ValueError(f"conversation input is not declared by surface: {field}")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def validate_conversation_input(
|
|
242
|
+
surface: ConversationSurface,
|
|
243
|
+
conversation_input: ConversationInput,
|
|
244
|
+
) -> None:
|
|
245
|
+
"""Apply the same capability allowlist before and after the network hop."""
|
|
246
|
+
|
|
247
|
+
if surface.session_id != conversation_input.session_id:
|
|
248
|
+
raise ValueError("conversation input session does not match active surface")
|
|
249
|
+
for capability in conversation_input.required_capabilities():
|
|
250
|
+
if not surface.permits_input(capability):
|
|
251
|
+
raise ValueError(f"conversation input is not declared by surface: {capability}")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
__all__ = [
|
|
255
|
+
"APPROVAL_MODE_EXTENSION",
|
|
256
|
+
"COLLABORATION_MODE_EXTENSION",
|
|
257
|
+
"ConversationCapability",
|
|
258
|
+
"ConversationInput",
|
|
259
|
+
"ConversationAttachmentPart",
|
|
260
|
+
"ConversationItem",
|
|
261
|
+
"ConversationSurface",
|
|
262
|
+
"ConversationTextPart",
|
|
263
|
+
"GOAL_OBJECTIVE_EXTENSION",
|
|
264
|
+
"validate_conversation_input",
|
|
265
|
+
"validate_surface_input",
|
|
266
|
+
]
|
|
@@ -5,6 +5,8 @@ from typing import Any
|
|
|
5
5
|
from urllib.parse import quote
|
|
6
6
|
|
|
7
7
|
from ksadk.agui.a2ui_projection import project_a2ui_operations
|
|
8
|
+
|
|
9
|
+
|
|
8
10
|
def _event_metadata(event: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
9
11
|
metadata = event.get("Metadata")
|
|
10
12
|
return metadata if isinstance(metadata, Mapping) else {}
|
|
@@ -620,6 +622,7 @@ def _normalize_canonical_event(
|
|
|
620
622
|
normalized_metadata.update({"call_id": call_id, "tool_name": name, "tool_args": args})
|
|
621
623
|
elif item_kind == "data" and source.get("protocol") == "a2ui":
|
|
622
624
|
surface_id = str(source.get("metadata", {}).get("surface_id") or "")
|
|
625
|
+
source_metadata = source.get("metadata")
|
|
623
626
|
initial = runtime_event.get("initial") or {}
|
|
624
627
|
parts = initial.get("parts") if isinstance(initial, Mapping) else []
|
|
625
628
|
data: Any = {}
|
|
@@ -627,7 +630,16 @@ def _normalize_canonical_event(
|
|
|
627
630
|
if isinstance(part, Mapping) and part.get("content_type") == "data":
|
|
628
631
|
data = part.get("data")
|
|
629
632
|
break
|
|
630
|
-
if
|
|
633
|
+
if (
|
|
634
|
+
isinstance(data, list)
|
|
635
|
+
and isinstance(source_metadata, Mapping)
|
|
636
|
+
and source_metadata.get("operation_batch") is True
|
|
637
|
+
):
|
|
638
|
+
normalized["Content"] = {
|
|
639
|
+
"surface_id": surface_id,
|
|
640
|
+
"a2ui_operations": data,
|
|
641
|
+
}
|
|
642
|
+
elif isinstance(data, list):
|
|
631
643
|
normalized["Content"] = {"surface_id": surface_id, "components": data}
|
|
632
644
|
elif isinstance(data, Mapping):
|
|
633
645
|
normalized["Content"] = data
|
|
@@ -663,6 +675,12 @@ def _normalize_canonical_event(
|
|
|
663
675
|
normalized["Content"] = {"call_id": call_id, "name": "", "result": result}
|
|
664
676
|
normalized_metadata.update({"call_id": call_id, "tool_output": result})
|
|
665
677
|
elif item_kind == "data" and source.get("protocol") == "a2ui":
|
|
678
|
+
source_metadata = source.get("metadata")
|
|
679
|
+
if (
|
|
680
|
+
isinstance(source_metadata, Mapping)
|
|
681
|
+
and source_metadata.get("operation_batch") is True
|
|
682
|
+
):
|
|
683
|
+
return event
|
|
666
684
|
surface_id = str(source.get("metadata", {}).get("surface_id") or "")
|
|
667
685
|
normalized["EventType"] = "a2ui.surface.end"
|
|
668
686
|
normalized["Content"] = {"surface_id": surface_id}
|