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
|
@@ -8,13 +8,17 @@ import tempfile
|
|
|
8
8
|
import time
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
|
+
from ksadk.skills.package_store import SkillPackage
|
|
12
|
+
from ksadk.skills.runtime.artifact_delivery import export_artifacts, import_artifacts
|
|
11
13
|
from ksadk.skills.runtime.base import (
|
|
12
14
|
SandboxInputFile,
|
|
15
|
+
SkillRuntimeError,
|
|
13
16
|
SkillRuntimeResult,
|
|
14
17
|
format_skill_names_env,
|
|
15
18
|
normalize_skill_names,
|
|
16
19
|
parse_output_files,
|
|
17
20
|
)
|
|
21
|
+
from ksadk.skills.runtime.pinned import stage_packages
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
def _coerce_output(value: str | bytes | None) -> str:
|
|
@@ -45,14 +49,29 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
45
49
|
skill_names: list[str] | None = None,
|
|
46
50
|
env: dict[str, str] | None = None,
|
|
47
51
|
input_files: list[SandboxInputFile] | None = None,
|
|
52
|
+
pinned_packages: list[SkillPackage] | None = None,
|
|
48
53
|
timeout: int = 900,
|
|
49
54
|
) -> SkillRuntimeResult:
|
|
50
55
|
started = time.monotonic()
|
|
51
|
-
|
|
56
|
+
if pinned_packages is not None and self.agent_path.resolve() != (
|
|
57
|
+
Path(__file__).resolve().parents[1] / "agent.py"
|
|
58
|
+
):
|
|
59
|
+
raise ValueError("Pinned Skill execution requires the bundled runtime agent")
|
|
60
|
+
runtime_env = (
|
|
61
|
+
{
|
|
62
|
+
key: value
|
|
63
|
+
for key, value in os.environ.items()
|
|
64
|
+
if key in {"PATH", "LANG", "LC_ALL", "TMPDIR", "SYSTEMROOT"}
|
|
65
|
+
}
|
|
66
|
+
if pinned_packages is not None
|
|
67
|
+
else os.environ.copy()
|
|
68
|
+
)
|
|
52
69
|
runtime_env.update(env or {})
|
|
53
70
|
runtime_env["KSADK_SKILL_SPACE_IDS"] = ",".join(skill_space_ids)
|
|
54
71
|
runtime_env["SKILL_SPACE_ID"] = skill_space_ids[0] if skill_space_ids else ""
|
|
55
|
-
if
|
|
72
|
+
if pinned_packages is None and (
|
|
73
|
+
public_spaces := os.environ.get("KSADK_PUBLIC_SKILL_SPACE_IDS")
|
|
74
|
+
):
|
|
56
75
|
runtime_env["KSADK_PUBLIC_SKILL_SPACE_IDS"] = public_spaces
|
|
57
76
|
selected_skill_names = format_skill_names_env(skill_names)
|
|
58
77
|
if selected_skill_names:
|
|
@@ -62,12 +81,27 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
62
81
|
try:
|
|
63
82
|
with tempfile.TemporaryDirectory(prefix="ksadk-skill-runtime-") as tmp_dir:
|
|
64
83
|
request_path = Path(tmp_dir) / "workflow-request.json"
|
|
84
|
+
request = {
|
|
85
|
+
"workflow_prompt": workflow_prompt,
|
|
86
|
+
"skill_names": normalize_skill_names(skill_names),
|
|
87
|
+
}
|
|
88
|
+
if pinned_packages is not None:
|
|
89
|
+
entries = stage_packages(pinned_packages, Path(tmp_dir))
|
|
90
|
+
request["pinned_packages"] = [entry.model_dump() for entry in entries]
|
|
91
|
+
request["pinned_protocol_version"] = 1
|
|
92
|
+
if not runtime_env.get("KSADK_SKILL_WORKDIR"):
|
|
93
|
+
# Artifacts outlive the temporary archive delivery directory.
|
|
94
|
+
runtime_env["KSADK_SKILL_WORKDIR"] = tempfile.mkdtemp(
|
|
95
|
+
prefix="ksadk-pinned-artifacts-"
|
|
96
|
+
)
|
|
97
|
+
# Use the same canonical root in the child and host validator
|
|
98
|
+
# (macOS temporary directories may be reached through /var).
|
|
99
|
+
runtime_env["KSADK_SKILL_WORKDIR"] = str(
|
|
100
|
+
Path(runtime_env["KSADK_SKILL_WORKDIR"]).resolve()
|
|
101
|
+
)
|
|
65
102
|
request_path.write_text(
|
|
66
103
|
json.dumps(
|
|
67
|
-
|
|
68
|
-
"workflow_prompt": workflow_prompt,
|
|
69
|
-
"skill_names": normalize_skill_names(skill_names),
|
|
70
|
-
},
|
|
104
|
+
request,
|
|
71
105
|
ensure_ascii=False,
|
|
72
106
|
),
|
|
73
107
|
encoding="utf-8",
|
|
@@ -75,6 +109,7 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
75
109
|
completed = subprocess.run(
|
|
76
110
|
[
|
|
77
111
|
sys.executable,
|
|
112
|
+
*(["-I"] if pinned_packages is not None else []),
|
|
78
113
|
"-u",
|
|
79
114
|
str(self.agent_path),
|
|
80
115
|
"--request-file",
|
|
@@ -86,13 +121,43 @@ class LocalProcessSkillRuntimeBackend:
|
|
|
86
121
|
env=runtime_env,
|
|
87
122
|
check=False,
|
|
88
123
|
)
|
|
124
|
+
stdout = completed.stdout
|
|
125
|
+
output_files = parse_output_files(stdout)
|
|
126
|
+
if pinned_packages is not None:
|
|
127
|
+
payloads = [
|
|
128
|
+
json.loads(line.split("=", 1)[1])
|
|
129
|
+
for line in stdout.splitlines()
|
|
130
|
+
if line.startswith("workflow_result=")
|
|
131
|
+
]
|
|
132
|
+
if len(payloads) != 1 or not isinstance(payloads[0], dict):
|
|
133
|
+
raise SkillRuntimeError("Runtime did not return a unique workflow result")
|
|
134
|
+
payload = payloads[0]
|
|
135
|
+
paths = payload.get("output_files")
|
|
136
|
+
if not isinstance(paths, list) or any(not isinstance(p, str) for p in paths):
|
|
137
|
+
raise SkillRuntimeError("Runtime returned invalid artifact paths")
|
|
138
|
+
# Snapshot only bounded regular files from the admitted workspace.
|
|
139
|
+
# A workflow's stdout is not authority to read arbitrary host files.
|
|
140
|
+
bundle_path = Path(tmp_dir) / "artifacts.zip"
|
|
141
|
+
receipt = export_artifacts(
|
|
142
|
+
paths, Path(runtime_env["KSADK_SKILL_WORKDIR"]), bundle_path
|
|
143
|
+
)
|
|
144
|
+
output_files = import_artifacts(bundle_path.read_bytes(), receipt)
|
|
145
|
+
payload["output_files"] = output_files
|
|
146
|
+
payload["artifacts"] = output_files
|
|
147
|
+
payload["artifact_bundle"] = receipt.model_dump()
|
|
148
|
+
stdout = "\n".join(
|
|
149
|
+
"workflow_result=" + json.dumps(payload, ensure_ascii=False, sort_keys=True)
|
|
150
|
+
if line.startswith("workflow_result=")
|
|
151
|
+
else line
|
|
152
|
+
for line in stdout.splitlines()
|
|
153
|
+
) + "\n"
|
|
89
154
|
return SkillRuntimeResult(
|
|
90
155
|
runtime_id=f"local:{session_id}",
|
|
91
156
|
exit_code=completed.returncode,
|
|
92
|
-
stdout=
|
|
157
|
+
stdout=stdout,
|
|
93
158
|
stderr=completed.stderr,
|
|
94
159
|
duration_ms=int((time.monotonic() - started) * 1000),
|
|
95
|
-
output_files=
|
|
160
|
+
output_files=output_files,
|
|
96
161
|
)
|
|
97
162
|
except subprocess.TimeoutExpired as exc:
|
|
98
163
|
return SkillRuntimeResult(
|
ksadk/skills/runtime/base.py
CHANGED
|
@@ -5,6 +5,8 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Protocol, Sequence
|
|
7
7
|
|
|
8
|
+
from ksadk.skills.package_store import SkillPackage
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
class SkillRuntimeError(RuntimeError):
|
|
10
12
|
pass
|
|
@@ -56,6 +58,7 @@ class SkillRuntimeBackend(Protocol):
|
|
|
56
58
|
skill_names: list[str] | None = None,
|
|
57
59
|
env: dict[str, str] | None = None,
|
|
58
60
|
input_files: list[SandboxInputFile] | None = None,
|
|
61
|
+
pinned_packages: list[SkillPackage] | None = None,
|
|
59
62
|
timeout: int = 900,
|
|
60
63
|
) -> SkillRuntimeResult: ...
|
|
61
64
|
|
ksadk/skills/runtime/executor.py
CHANGED
|
@@ -27,6 +27,7 @@ class WorkflowExecution:
|
|
|
27
27
|
artifacts: list[str] = field(default_factory=list)
|
|
28
28
|
warnings: list[str] = field(default_factory=list)
|
|
29
29
|
error: str = ""
|
|
30
|
+
artifact_bundle: dict[str, object] | None = None
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
def execute_workflow(
|
|
@@ -136,6 +137,7 @@ def _run_generic_workflow(skill: LocalSkill, prompt: str) -> WorkflowExecution:
|
|
|
136
137
|
workdir = _skill_workdir()
|
|
137
138
|
workdir.mkdir(parents=True, exist_ok=True)
|
|
138
139
|
output_dir = workdir / "artifacts"
|
|
140
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
139
141
|
timeout = _runtime_timeout()
|
|
140
142
|
command = _run_command(
|
|
141
143
|
["bash", str(skill.root_dir / "scripts" / "run-workflow.sh")],
|
ksadk/skills/runtime/loader.py
CHANGED
|
@@ -49,10 +49,14 @@ def load_skills(
|
|
|
49
49
|
seen_names: set[str] = {skill.name.lower() for skill in skills if skill.name}
|
|
50
50
|
for space_id in registry.user_skill_space_ids():
|
|
51
51
|
listing = client.list_skills_by_space_id(space_id)
|
|
52
|
+
if listing.truncated:
|
|
53
|
+
warnings.append(
|
|
54
|
+
"Skill directory is incomplete; selection covers only retrieved entries"
|
|
55
|
+
)
|
|
52
56
|
selected_refs.extend(
|
|
53
57
|
registry.dedupe_skill_refs(
|
|
54
58
|
registry.select_remote_skill_refs(
|
|
55
|
-
listing.active_skills(),
|
|
59
|
+
listing.active_skills(allow_partial=True),
|
|
56
60
|
prompt,
|
|
57
61
|
skill_names=skill_names,
|
|
58
62
|
),
|
|
@@ -62,9 +66,13 @@ def load_skills(
|
|
|
62
66
|
|
|
63
67
|
if registry.public_skill_space_ids():
|
|
64
68
|
listing = client.list_available_premade_skills()
|
|
69
|
+
if listing.truncated:
|
|
70
|
+
warnings.append(
|
|
71
|
+
"Public Skill directory is incomplete; selection covers only retrieved entries"
|
|
72
|
+
)
|
|
65
73
|
selected_refs.extend(
|
|
66
74
|
registry.dedupe_skill_refs(
|
|
67
|
-
registry.select_public_skill_refs(listing.active_skills()),
|
|
75
|
+
registry.select_public_skill_refs(listing.active_skills(allow_partial=True)),
|
|
68
76
|
seen_names=seen_names,
|
|
69
77
|
)
|
|
70
78
|
)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Transport and consume exact Skill archives without directory discovery.
|
|
2
|
+
|
|
3
|
+
The trusted caller authorizes the package set before staging. This contract
|
|
4
|
+
verifies bytes at the consumer; it is not an authorization or sandbox boundary.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import hashlib
|
|
10
|
+
import os
|
|
11
|
+
import stat
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
15
|
+
|
|
16
|
+
from ksadk.skills.loader import LocalSkill, load_local_skill
|
|
17
|
+
from ksadk.skills.models import ContentHash, SkillRef
|
|
18
|
+
from ksadk.skills.package_store import PackageStore, SkillPackage, SkillPackageError
|
|
19
|
+
|
|
20
|
+
MAX_ARCHIVE_BYTES = 20 * 1024 * 1024
|
|
21
|
+
MAX_PACKAGES = 32
|
|
22
|
+
PINNED_PACKAGE_PROTOCOL_VERSION = 1
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PinnedSkillArchive(BaseModel):
|
|
26
|
+
model_config = ConfigDict(extra="forbid", frozen=True, hide_input_in_errors=True)
|
|
27
|
+
|
|
28
|
+
skill_id: str = Field(min_length=1, max_length=256, strict=True)
|
|
29
|
+
version_id: str = Field(min_length=1, max_length=256, strict=True)
|
|
30
|
+
name: str = Field(min_length=1, max_length=256, strict=True)
|
|
31
|
+
content_hash: str = Field(pattern=r"^sha256:[0-9a-f]{64}$", strict=True)
|
|
32
|
+
archive_name: str = Field(pattern=r"^[0-9a-f]{64}\.zip$", strict=True)
|
|
33
|
+
|
|
34
|
+
def skill_ref(self) -> SkillRef:
|
|
35
|
+
return SkillRef(
|
|
36
|
+
skill_id=self.skill_id,
|
|
37
|
+
version_id=self.version_id,
|
|
38
|
+
version="",
|
|
39
|
+
name=self.name,
|
|
40
|
+
content_hash=ContentHash.parse(self.content_hash),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def read_archive(path: Path) -> bytes:
|
|
45
|
+
"""Read a bounded regular archive, rejecting a symlink at the final component."""
|
|
46
|
+
descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
|
|
47
|
+
with os.fdopen(descriptor, "rb") as stream:
|
|
48
|
+
info = os.fstat(stream.fileno())
|
|
49
|
+
if not stat.S_ISREG(info.st_mode) or info.st_size > MAX_ARCHIVE_BYTES:
|
|
50
|
+
raise SkillPackageError("Pinned Skill archive is not a bounded regular file")
|
|
51
|
+
content = stream.read(MAX_ARCHIVE_BYTES + 1)
|
|
52
|
+
if len(content) > MAX_ARCHIVE_BYTES:
|
|
53
|
+
raise SkillPackageError("Pinned Skill archive exceeds size limit")
|
|
54
|
+
return content
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def validate_package_set(entries: tuple[PinnedSkillArchive, ...]) -> None:
|
|
58
|
+
if len(entries) > MAX_PACKAGES:
|
|
59
|
+
raise SkillPackageError("Too many pinned Skill packages")
|
|
60
|
+
if len({entry.skill_id for entry in entries}) != len(entries) or len(
|
|
61
|
+
{entry.name.casefold() for entry in entries}
|
|
62
|
+
) != len(entries):
|
|
63
|
+
raise SkillPackageError("Pinned Skill identities and names must be unique")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def stage_packages(packages: list[SkillPackage], directory: Path) -> tuple[PinnedSkillArchive, ...]:
|
|
67
|
+
"""Copy verified archives into a private request delivery directory."""
|
|
68
|
+
if len(packages) > MAX_PACKAGES:
|
|
69
|
+
raise SkillPackageError("Too many pinned Skill packages")
|
|
70
|
+
entries = tuple(
|
|
71
|
+
PinnedSkillArchive(
|
|
72
|
+
skill_id=package.ref.skill_id,
|
|
73
|
+
version_id=package.ref.version_id,
|
|
74
|
+
name=package.ref.name,
|
|
75
|
+
content_hash=package.ref.content_hash.render() if package.ref.content_hash else "",
|
|
76
|
+
archive_name=(package.ref.content_hash.value if package.ref.content_hash else "")
|
|
77
|
+
+ ".zip",
|
|
78
|
+
)
|
|
79
|
+
for package in packages
|
|
80
|
+
)
|
|
81
|
+
validate_package_set(entries)
|
|
82
|
+
for package, entry in zip(packages, entries, strict=True):
|
|
83
|
+
content = read_archive(package.archive_path)
|
|
84
|
+
if "sha256:" + hashlib.sha256(content).hexdigest() != entry.content_hash:
|
|
85
|
+
raise SkillPackageError("Pinned Skill archive digest mismatch")
|
|
86
|
+
target = directory / entry.archive_name
|
|
87
|
+
if target.exists():
|
|
88
|
+
if read_archive(target) != content:
|
|
89
|
+
raise SkillPackageError("Pinned Skill archive destination conflict")
|
|
90
|
+
continue
|
|
91
|
+
with target.open("xb") as output:
|
|
92
|
+
os.chmod(target, 0o600)
|
|
93
|
+
output.write(content)
|
|
94
|
+
return entries
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def load_pinned_packages(
|
|
98
|
+
entries: tuple[PinnedSkillArchive, ...], directory: Path
|
|
99
|
+
) -> list[LocalSkill]:
|
|
100
|
+
"""Use only supplied archives; never read environment Skill directories or APIs."""
|
|
101
|
+
validate_package_set(entries)
|
|
102
|
+
store = PackageStore(
|
|
103
|
+
directory / "extracted-packages", namespace="pinned-request", require_hash=True
|
|
104
|
+
)
|
|
105
|
+
skills = []
|
|
106
|
+
for entry in entries:
|
|
107
|
+
package = store.store_archive(
|
|
108
|
+
entry.skill_ref(), read_archive(directory / entry.archive_name)
|
|
109
|
+
)
|
|
110
|
+
skill = load_local_skill(package.root_dir)
|
|
111
|
+
if skill.name != entry.name:
|
|
112
|
+
raise SkillPackageError("Pinned Skill name does not match its manifest")
|
|
113
|
+
skills.append(skill)
|
|
114
|
+
return skills
|
ksadk/skills/runtime/request.py
CHANGED
|
@@ -5,7 +5,11 @@ from dataclasses import dataclass, field
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
+
from pydantic import ValidationError
|
|
9
|
+
|
|
10
|
+
from ksadk.skills.package_store import SkillPackageError
|
|
8
11
|
from ksadk.skills.runtime.base import normalize_skill_names
|
|
12
|
+
from ksadk.skills.runtime.pinned import PinnedSkillArchive, validate_package_set
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
class SkillWorkflowRequestError(ValueError):
|
|
@@ -16,6 +20,9 @@ class SkillWorkflowRequestError(ValueError):
|
|
|
16
20
|
class SkillWorkflowRequest:
|
|
17
21
|
workflow_prompt: str = ""
|
|
18
22
|
skill_names: list[str] = field(default_factory=list)
|
|
23
|
+
pinned_packages: tuple[PinnedSkillArchive, ...] | None = None
|
|
24
|
+
package_directory: Path | None = None
|
|
25
|
+
collect_artifacts: bool = False
|
|
19
26
|
|
|
20
27
|
|
|
21
28
|
def parse_workflow_request(argv: list[str]) -> SkillWorkflowRequest:
|
|
@@ -56,9 +63,33 @@ def _request_from_json_file(path: str) -> SkillWorkflowRequest:
|
|
|
56
63
|
raise SkillWorkflowRequestError("request file must contain a JSON object")
|
|
57
64
|
prompt = payload.get("workflow_prompt", payload.get("prompt", ""))
|
|
58
65
|
skill_names = _skill_names_from_payload(payload)
|
|
66
|
+
pinned_packages = None
|
|
67
|
+
if "pinned_protocol_version" in payload and "pinned_packages" not in payload:
|
|
68
|
+
raise SkillWorkflowRequestError("Pinned Skill manifest is missing")
|
|
69
|
+
if "pinned_packages" in payload:
|
|
70
|
+
version = payload.get("pinned_protocol_version")
|
|
71
|
+
if type(version) is not int or version != 1:
|
|
72
|
+
raise SkillWorkflowRequestError("Unsupported pinned Skill protocol version")
|
|
73
|
+
raw = payload["pinned_packages"]
|
|
74
|
+
if not isinstance(raw, list):
|
|
75
|
+
raise SkillWorkflowRequestError("pinned_packages must be an array")
|
|
76
|
+
try:
|
|
77
|
+
pinned_packages = tuple(PinnedSkillArchive.model_validate(item) for item in raw)
|
|
78
|
+
validate_package_set(pinned_packages)
|
|
79
|
+
except (ValidationError, SkillPackageError):
|
|
80
|
+
raise SkillWorkflowRequestError("Invalid pinned Skill manifest") from None
|
|
81
|
+
allowed = {entry.name.casefold() for entry in pinned_packages}
|
|
82
|
+
if any(name.casefold() not in allowed for name in skill_names):
|
|
83
|
+
raise SkillWorkflowRequestError("Selected Skill is not in the pinned manifest")
|
|
84
|
+
collect_artifacts = payload.get("collect_artifacts", False)
|
|
85
|
+
if type(collect_artifacts) is not bool or (collect_artifacts and pinned_packages is None):
|
|
86
|
+
raise SkillWorkflowRequestError("Artifact collection requires a pinned request")
|
|
59
87
|
return SkillWorkflowRequest(
|
|
60
88
|
workflow_prompt=str(prompt or ""),
|
|
61
89
|
skill_names=skill_names,
|
|
90
|
+
pinned_packages=pinned_packages,
|
|
91
|
+
package_directory=Path(path).resolve().parent if pinned_packages is not None else None,
|
|
92
|
+
collect_artifacts=collect_artifacts,
|
|
62
93
|
)
|
|
63
94
|
|
|
64
95
|
|
ksadk/skills/service_client.py
CHANGED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from collections.abc import Mapping
|
|
5
|
+
from dataclasses import replace
|
|
5
6
|
from typing import Any
|
|
6
7
|
from urllib.parse import quote, urlsplit, urlunsplit
|
|
7
8
|
|
|
@@ -41,26 +42,44 @@ class SkillServiceClient:
|
|
|
41
42
|
extra_headers: Mapping[str, str] | None = None,
|
|
42
43
|
timeout: float = 60.0,
|
|
43
44
|
transport: httpx.BaseTransport | None = None,
|
|
45
|
+
allow_env_fallback: bool = True,
|
|
44
46
|
):
|
|
47
|
+
self.allow_env_fallback = allow_env_fallback
|
|
48
|
+
resolve_env = _env if allow_env_fallback else lambda *names: ""
|
|
45
49
|
self.base_url = _normalize_base_url(base_url)
|
|
46
50
|
self.token = token
|
|
47
|
-
self.access_key = access_key or
|
|
51
|
+
self.access_key = access_key or resolve_env(
|
|
48
52
|
"KSADK_SKILL_SERVICE_ACCESS_KEY", "KSYUN_ACCESS_KEY", "KS3_ACCESS_KEY"
|
|
49
53
|
)
|
|
50
|
-
self.secret_key = secret_key or
|
|
54
|
+
self.secret_key = secret_key or resolve_env(
|
|
51
55
|
"KSADK_SKILL_SERVICE_SECRET_KEY", "KSYUN_SECRET_KEY", "KS3_SECRET_KEY"
|
|
52
56
|
)
|
|
53
|
-
self.account_id = account_id or
|
|
57
|
+
self.account_id = account_id or resolve_env(
|
|
58
|
+
"KSADK_SKILL_SERVICE_ACCOUNT_ID", "KSYUN_ACCOUNT_ID"
|
|
59
|
+
)
|
|
54
60
|
self.logical_region = (
|
|
55
|
-
region or
|
|
61
|
+
region or resolve_env("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
|
|
62
|
+
)
|
|
63
|
+
if not allow_env_fallback:
|
|
64
|
+
if not region or region.strip().lower() == "pre-online":
|
|
65
|
+
raise ValueError("Explicit Skill clients require a concrete region")
|
|
66
|
+
if token and (access_key or secret_key):
|
|
67
|
+
raise ValueError("Explicit Skill clients cannot mix token and signing credentials")
|
|
68
|
+
if bool(access_key) != bool(secret_key):
|
|
69
|
+
raise ValueError("Both signing credentials are required")
|
|
70
|
+
self.region = (
|
|
71
|
+
_normalize_control_region(self.logical_region)
|
|
72
|
+
if allow_env_fallback
|
|
73
|
+
else self.logical_region.strip()
|
|
74
|
+
)
|
|
75
|
+
self.custom_source = (
|
|
76
|
+
_resolve_custom_source(self.logical_region) if allow_env_fallback else ""
|
|
56
77
|
)
|
|
57
|
-
self.
|
|
58
|
-
|
|
59
|
-
self.api_version = api_version or os.environ.get(
|
|
60
|
-
"KSADK_SKILL_SERVICE_API_VERSION", "2024-06-12"
|
|
78
|
+
self.api_version = (
|
|
79
|
+
api_version or resolve_env("KSADK_SKILL_SERVICE_API_VERSION") or "2024-06-12"
|
|
61
80
|
)
|
|
62
|
-
self.sign_service =
|
|
63
|
-
"KSADK_SKILL_SERVICE_SIGN_SERVICE"
|
|
81
|
+
self.sign_service = (
|
|
82
|
+
sign_service or resolve_env("KSADK_SKILL_SERVICE_SIGN_SERVICE") or "aicp"
|
|
64
83
|
)
|
|
65
84
|
self.extra_headers = dict(extra_headers or {})
|
|
66
85
|
self.timeout = timeout
|
|
@@ -71,6 +90,7 @@ class SkillServiceClient:
|
|
|
71
90
|
secret_access_key=self.secret_key,
|
|
72
91
|
region=self.region,
|
|
73
92
|
service=self.sign_service,
|
|
93
|
+
allow_env_fallback=allow_env_fallback,
|
|
74
94
|
)
|
|
75
95
|
|
|
76
96
|
def action_url(self, action: str) -> str:
|
|
@@ -87,21 +107,113 @@ class SkillServiceClient:
|
|
|
87
107
|
{"PageNumber": page_number, "PageSize": page_size},
|
|
88
108
|
)
|
|
89
109
|
|
|
90
|
-
def list_skills_by_space_id(self, space_id: str) -> SkillListResponse:
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
else:
|
|
110
|
+
def list_skills_by_space_id(self, space_id: str, *, max_pages: int = 20) -> SkillListResponse:
|
|
111
|
+
if type(max_pages) is not int or not 1 <= max_pages <= 1000:
|
|
112
|
+
raise ValueError("Skill directory page budget must be 1..1000")
|
|
113
|
+
if not self._is_kop_mode():
|
|
114
|
+
# Legacy REST endpoints do not advertise a paging contract. Preserve
|
|
115
|
+
# their request shape and report known incompleteness explicitly.
|
|
97
116
|
payload = self._get_json("ListSkillsBySpaceId", {"SpaceId": space_id})
|
|
98
|
-
|
|
117
|
+
result = SkillListResponse.from_payload(payload, space_id=space_id)
|
|
118
|
+
if result.space_id != space_id:
|
|
119
|
+
raise ValueError("Skill directory does not match the requested space")
|
|
120
|
+
if result.total_count is not None and result.total_count > len(result.skills):
|
|
121
|
+
return replace(result, truncated=True, pagination_warning="pagination_unavailable")
|
|
122
|
+
return result
|
|
123
|
+
skills = []
|
|
124
|
+
seen = set()
|
|
125
|
+
total = None
|
|
126
|
+
for page_number in range(1, max_pages + 1):
|
|
127
|
+
result = self.list_skills_page(space_id, page_number=page_number)
|
|
128
|
+
if page_number > 1 and result.total_count != total:
|
|
129
|
+
return replace(
|
|
130
|
+
result,
|
|
131
|
+
skills=skills,
|
|
132
|
+
truncated=True,
|
|
133
|
+
next_page=None,
|
|
134
|
+
pagination_warning="directory_changed",
|
|
135
|
+
)
|
|
136
|
+
total = result.total_count
|
|
137
|
+
identities = [(skill.skill_id, skill.version_id) for skill in result.skills]
|
|
138
|
+
if (
|
|
139
|
+
any(not identity[0] for identity in identities)
|
|
140
|
+
or len(set(identities)) != len(identities)
|
|
141
|
+
or any(identity in seen for identity in identities)
|
|
142
|
+
):
|
|
143
|
+
return replace(
|
|
144
|
+
result,
|
|
145
|
+
skills=skills,
|
|
146
|
+
truncated=True,
|
|
147
|
+
next_page=None,
|
|
148
|
+
pagination_warning="pagination_repeated",
|
|
149
|
+
)
|
|
150
|
+
seen.update(identities)
|
|
151
|
+
skills.extend(result.skills)
|
|
152
|
+
if total is not None and len(skills) > total:
|
|
153
|
+
return replace(
|
|
154
|
+
result,
|
|
155
|
+
skills=skills,
|
|
156
|
+
truncated=True,
|
|
157
|
+
next_page=None,
|
|
158
|
+
pagination_warning="directory_changed",
|
|
159
|
+
)
|
|
160
|
+
if total is not None and len(skills) == total:
|
|
161
|
+
return replace(result, skills=skills, truncated=False, next_page=None)
|
|
162
|
+
if len(result.skills) < 100:
|
|
163
|
+
incomplete = total is not None and len(skills) < total
|
|
164
|
+
return replace(
|
|
165
|
+
result,
|
|
166
|
+
skills=skills,
|
|
167
|
+
truncated=incomplete,
|
|
168
|
+
next_page=None,
|
|
169
|
+
pagination_warning="directory_incomplete" if incomplete else "",
|
|
170
|
+
)
|
|
171
|
+
return replace(
|
|
172
|
+
result,
|
|
173
|
+
skills=skills,
|
|
174
|
+
truncated=True,
|
|
175
|
+
next_page=max_pages + 1,
|
|
176
|
+
pagination_warning="page_budget_exhausted",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
def list_skills_page(
|
|
180
|
+
self, space_id: str, *, page_number: int = 1, page_size: int = 100
|
|
181
|
+
) -> SkillListResponse:
|
|
182
|
+
if not self._is_kop_mode():
|
|
183
|
+
raise ValueError("This Skill endpoint does not advertise pagination")
|
|
184
|
+
if (
|
|
185
|
+
type(page_number) is not int
|
|
186
|
+
or page_number < 1
|
|
187
|
+
or type(page_size) is not int
|
|
188
|
+
or not 1 <= page_size <= 100
|
|
189
|
+
):
|
|
190
|
+
raise ValueError("Invalid Skill directory page parameters")
|
|
191
|
+
payload = self._get_json(
|
|
192
|
+
"ListSkillsBySpaceId",
|
|
193
|
+
{
|
|
194
|
+
"SpaceId": space_id,
|
|
195
|
+
"PageNumber": page_number,
|
|
196
|
+
"PageSize": page_size,
|
|
197
|
+
},
|
|
198
|
+
)
|
|
199
|
+
result = SkillListResponse.from_payload(payload, space_id=space_id)
|
|
200
|
+
if result.space_id != space_id or len(result.skills) > page_size:
|
|
201
|
+
raise ValueError("Skill directory page does not match the requested space or limit")
|
|
202
|
+
more = (
|
|
203
|
+
page_number * page_size < result.total_count
|
|
204
|
+
if result.total_count is not None
|
|
205
|
+
else len(result.skills) == page_size
|
|
206
|
+
)
|
|
207
|
+
return replace(result, truncated=more, next_page=page_number + 1 if more else None)
|
|
99
208
|
|
|
100
209
|
def list_available_premade_skills(self) -> SkillListResponse:
|
|
101
210
|
payload = self._get_json("ListAvailablePremadeSkills", {})
|
|
102
|
-
|
|
211
|
+
result = SkillListResponse.from_payload(
|
|
103
212
|
payload, space_id="public", space_name="Public Skills"
|
|
104
213
|
)
|
|
214
|
+
if result.total_count is not None and result.total_count > len(result.skills):
|
|
215
|
+
return replace(result, truncated=True, pagination_warning="pagination_unavailable")
|
|
216
|
+
return result
|
|
105
217
|
|
|
106
218
|
def get_skill_download_url(self, skill: SkillRef) -> str:
|
|
107
219
|
action = "GetSkillDownloadUrl" if skill.version_id else "GetPremadeSkillDownloadUrl"
|
|
@@ -115,15 +227,33 @@ class SkillServiceClient:
|
|
|
115
227
|
data = payload.get("Data") or payload.get("data") or {}
|
|
116
228
|
return str(data.get("DownloadUrl") or data.get("download_url") or "")
|
|
117
229
|
|
|
118
|
-
def download_skill_archive(
|
|
230
|
+
def download_skill_archive(
|
|
231
|
+
self, skill: SkillRef, *, max_bytes: int = 20 * 1024 * 1024
|
|
232
|
+
) -> bytes:
|
|
233
|
+
if type(max_bytes) is not int or max_bytes < 1:
|
|
234
|
+
raise ValueError("Skill archive size limit must be a positive integer")
|
|
119
235
|
download_url = self.get_skill_download_url(skill)
|
|
120
236
|
if not download_url:
|
|
121
237
|
raise ValueError(f"Skill Service did not return DownloadUrl for {skill.skill_id}")
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
238
|
+
if self.allow_env_fallback:
|
|
239
|
+
download_url = _rewrite_ks3_to_internal(download_url)
|
|
240
|
+
try:
|
|
241
|
+
with httpx.Client(**self._client_kwargs()) as client:
|
|
242
|
+
with client.stream("GET", download_url) as response:
|
|
243
|
+
response.raise_for_status()
|
|
244
|
+
length = response.headers.get("content-length", "")
|
|
245
|
+
if length.isdigit() and int(length) > max_bytes:
|
|
246
|
+
raise ValueError("Skill archive exceeds download limit")
|
|
247
|
+
content = bytearray()
|
|
248
|
+
for chunk in response.iter_bytes(chunk_size=64 * 1024):
|
|
249
|
+
if len(content) + len(chunk) > max_bytes:
|
|
250
|
+
raise ValueError("Skill archive exceeds download limit")
|
|
251
|
+
content.extend(chunk)
|
|
252
|
+
return bytes(content)
|
|
253
|
+
except httpx.HTTPError:
|
|
254
|
+
# Download URLs can carry temporary credentials; do not expose the
|
|
255
|
+
# HTTP exception's URL through logs or the consumer's tool result.
|
|
256
|
+
raise ValueError("Skill archive download failed") from None
|
|
127
257
|
|
|
128
258
|
def _get_json(self, action: str, params: dict[str, Any]) -> dict[str, Any]:
|
|
129
259
|
if self._is_kop_mode():
|
|
@@ -155,6 +285,8 @@ class SkillServiceClient:
|
|
|
155
285
|
|
|
156
286
|
def _client_kwargs(self) -> dict[str, Any]:
|
|
157
287
|
kwargs: dict[str, Any] = {"timeout": self.timeout}
|
|
288
|
+
if not self.allow_env_fallback:
|
|
289
|
+
kwargs["trust_env"] = False
|
|
158
290
|
if self.transport is not None:
|
|
159
291
|
kwargs["transport"] = self.transport
|
|
160
292
|
return kwargs
|
|
@@ -201,6 +333,7 @@ class SkillServiceClient:
|
|
|
201
333
|
headers=headers,
|
|
202
334
|
auth=self._auth.get_auth(),
|
|
203
335
|
timeout=self.timeout,
|
|
336
|
+
allow_redirects=False,
|
|
204
337
|
)
|
|
205
338
|
requests_response.raise_for_status()
|
|
206
339
|
data = requests_response.json()
|
|
@@ -219,8 +352,16 @@ class SkillServiceClient:
|
|
|
219
352
|
def _requests(self) -> requests.Session:
|
|
220
353
|
if self._requests_session is None:
|
|
221
354
|
self._requests_session = requests.Session()
|
|
355
|
+
if not self.allow_env_fallback:
|
|
356
|
+
self._requests_session.trust_env = False
|
|
222
357
|
return self._requests_session
|
|
223
358
|
|
|
359
|
+
def close(self) -> None:
|
|
360
|
+
"""Release the signing session when its owning activation ends."""
|
|
361
|
+
if self._requests_session is not None:
|
|
362
|
+
self._requests_session.close()
|
|
363
|
+
self._requests_session = None
|
|
364
|
+
|
|
224
365
|
def _is_kop_mode(self) -> bool:
|
|
225
366
|
"""Match only exact AICP control-plane endpoints.
|
|
226
367
|
|
|
@@ -287,9 +428,7 @@ def _rewrite_ks3_to_internal(url: str) -> str:
|
|
|
287
428
|
|
|
288
429
|
from ksadk.common.constants import get_ks3_endpoints
|
|
289
430
|
|
|
290
|
-
region = os.environ.get(
|
|
291
|
-
"KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION"
|
|
292
|
-
) or "cn-beijing-6"
|
|
431
|
+
region = os.environ.get("KSADK_SKILL_SERVICE_REGION", "KSYUN_REGION") or "cn-beijing-6"
|
|
293
432
|
public_ep, internal_ep = get_ks3_endpoints(region)
|
|
294
433
|
if not public_ep or not internal_ep:
|
|
295
434
|
return url
|