agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/METADATA +9 -8
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/RECORD +482 -245
- ksadk/_build_provenance.json +1 -1
- ksadk/api/client.py +105 -91
- ksadk/builders/code_builder.py +36 -9
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +1 -0
- ksadk/cli/__init__.py +32 -3
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_plugin.py +6 -1
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +424 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +56 -298
- ksadk/common/auth.py +16 -10
- ksadk/configs/env_registry.py +29 -1
- ksadk/conversations/message_projection.py +135 -14
- ksadk/conversations/projector.py +4 -6
- ksadk/conversations/runtime_invocation.py +5 -0
- ksadk/conversations/runtime_payloads.py +1 -0
- ksadk/conversations/runtime_preparation.py +30 -27
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +5 -0
- ksadk/conversations/runtime_streaming.py +25 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/harness/config.py +2 -2
- ksadk/harness/runtime.py +27 -27
- ksadk/harness/tools.py +38 -13
- ksadk/interaction/provider.py +1 -0
- ksadk/interaction/providers/langgraph.py +1 -0
- ksadk/kernel/bootstrap.py +28 -4
- ksadk/kernel/ingress.py +15 -2
- ksadk/kernel/sqlite_store.py +27 -0
- ksadk/kernel/store.py +3 -0
- ksadk/kernel/worker.py +65 -10
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/models.py +7 -4
- ksadk/memory/provider_resolver.py +3 -0
- ksadk/model_proxy/server.py +10 -5
- ksadk/plugins/__init__.py +4 -0
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +4 -2
- ksadk/plugins/bridges/codex.py +120 -13
- ksadk/plugins/bridges/dsh.py +340 -156
- ksadk/plugins/builtins.py +35 -36
- ksadk/plugins/bundle_security.py +28 -4
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/composition.py +8 -0
- ksadk/plugins/contracts.py +118 -0
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_toolchain.py +110 -21
- ksadk/plugins/ecosystem_probe.py +6 -6
- ksadk/plugins/host.py +102 -39
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +23 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +870 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +92 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +15 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/codex.py +335 -69
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh_capabilities.py +1389 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +118 -113
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/resolver.py +8 -1
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +74 -6
- ksadk/runners/adk_runner.py +149 -11
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +475 -145
- ksadk/runtime/_runner_adapter/stream_mapping.py +142 -18
- ksadk/runtime/adapter.py +2 -0
- ksadk/runtime/conversation_execution.py +92 -16
- ksadk/runtime/executor.py +78 -2
- ksadk/runtime/factory.py +29 -273
- ksadk/runtime/framework_adapters.py +23 -0
- ksadk/runtime/preprocessing.py +10 -2
- ksadk/runtime/runner_adapter.py +73 -14
- ksadk/runtime_context.py +40 -2
- ksadk/sandbox/backends/e2b.py +52 -11
- ksadk/sandbox/backends/local_process.py +9 -0
- ksadk/sandbox/base.py +2 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/scheduler/sqlite_store.py +18 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/control.py +210 -46
- ksadk/server/routes/dependencies.py +15 -0
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/sessions.py +284 -107
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-CGbWlMNh.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-b4C7upmO.js} +3 -3
- ksadk/server/static/assets/{MathMessageMarkdown-D9uB55Oh.js → MathMessageMarkdown-DbdW5A4_.js} +4 -4
- ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-BEBN4Ksz.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-zvL-WpAn.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-BYafW7Za.js} +1 -1
- ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-bTohInsS.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-Ch5Lbzsi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-kqF4MDOG.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-8uSRIODv.js} +1 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-DkhehZDr.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BdXhtPe9.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DPTpvpwi.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-Pqoh38el.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-DeU00qC-.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-CzxScFkr.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-DpqMx-ux.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-C6t0SypQ.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-DVaeafZk.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-Bf9D3tzJ.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-B9cY3iTz.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-CSwlx3CB.js} +1 -1
- ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-UBpgon5q.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-C9akhN9a.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CgedhTPI.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Cjucz5BY.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-Dd4Vleyn.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-CZ2jGtYW.js} +1 -1
- ksadk/server/static/assets/{dist-DdRBIceA.js → dist-B2_CVgKv.js} +1 -1
- ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-B3FR1SKK.js} +1 -1
- ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-BIr4DSRq.js} +1 -1
- ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-BgV_owcB.js} +1 -1
- ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-Bj730Ib4.js} +1 -1
- ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-BnaTiyzN.js} +1 -1
- ksadk/server/static/assets/{dist-C71CsujO.js → dist-C1NMAY5a.js} +1 -1
- ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-C5_ZAZsG.js} +1 -1
- ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-CB9iJrvg.js} +1 -1
- ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CFzsn6BG.js} +1 -1
- ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-Cf125P_m.js} +1 -1
- ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-ClYUxfeK.js} +1 -1
- ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-DFD6Qa6T.js} +1 -1
- ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DVCOWtha.js} +1 -1
- ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-D_ctSS2i.js} +1 -1
- ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-DiixqL0J.js} +1 -1
- ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-DoVSwoDb.js} +1 -1
- ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-DvFK7p5S.js} +1 -1
- ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-QfkEHOlb.js} +1 -1
- ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-btbmmX5O.js} +1 -1
- ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-fBO2v5Kt.js} +1 -1
- ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-ufY3F5p6.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-Ci8NqqZu.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-CCIOhLZG.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-Cp_r9Hb6.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.js} +1 -1
- ksadk/server/static/assets/index-DcTML1Up.css +2 -0
- ksadk/server/static/assets/index-Dh2XHqPK.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CO0rRTRA.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CHiaedSS.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-CHcCIB09.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-CJ_ebBZf.js} +1 -1
- ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-B4weu383.js} +1 -1
- ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-V-MgYHW1.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-CBijEX_c.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-Bc-pQvpp.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-D7genGLl.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-Bxj32zwD.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-BURv2mGh.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-CCsh3avW.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-_FRRBKEd.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-C-gr2o9M.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-D97NmfKg.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-DjrPC5FX.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-DzMNg1hh.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-Cssf_CsU.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-BWTHzyS1.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BSKgJsmR.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-eflHNoaZ.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-eYqrQ-v4.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/models.py +26 -4
- ksadk/skills/package_store.py +186 -38
- ksadk/skills/runtime/agent.py +31 -6
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/backends/e2b.py +98 -6
- ksadk/skills/runtime/backends/local.py +73 -8
- ksadk/skills/runtime/base.py +3 -0
- ksadk/skills/runtime/executor.py +2 -0
- ksadk/skills/runtime/loader.py +10 -2
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +31 -0
- ksadk/skills/service_client.py +167 -28
- ksadk/studio/api.py +224 -42
- ksadk/studio/api_catalog_routes.py +18 -0
- ksadk/studio/api_plugin_routes.py +526 -95
- ksadk/studio/api_resource_connections.py +183 -0
- ksadk/studio/authoring_coordinator.py +19 -14
- ksadk/studio/builder.py +76 -0
- ksadk/studio/cloud.py +342 -104
- ksadk/studio/cloud_shared_web.py +565 -0
- ksadk/studio/codex_agent_service.py +128 -26
- ksadk/studio/codex_builder.py +241 -2
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +31 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +184 -25
- ksadk/studio/compatibility_report.py +12 -1
- ksadk/studio/compiler.py +78 -14
- ksadk/studio/contracts.py +132 -6
- ksadk/studio/dsh_application.py +137 -0
- ksadk/studio/dsh_capability_service.py +1107 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +320 -13
- ksadk/studio/hosted_kernel.py +88 -13
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +2 -2
- ksadk/studio/plugin_composition.py +190 -23
- ksadk/studio/plugin_kernel_adapter.py +12 -112
- ksadk/studio/plugin_runtime.py +224 -45
- ksadk/studio/resource_authority.py +637 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +143 -2
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_service.py +462 -52
- ksadk/studio/runtime_source.py +15 -7
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +9 -0
- ksadk/studio/scheduler_service.py +3 -0
- ksadk/studio/service.py +490 -44
- ksadk/studio/shared_web.py +446 -62
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +41 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +44 -0
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CFmPl1de.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BRrGu8qt.js +38 -0
- ksadk/studio/static/assets/channel-BqO-gtEw.js +1 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-D220vUtq.js +62 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +2 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-C4DtVpCu.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DiQA-u2N.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-BSlbjT_b.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +1 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-M2m6G3j4.js +10 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-DezaQxiK.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DAyIVp5H.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DulomOrS.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-bHJYoflj.js +206 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-0BZ98mya.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-DLGry2Ap.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/index-CeHL9ARV.css +2 -0
- ksadk/studio/static/assets/index-D9QEcVpL.js +320 -0
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-CljI2wyf.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-D50Fo2sL.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-DimfOTam.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/line-CX5BOOUP.js +1 -0
- ksadk/studio/static/assets/linear-BCxN9JLv.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +7 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-Bizzqy5R.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-B9mrFSDF.js +39 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-NzUfCbMR.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-BF3d103U.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-SFn9St9H.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-DxmSSjRB.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-Ba1AOWoe.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js +7 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/version.py +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
- ksadk/server/static/assets/index-B2k_urY8.js +0 -241
- ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
- ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
"""Host-owned platform resource admission for explicit signed connections.
|
|
2
|
+
|
|
3
|
+
The first supported slice verifies a sub-account with IAM and proves read access
|
|
4
|
+
to one exact knowledge-base binding. Browser declarations are comparisons only;
|
|
5
|
+
they never become authority by being well formed or present in a catalogue.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from datetime import datetime, timedelta, timezone
|
|
16
|
+
from typing import Any, Literal
|
|
17
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
18
|
+
|
|
19
|
+
import requests
|
|
20
|
+
from pydantic import Field, model_validator
|
|
21
|
+
|
|
22
|
+
from ksadk.knowledge_base.client import KnowledgeBaseClient
|
|
23
|
+
from ksadk.memory.adk.backends.sdk_ltm_backend import SdkLTMBackend
|
|
24
|
+
from ksadk.plugins.contracts import PluginContractModel
|
|
25
|
+
from ksadk.resource_runtime.contracts import Identifier, ResourceConfig, ResourceRef
|
|
26
|
+
from ksadk.resource_runtime.ipc import ResourceOperation
|
|
27
|
+
from ksadk.skills.service_client import SkillServiceClient
|
|
28
|
+
from ksadk.studio.errors import StudioError
|
|
29
|
+
from ksadk.studio.resource_connections import (
|
|
30
|
+
ResolvedResourceCredentials,
|
|
31
|
+
ResourceConnectionRepository,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
_IAM_KRN = re.compile(r"^krn:ksc:iam::([^:]+):user/([^/]+)$")
|
|
35
|
+
_MAX_AUTHORITY_RESPONSE_BYTES = 1024 * 1024
|
|
36
|
+
_KSYUN_INTERNAL_HTTP_HOSTS = frozenset(
|
|
37
|
+
{
|
|
38
|
+
"iam.inner.api.ksyun.com",
|
|
39
|
+
"iam.internal.api.ksyun.com",
|
|
40
|
+
"aicp.inner.api.ksyun.com",
|
|
41
|
+
"aicp.internal.api.ksyun.com",
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _canonical_endpoint(
|
|
47
|
+
value: str,
|
|
48
|
+
*,
|
|
49
|
+
allow_loopback_http: bool,
|
|
50
|
+
allow_ksyun_internal_http: bool,
|
|
51
|
+
) -> str:
|
|
52
|
+
if any(char.isspace() for char in value) or "\\" in value:
|
|
53
|
+
raise ValueError("Resource authority endpoint is invalid")
|
|
54
|
+
parsed = urlsplit(value)
|
|
55
|
+
parsed.port
|
|
56
|
+
if (
|
|
57
|
+
parsed.scheme not in {"http", "https"}
|
|
58
|
+
or not parsed.hostname
|
|
59
|
+
or parsed.username is not None
|
|
60
|
+
or parsed.password is not None
|
|
61
|
+
or parsed.query
|
|
62
|
+
or parsed.fragment
|
|
63
|
+
):
|
|
64
|
+
raise ValueError("Resource authority endpoint must be an explicit HTTP service URL")
|
|
65
|
+
host = parsed.hostname.encode("idna").decode("ascii").lower()
|
|
66
|
+
if "%" in host:
|
|
67
|
+
raise ValueError("Resource authority endpoint hostname is invalid")
|
|
68
|
+
loopback_http = allow_loopback_http and host in {"127.0.0.1", "::1", "localhost"}
|
|
69
|
+
internal_http = (
|
|
70
|
+
parsed.scheme == "http"
|
|
71
|
+
and allow_ksyun_internal_http
|
|
72
|
+
and host in _KSYUN_INTERNAL_HTTP_HOSTS
|
|
73
|
+
)
|
|
74
|
+
if parsed.scheme != "https" and not (loopback_http or internal_http):
|
|
75
|
+
raise ValueError("Resource authority endpoints require HTTPS")
|
|
76
|
+
if internal_http and (parsed.port not in {None, 80} or parsed.path.rstrip("/")):
|
|
77
|
+
raise ValueError("Ksyun internal HTTP endpoints must use the service root")
|
|
78
|
+
if ":" in host:
|
|
79
|
+
host = f"[{host}]"
|
|
80
|
+
if parsed.port is not None and (parsed.scheme, parsed.port) not in {
|
|
81
|
+
("http", 80),
|
|
82
|
+
("https", 443),
|
|
83
|
+
}:
|
|
84
|
+
host += f":{parsed.port}"
|
|
85
|
+
return urlunsplit((parsed.scheme, host, parsed.path.rstrip("/"), "", ""))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class ResourceAuthorityPolicy(PluginContractModel):
|
|
89
|
+
"""Trusted host configuration; it is never populated from a Studio request."""
|
|
90
|
+
|
|
91
|
+
iam_endpoint: str
|
|
92
|
+
iam_region: Identifier = "cn-beijing-6"
|
|
93
|
+
allowed_data_endpoints: tuple[str, ...] = Field(min_length=1, max_length=16)
|
|
94
|
+
allowed_regions: tuple[Identifier, ...] = Field(min_length=1, max_length=32)
|
|
95
|
+
timeout_seconds: float = Field(default=10.0, gt=0, le=30)
|
|
96
|
+
grant_ttl_seconds: int = Field(default=60, strict=True, ge=5, le=600)
|
|
97
|
+
allow_loopback_http_for_tests: bool = Field(default=False, strict=True)
|
|
98
|
+
allow_ksyun_internal_http: bool = Field(default=False, strict=True)
|
|
99
|
+
|
|
100
|
+
@model_validator(mode="after")
|
|
101
|
+
def trusted_targets(self) -> ResourceAuthorityPolicy:
|
|
102
|
+
iam = _canonical_endpoint(
|
|
103
|
+
self.iam_endpoint,
|
|
104
|
+
allow_loopback_http=self.allow_loopback_http_for_tests,
|
|
105
|
+
allow_ksyun_internal_http=self.allow_ksyun_internal_http,
|
|
106
|
+
)
|
|
107
|
+
data = tuple(
|
|
108
|
+
_canonical_endpoint(
|
|
109
|
+
endpoint,
|
|
110
|
+
allow_loopback_http=self.allow_loopback_http_for_tests,
|
|
111
|
+
allow_ksyun_internal_http=self.allow_ksyun_internal_http,
|
|
112
|
+
)
|
|
113
|
+
for endpoint in self.allowed_data_endpoints
|
|
114
|
+
)
|
|
115
|
+
if len(data) != len(set(data)) or len(self.allowed_regions) != len(
|
|
116
|
+
set(self.allowed_regions)
|
|
117
|
+
):
|
|
118
|
+
raise ValueError("Resource authority targets must be unique")
|
|
119
|
+
object.__setattr__(self, "iam_endpoint", iam)
|
|
120
|
+
object.__setattr__(self, "allowed_data_endpoints", data)
|
|
121
|
+
return self
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class VerifiedResourceAuthority(PluginContractModel):
|
|
125
|
+
"""Short-lived, credential-free evidence produced only by the trusted host."""
|
|
126
|
+
|
|
127
|
+
schema_version: Literal[1] = 1
|
|
128
|
+
connection_ref: Identifier
|
|
129
|
+
connection_revision: int = Field(strict=True, ge=1)
|
|
130
|
+
tenant_ref: Identifier
|
|
131
|
+
resource_principal_ref: Identifier
|
|
132
|
+
resource: ResourceRef
|
|
133
|
+
allowed_operations: tuple[ResourceOperation, ...] = Field(min_length=1)
|
|
134
|
+
issuer_endpoint: str
|
|
135
|
+
issuer_region: Identifier
|
|
136
|
+
data_endpoint: str
|
|
137
|
+
observed_at: datetime
|
|
138
|
+
expires_at: datetime
|
|
139
|
+
request_id: str = Field(default="", max_length=256)
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def digest(self) -> str:
|
|
143
|
+
payload = self.model_dump(by_alias=True, mode="json")
|
|
144
|
+
raw = json.dumps(
|
|
145
|
+
payload, ensure_ascii=False, sort_keys=True, separators=(",", ":")
|
|
146
|
+
).encode()
|
|
147
|
+
return "sha256:" + hashlib.sha256(raw).hexdigest()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass(frozen=True)
|
|
151
|
+
class AdmittedResourceAccess:
|
|
152
|
+
"""Runtime-only authority proof paired with the exact verified credentials."""
|
|
153
|
+
|
|
154
|
+
authority: VerifiedResourceAuthority
|
|
155
|
+
credentials: ResolvedResourceCredentials = field(repr=False)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass(frozen=True)
|
|
159
|
+
class _VerifiedIamIdentity:
|
|
160
|
+
tenant_ref: str
|
|
161
|
+
principal_ref: str
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class _HardenedSdkTransport:
|
|
165
|
+
"""Use the SDK's request serialization/signing with a closed HTTP transport."""
|
|
166
|
+
|
|
167
|
+
def __init__(self, endpoint: str, *, timeout: float):
|
|
168
|
+
self.endpoint = endpoint
|
|
169
|
+
self.timeout = timeout
|
|
170
|
+
|
|
171
|
+
def send_request(self, request: Any):
|
|
172
|
+
from ksyun.common.http.request import ResponseInternal # type: ignore[import-untyped]
|
|
173
|
+
|
|
174
|
+
url = self.endpoint
|
|
175
|
+
path = str(request.uri or "")
|
|
176
|
+
if path not in {"", "/"}:
|
|
177
|
+
url += "/" + path.lstrip("/")
|
|
178
|
+
if request.uri_params:
|
|
179
|
+
url += "?" + request.uri_params
|
|
180
|
+
with requests.Session() as session:
|
|
181
|
+
session.trust_env = False
|
|
182
|
+
with session.request(
|
|
183
|
+
method=request.method,
|
|
184
|
+
url=url,
|
|
185
|
+
data=request.data,
|
|
186
|
+
headers=dict(request.header),
|
|
187
|
+
auth=request.auth,
|
|
188
|
+
timeout=self.timeout,
|
|
189
|
+
verify=True,
|
|
190
|
+
allow_redirects=False,
|
|
191
|
+
stream=True,
|
|
192
|
+
) as response:
|
|
193
|
+
if 300 <= response.status_code < 400:
|
|
194
|
+
raise RuntimeError("RESOURCE_AUTHORITY_REDIRECT_REFUSED")
|
|
195
|
+
declared_length = response.headers.get("Content-Length")
|
|
196
|
+
if declared_length and int(declared_length) > _MAX_AUTHORITY_RESPONSE_BYTES:
|
|
197
|
+
raise RuntimeError("RESOURCE_AUTHORITY_RESPONSE_TOO_LARGE")
|
|
198
|
+
chunks = []
|
|
199
|
+
size = 0
|
|
200
|
+
for chunk in response.iter_content(chunk_size=65536):
|
|
201
|
+
size += len(chunk)
|
|
202
|
+
if size > _MAX_AUTHORITY_RESPONSE_BYTES:
|
|
203
|
+
raise RuntimeError("RESOURCE_AUTHORITY_RESPONSE_TOO_LARGE")
|
|
204
|
+
chunks.append(chunk)
|
|
205
|
+
content = b"".join(chunks)
|
|
206
|
+
return ResponseInternal(
|
|
207
|
+
status=response.status_code,
|
|
208
|
+
header=dict(response.headers),
|
|
209
|
+
data=content.decode("utf-8", errors="strict"),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _response_object(value: Any) -> dict[str, Any]:
|
|
214
|
+
if isinstance(value, str):
|
|
215
|
+
if len(value.encode()) > _MAX_AUTHORITY_RESPONSE_BYTES:
|
|
216
|
+
raise ValueError("oversized response")
|
|
217
|
+
value = json.loads(value)
|
|
218
|
+
if not isinstance(value, dict):
|
|
219
|
+
raise ValueError("invalid authority response")
|
|
220
|
+
metadata = value.get("ResponseMetadata", {})
|
|
221
|
+
if not isinstance(metadata, dict) or value.get("Error") or metadata.get("Error"):
|
|
222
|
+
raise ValueError("authority rejected the request")
|
|
223
|
+
code = value.get("Code")
|
|
224
|
+
if "Code" in value and not (
|
|
225
|
+
(type(code) is int and code in {0, 200})
|
|
226
|
+
or (type(code) is str and code in {"0", "200"})
|
|
227
|
+
):
|
|
228
|
+
raise ValueError("authority rejected the request")
|
|
229
|
+
return value
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _credential_values(credentials: ResolvedResourceCredentials) -> tuple[str, str, str, str]:
|
|
233
|
+
def reveal(value: Any) -> str:
|
|
234
|
+
return value.get_secret_value() if value is not None else ""
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
reveal(credentials.access_key),
|
|
238
|
+
reveal(credentials.secret_key),
|
|
239
|
+
reveal(credentials.session_token),
|
|
240
|
+
reveal(credentials.token),
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class SignedKnowledgeResourceAuthority:
|
|
245
|
+
"""Fail-closed admission for signed, read-oriented platform resources."""
|
|
246
|
+
|
|
247
|
+
def __init__(
|
|
248
|
+
self,
|
|
249
|
+
connections: ResourceConnectionRepository,
|
|
250
|
+
policy: ResourceAuthorityPolicy,
|
|
251
|
+
) -> None:
|
|
252
|
+
self.connections = connections
|
|
253
|
+
self.policy = policy
|
|
254
|
+
|
|
255
|
+
def admit(
|
|
256
|
+
self,
|
|
257
|
+
config: ResourceConfig,
|
|
258
|
+
*,
|
|
259
|
+
expected_connection_revision: int | None = None,
|
|
260
|
+
) -> VerifiedResourceAuthority:
|
|
261
|
+
return self.admit_runtime(
|
|
262
|
+
config,
|
|
263
|
+
expected_connection_revision=expected_connection_revision,
|
|
264
|
+
).authority
|
|
265
|
+
|
|
266
|
+
def resolve_signed_identity(self, access_key: str, secret_key: str) -> tuple[str, str]:
|
|
267
|
+
"""Resolve the host credential owner for an explicit connection declaration."""
|
|
268
|
+
|
|
269
|
+
identity = self._verify_identity(access_key, secret_key)
|
|
270
|
+
return identity.tenant_ref, identity.principal_ref
|
|
271
|
+
|
|
272
|
+
def admit_runtime(
|
|
273
|
+
self,
|
|
274
|
+
config: ResourceConfig,
|
|
275
|
+
*,
|
|
276
|
+
expected_connection_revision: int | None = None,
|
|
277
|
+
) -> AdmittedResourceAccess:
|
|
278
|
+
"""Return only credentials proven inside this exact admission transaction."""
|
|
279
|
+
|
|
280
|
+
resource = config.binding.resource
|
|
281
|
+
field = "spec.bindings.plugins.config.binding"
|
|
282
|
+
before = self.connections.get(config.binding.connection_ref)
|
|
283
|
+
if (
|
|
284
|
+
expected_connection_revision is not None
|
|
285
|
+
and before.revision != expected_connection_revision
|
|
286
|
+
):
|
|
287
|
+
raise StudioError(
|
|
288
|
+
"RESOURCE_CONNECTION_CHANGED", "资源连接已变更,请刷新后重试", status_code=409
|
|
289
|
+
)
|
|
290
|
+
target = before.target
|
|
291
|
+
if target.auth_mode != "signed":
|
|
292
|
+
raise StudioError(
|
|
293
|
+
"RESOURCE_AUTHORITY_UNSUPPORTED",
|
|
294
|
+
"当前可信准入首片仅支持签名子账号连接",
|
|
295
|
+
status_code=422,
|
|
296
|
+
field=field + ".connectionRef",
|
|
297
|
+
)
|
|
298
|
+
if target.endpoint not in self.policy.allowed_data_endpoints or (
|
|
299
|
+
resource.region not in self.policy.allowed_regions
|
|
300
|
+
):
|
|
301
|
+
raise StudioError(
|
|
302
|
+
"RESOURCE_AUTHORITY_TARGET_FORBIDDEN",
|
|
303
|
+
"资源数据面地址或区域未被当前宿主批准",
|
|
304
|
+
status_code=403,
|
|
305
|
+
field=field + ".resource",
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
credentials = self.connections.resolve_credentials(target)
|
|
309
|
+
values = _credential_values(credentials)
|
|
310
|
+
if not values[0] or not values[1] or values[2] or values[3]:
|
|
311
|
+
raise StudioError(
|
|
312
|
+
"RESOURCE_AUTHORITY_UNSUPPORTED",
|
|
313
|
+
"当前可信准入首片需要独立的 AK/SK 签名凭证",
|
|
314
|
+
status_code=422,
|
|
315
|
+
)
|
|
316
|
+
identity = self._verify_identity(values[0], values[1])
|
|
317
|
+
if (
|
|
318
|
+
identity.tenant_ref != target.tenant_ref
|
|
319
|
+
or identity.principal_ref != target.principal_ref
|
|
320
|
+
):
|
|
321
|
+
raise StudioError(
|
|
322
|
+
"RESOURCE_IDENTITY_MISMATCH",
|
|
323
|
+
"连接声明的租户或主体与当前签名凭证不一致",
|
|
324
|
+
status_code=403,
|
|
325
|
+
field=field + ".connectionRef",
|
|
326
|
+
)
|
|
327
|
+
if resource.kind == "knowledge-base":
|
|
328
|
+
request_id = self._prove_knowledge_read(
|
|
329
|
+
config, target.endpoint, values[0], values[1]
|
|
330
|
+
)
|
|
331
|
+
elif resource.kind == "memory-instance":
|
|
332
|
+
request_id = self._prove_memory_read(
|
|
333
|
+
config, target.endpoint, values[0], values[1]
|
|
334
|
+
)
|
|
335
|
+
else:
|
|
336
|
+
request_id = self._prove_skill_read(
|
|
337
|
+
config, target.endpoint, values[0], values[1]
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
after = self.connections.get(config.binding.connection_ref)
|
|
341
|
+
after_values = _credential_values(self.connections.resolve_credentials(after.target))
|
|
342
|
+
if after != before or after_values != values:
|
|
343
|
+
raise StudioError(
|
|
344
|
+
"RESOURCE_CONNECTION_CHANGED", "资源连接或凭证在准入期间发生变更", status_code=409
|
|
345
|
+
)
|
|
346
|
+
now = datetime.now(timezone.utc)
|
|
347
|
+
return AdmittedResourceAccess(
|
|
348
|
+
authority=VerifiedResourceAuthority(
|
|
349
|
+
connection_ref=target.connection_ref,
|
|
350
|
+
connection_revision=before.revision,
|
|
351
|
+
tenant_ref=identity.tenant_ref,
|
|
352
|
+
resource_principal_ref=identity.principal_ref,
|
|
353
|
+
resource=resource,
|
|
354
|
+
allowed_operations=resource_allowed_operations(config),
|
|
355
|
+
issuer_endpoint=self.policy.iam_endpoint,
|
|
356
|
+
issuer_region=self.policy.iam_region,
|
|
357
|
+
data_endpoint=target.endpoint,
|
|
358
|
+
observed_at=now,
|
|
359
|
+
expires_at=now + timedelta(seconds=self.policy.grant_ttl_seconds),
|
|
360
|
+
request_id=request_id,
|
|
361
|
+
),
|
|
362
|
+
credentials=credentials,
|
|
363
|
+
)
|
|
364
|
+
def _verify_identity(self, access_key: str, secret_key: str) -> _VerifiedIamIdentity:
|
|
365
|
+
try:
|
|
366
|
+
from ksyun.client.iam.v20151101.client import ( # type: ignore[import-untyped]
|
|
367
|
+
IamClient,
|
|
368
|
+
)
|
|
369
|
+
from ksyun.client.iam.v20151101.models import ( # type: ignore[import-untyped]
|
|
370
|
+
GetUserRequest,
|
|
371
|
+
ListAllUserAccessKeysRequest,
|
|
372
|
+
)
|
|
373
|
+
from ksyun.common.credential import Credential # type: ignore[import-untyped]
|
|
374
|
+
from ksyun.common.profile.client_profile import ( # type: ignore[import-untyped]
|
|
375
|
+
ClientProfile,
|
|
376
|
+
)
|
|
377
|
+
from ksyun.common.profile.http_profile import ( # type: ignore[import-untyped]
|
|
378
|
+
HttpProfile,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
endpoint = urlsplit(self.policy.iam_endpoint)
|
|
382
|
+
profile = ClientProfile()
|
|
383
|
+
profile.httpProfile = HttpProfile(
|
|
384
|
+
protocol=endpoint.scheme,
|
|
385
|
+
endpoint=endpoint.netloc,
|
|
386
|
+
# The hardened transport owns the configured base path.
|
|
387
|
+
path="/",
|
|
388
|
+
reqMethod="POST",
|
|
389
|
+
reqTimeout=self.policy.timeout_seconds,
|
|
390
|
+
)
|
|
391
|
+
client = IamClient(
|
|
392
|
+
Credential(access_key, secret_key), self.policy.iam_region, profile
|
|
393
|
+
)
|
|
394
|
+
client.request = _HardenedSdkTransport(
|
|
395
|
+
self.policy.iam_endpoint, timeout=self.policy.timeout_seconds
|
|
396
|
+
)
|
|
397
|
+
listed = _response_object(client.ListAllUserAccessKeys(ListAllUserAccessKeysRequest()))
|
|
398
|
+
identity = self._identity_from_iam_listing(listed, access_key)
|
|
399
|
+
request = GetUserRequest()
|
|
400
|
+
request.UserName = identity
|
|
401
|
+
user_response = _response_object(client.GetUser(request))
|
|
402
|
+
return self._identity_from_iam_user(user_response, identity)
|
|
403
|
+
except StudioError:
|
|
404
|
+
raise
|
|
405
|
+
except Exception as error:
|
|
406
|
+
raise StudioError(
|
|
407
|
+
"RESOURCE_IDENTITY_UNVERIFIED",
|
|
408
|
+
"无法使用当前签名凭证验证平台子账号身份",
|
|
409
|
+
status_code=403,
|
|
410
|
+
) from error
|
|
411
|
+
|
|
412
|
+
@staticmethod
|
|
413
|
+
def _identity_from_iam_listing(response: dict[str, Any], access_key: str) -> str:
|
|
414
|
+
truncated = response.get("IsTruncated", False)
|
|
415
|
+
if type(truncated) is not bool or truncated or response.get("NextMarker"):
|
|
416
|
+
raise ValueError("incomplete access-key listing")
|
|
417
|
+
has_primary = "AccessKeyList" in response
|
|
418
|
+
has_alias = "AccessKeys" in response
|
|
419
|
+
if has_primary == has_alias:
|
|
420
|
+
raise ValueError("ambiguous access-key listing")
|
|
421
|
+
entries = response["AccessKeyList" if has_primary else "AccessKeys"]
|
|
422
|
+
if not isinstance(entries, list):
|
|
423
|
+
raise ValueError("invalid access-key listing")
|
|
424
|
+
matches = []
|
|
425
|
+
for entry in entries:
|
|
426
|
+
if not isinstance(entry, dict):
|
|
427
|
+
raise ValueError("invalid access-key entry")
|
|
428
|
+
has_key = "AccessKey" in entry
|
|
429
|
+
has_alias_key = "AccessKeyId" in entry
|
|
430
|
+
if has_key == has_alias_key:
|
|
431
|
+
raise ValueError("ambiguous access-key entry")
|
|
432
|
+
candidate = entry["AccessKey" if has_key else "AccessKeyId"]
|
|
433
|
+
user_name = entry.get("UserName")
|
|
434
|
+
if (
|
|
435
|
+
not isinstance(candidate, str)
|
|
436
|
+
or not candidate
|
|
437
|
+
or candidate != candidate.strip()
|
|
438
|
+
or not isinstance(user_name, str)
|
|
439
|
+
or not user_name
|
|
440
|
+
or user_name != user_name.strip()
|
|
441
|
+
):
|
|
442
|
+
raise ValueError("invalid access-key identity")
|
|
443
|
+
if candidate == access_key:
|
|
444
|
+
matches.append(user_name)
|
|
445
|
+
if len(matches) != 1:
|
|
446
|
+
raise ValueError("signed access key has no unique sub-account")
|
|
447
|
+
return matches[0]
|
|
448
|
+
|
|
449
|
+
@staticmethod
|
|
450
|
+
def _identity_from_iam_user(
|
|
451
|
+
response: dict[str, Any], expected_user_name: str
|
|
452
|
+
) -> _VerifiedIamIdentity:
|
|
453
|
+
result = response.get("GetUserResult")
|
|
454
|
+
user = result.get("User") if isinstance(result, dict) else None
|
|
455
|
+
if not isinstance(user, dict):
|
|
456
|
+
raise ValueError("invalid IAM user response")
|
|
457
|
+
user_id = user.get("UserId")
|
|
458
|
+
user_name = user.get("UserName", expected_user_name)
|
|
459
|
+
krn = user.get("Krn")
|
|
460
|
+
if not all(
|
|
461
|
+
isinstance(value, str) and value and value == value.strip()
|
|
462
|
+
for value in (user_id, user_name, krn)
|
|
463
|
+
):
|
|
464
|
+
raise ValueError("incomplete IAM user identity")
|
|
465
|
+
match = _IAM_KRN.fullmatch(krn)
|
|
466
|
+
if not match or user_name != expected_user_name or match.group(2) != user_name:
|
|
467
|
+
raise ValueError("IAM user identity is inconsistent")
|
|
468
|
+
return _VerifiedIamIdentity(tenant_ref=match.group(1), principal_ref=user_id)
|
|
469
|
+
|
|
470
|
+
def _prove_knowledge_read(
|
|
471
|
+
self,
|
|
472
|
+
config: ResourceConfig,
|
|
473
|
+
data_endpoint: str,
|
|
474
|
+
access_key: str,
|
|
475
|
+
secret_key: str,
|
|
476
|
+
) -> str:
|
|
477
|
+
endpoint = urlsplit(data_endpoint)
|
|
478
|
+
client = KnowledgeBaseClient(
|
|
479
|
+
dataset_id=config.binding.resource.id,
|
|
480
|
+
region=config.binding.resource.region,
|
|
481
|
+
endpoint=endpoint.netloc,
|
|
482
|
+
scheme=endpoint.scheme,
|
|
483
|
+
access_key=access_key,
|
|
484
|
+
secret_key=secret_key,
|
|
485
|
+
top_k=1,
|
|
486
|
+
)
|
|
487
|
+
try:
|
|
488
|
+
upstream = client._get_client()
|
|
489
|
+
upstream.request = _HardenedSdkTransport(
|
|
490
|
+
data_endpoint, timeout=self.policy.timeout_seconds
|
|
491
|
+
)
|
|
492
|
+
client.search("ksadk-resource-authority-probe", top_k=1)
|
|
493
|
+
if client.last_http_status != 200 or client.last_error:
|
|
494
|
+
raise ValueError("knowledge access was not proven")
|
|
495
|
+
return client.last_request_id
|
|
496
|
+
except Exception as error:
|
|
497
|
+
raise StudioError(
|
|
498
|
+
"RESOURCE_OPERATION_UNVERIFIED",
|
|
499
|
+
"当前签名主体未通过指定知识库的只读检索校验",
|
|
500
|
+
status_code=403,
|
|
501
|
+
) from error
|
|
502
|
+
|
|
503
|
+
def _prove_memory_read(
|
|
504
|
+
self,
|
|
505
|
+
config: ResourceConfig,
|
|
506
|
+
data_endpoint: str,
|
|
507
|
+
access_key: str,
|
|
508
|
+
secret_key: str,
|
|
509
|
+
) -> str:
|
|
510
|
+
endpoint = urlsplit(data_endpoint)
|
|
511
|
+
backend = SdkLTMBackend(
|
|
512
|
+
index="resource-authority",
|
|
513
|
+
memory_collection_id=config.binding.resource.id,
|
|
514
|
+
namespace=config.binding.resource.id,
|
|
515
|
+
agent_id="resource-authority",
|
|
516
|
+
region=config.binding.resource.region,
|
|
517
|
+
endpoint=endpoint.netloc,
|
|
518
|
+
scheme=endpoint.scheme,
|
|
519
|
+
access_key=access_key,
|
|
520
|
+
secret_key=secret_key,
|
|
521
|
+
)
|
|
522
|
+
try:
|
|
523
|
+
upstream = backend._get_client()
|
|
524
|
+
upstream.request = _HardenedSdkTransport(
|
|
525
|
+
data_endpoint, timeout=self.policy.timeout_seconds
|
|
526
|
+
)
|
|
527
|
+
backend.search_memory(
|
|
528
|
+
"ksadk-resource-authority",
|
|
529
|
+
"ksadk-resource-authority-probe",
|
|
530
|
+
top_k=1,
|
|
531
|
+
)
|
|
532
|
+
if backend.last_http_status != 200 or backend.last_error:
|
|
533
|
+
raise ValueError("memory access was not proven")
|
|
534
|
+
return "memory-read-proven"
|
|
535
|
+
except Exception as error:
|
|
536
|
+
raise StudioError(
|
|
537
|
+
"RESOURCE_OPERATION_UNVERIFIED",
|
|
538
|
+
"当前签名主体未通过指定记忆库的只读召回校验",
|
|
539
|
+
status_code=403,
|
|
540
|
+
) from error
|
|
541
|
+
|
|
542
|
+
def _prove_skill_read(
|
|
543
|
+
self,
|
|
544
|
+
config: ResourceConfig,
|
|
545
|
+
data_endpoint: str,
|
|
546
|
+
access_key: str,
|
|
547
|
+
secret_key: str,
|
|
548
|
+
) -> str:
|
|
549
|
+
client = SkillServiceClient(
|
|
550
|
+
base_url=data_endpoint,
|
|
551
|
+
access_key=access_key,
|
|
552
|
+
secret_key=secret_key,
|
|
553
|
+
region=config.binding.resource.region,
|
|
554
|
+
allow_env_fallback=False,
|
|
555
|
+
timeout=self.policy.timeout_seconds,
|
|
556
|
+
)
|
|
557
|
+
try:
|
|
558
|
+
listing = client.list_skills_by_space_id(
|
|
559
|
+
config.binding.resource.id, max_pages=1
|
|
560
|
+
)
|
|
561
|
+
if listing.space_id != config.binding.resource.id:
|
|
562
|
+
raise ValueError("skill space access was not proven")
|
|
563
|
+
return "skill-space-read-proven"
|
|
564
|
+
except Exception as error:
|
|
565
|
+
raise StudioError(
|
|
566
|
+
"RESOURCE_OPERATION_UNVERIFIED",
|
|
567
|
+
"当前签名主体未通过指定 Skill Space 的只读目录校验",
|
|
568
|
+
status_code=403,
|
|
569
|
+
) from error
|
|
570
|
+
finally:
|
|
571
|
+
client.close()
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def resource_allowed_operations(config: ResourceConfig) -> tuple[ResourceOperation, ...]:
|
|
575
|
+
"""Return the maximum host capability set for one admitted resource kind.
|
|
576
|
+
|
|
577
|
+
Activation policy narrows this set before issuing leases. Memory writes are
|
|
578
|
+
still fail-closed unless that activation also owns a write authorizer.
|
|
579
|
+
"""
|
|
580
|
+
|
|
581
|
+
kind = config.binding.resource.kind
|
|
582
|
+
if kind == "knowledge-base":
|
|
583
|
+
return ("search_knowledge_base",)
|
|
584
|
+
if kind == "memory-instance":
|
|
585
|
+
return ("load_memory", "save_memory", "memory_status")
|
|
586
|
+
return ("list_skills", "search_skills", "load_skill", "read_skill_resource")
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def resource_authority_policy_from_environment() -> ResourceAuthorityPolicy | None:
|
|
590
|
+
"""Build a trusted policy from operator-owned local Studio environment."""
|
|
591
|
+
|
|
592
|
+
access_key = os.environ.get("KSYUN_ACCESS_KEY", "").strip()
|
|
593
|
+
secret_key = os.environ.get("KSYUN_SECRET_KEY", "").strip()
|
|
594
|
+
endpoint = os.environ.get("AGENTENGINE_SERVER_URL", "").strip()
|
|
595
|
+
if not access_key or not secret_key or not endpoint:
|
|
596
|
+
return None
|
|
597
|
+
logical_region = (
|
|
598
|
+
os.environ.get("AGENTENGINE_REGION")
|
|
599
|
+
or os.environ.get("KSYUN_REGION")
|
|
600
|
+
or "cn-beijing-6"
|
|
601
|
+
).strip()
|
|
602
|
+
region = (
|
|
603
|
+
os.environ.get("AGENTENGINE_PRE_CONTROL_REGION", "cn-beijing-6").strip()
|
|
604
|
+
if logical_region.lower() == "pre-online"
|
|
605
|
+
else logical_region
|
|
606
|
+
)
|
|
607
|
+
iam_endpoint = os.environ.get("KSADK_RESOURCE_IAM_ENDPOINT", "").strip()
|
|
608
|
+
if not iam_endpoint:
|
|
609
|
+
try:
|
|
610
|
+
endpoint_host = (
|
|
611
|
+
(urlsplit(endpoint).hostname or "")
|
|
612
|
+
.encode("idna")
|
|
613
|
+
.decode("ascii")
|
|
614
|
+
.lower()
|
|
615
|
+
.rstrip(".")
|
|
616
|
+
)
|
|
617
|
+
except (UnicodeError, ValueError):
|
|
618
|
+
endpoint_host = ""
|
|
619
|
+
endpoint_labels = endpoint_host.split(".")
|
|
620
|
+
uses_ksyun_internal_dns = endpoint_labels[-4:] == [
|
|
621
|
+
"inner",
|
|
622
|
+
"api",
|
|
623
|
+
"ksyun",
|
|
624
|
+
"com",
|
|
625
|
+
]
|
|
626
|
+
iam_endpoint = (
|
|
627
|
+
"http://iam.inner.api.ksyun.com"
|
|
628
|
+
if uses_ksyun_internal_dns
|
|
629
|
+
else "https://iam.api.ksyun.com"
|
|
630
|
+
)
|
|
631
|
+
return ResourceAuthorityPolicy(
|
|
632
|
+
iam_endpoint=iam_endpoint,
|
|
633
|
+
iam_region=region,
|
|
634
|
+
allowed_data_endpoints=(endpoint,),
|
|
635
|
+
allowed_regions=(region,),
|
|
636
|
+
allow_ksyun_internal_http=True,
|
|
637
|
+
)
|