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
ksadk/studio/run_service.py
CHANGED
|
@@ -14,6 +14,8 @@ from pathlib import Path
|
|
|
14
14
|
from typing import Any
|
|
15
15
|
from uuid import uuid4
|
|
16
16
|
|
|
17
|
+
from jsonschema import Draft202012Validator
|
|
18
|
+
|
|
17
19
|
from ksadk.agui.a2ui_projection import project_a2ui_operations
|
|
18
20
|
from ksadk.conversations.projector import (
|
|
19
21
|
project_conversation_item,
|
|
@@ -60,6 +62,7 @@ from ksadk.runtime import (
|
|
|
60
62
|
RuntimeLaunchContext,
|
|
61
63
|
StartRequest,
|
|
62
64
|
)
|
|
65
|
+
from ksadk.runtime.executor import RuntimeStartPreparation
|
|
63
66
|
from ksadk.sessions.base import BaseSessionService
|
|
64
67
|
from ksadk.sessions.local_service import LocalSessionService
|
|
65
68
|
from ksadk.studio.contracts import RunEvent, RunRecord, RunStatus, Usage
|
|
@@ -68,6 +71,7 @@ from ksadk.studio.event_store import RunEventStore
|
|
|
68
71
|
from ksadk.studio.workspace import Workspace
|
|
69
72
|
|
|
70
73
|
_CANCEL_TIMEOUT_SECONDS = 2.0
|
|
74
|
+
_INTERACTION_SUBMIT_TIMEOUT_SECONDS = 10.0
|
|
71
75
|
|
|
72
76
|
|
|
73
77
|
logger = logging.getLogger(__name__)
|
|
@@ -107,13 +111,16 @@ class StudioRunService:
|
|
|
107
111
|
)
|
|
108
112
|
self.runtime_events = runtime_events or RuntimeEventStore(self.session_service)
|
|
109
113
|
self.plugin_runtime = plugin_runtime
|
|
114
|
+
self.schedule_assistant: Any | None = None
|
|
110
115
|
self._active_handles: dict[str, Any] = {}
|
|
116
|
+
self._active_sessions: set[tuple[str, str]] = set()
|
|
111
117
|
self._cancel_flags: dict[str, bool] = {}
|
|
112
118
|
self._control_queues: dict[
|
|
113
119
|
str,
|
|
114
120
|
asyncio.Queue[tuple[str, ResumePayload | None, asyncio.Future[None] | None]],
|
|
115
121
|
] = {}
|
|
116
122
|
self._waiting_modes: dict[str, str] = {}
|
|
123
|
+
self._submitted_interactions: dict[str, set[str]] = {}
|
|
117
124
|
# Interaction resolution appends to one run-level event file. Serialise
|
|
118
125
|
# every decision for that run, not only identical interaction ids, so
|
|
119
126
|
# two concurrently visible cards cannot overwrite each other's receipt.
|
|
@@ -142,6 +149,7 @@ class StudioRunService:
|
|
|
142
149
|
"run.interrupted",
|
|
143
150
|
{"reason": "local_studio_restarted", "recoverable": False},
|
|
144
151
|
)
|
|
152
|
+
self._expire_unresolved_interactions(record)
|
|
145
153
|
|
|
146
154
|
async def events(self, run_id: str, *, after: int = 0) -> list[RunEvent]:
|
|
147
155
|
"""Read the durable Studio event timeline for API/SSE replay."""
|
|
@@ -155,6 +163,38 @@ class StudioRunService:
|
|
|
155
163
|
runtime_input: Any = None,
|
|
156
164
|
session_id: str | None = None,
|
|
157
165
|
on_event: Callable[[RunEvent], None] | None = None,
|
|
166
|
+
) -> RunRecord:
|
|
167
|
+
session = session_id or f"ses_{uuid4().hex}"
|
|
168
|
+
key = (spec.agent_id, session)
|
|
169
|
+
# Claim before the first await, including preparation and plugin runs.
|
|
170
|
+
# A second turn must never attach another adapter to the live thread.
|
|
171
|
+
if key in self._active_sessions:
|
|
172
|
+
raise StudioError(
|
|
173
|
+
"SESSION_RUN_ACTIVE",
|
|
174
|
+
"上一轮仍在运行或等待回答,请先完成回答或停止运行。",
|
|
175
|
+
status_code=409,
|
|
176
|
+
details={"sessionId": session},
|
|
177
|
+
)
|
|
178
|
+
self._active_sessions.add(key)
|
|
179
|
+
try:
|
|
180
|
+
return await self._run_owned(
|
|
181
|
+
spec,
|
|
182
|
+
user_input,
|
|
183
|
+
runtime_input=runtime_input,
|
|
184
|
+
session_id=session,
|
|
185
|
+
on_event=on_event,
|
|
186
|
+
)
|
|
187
|
+
finally:
|
|
188
|
+
self._active_sessions.discard(key)
|
|
189
|
+
|
|
190
|
+
async def _run_owned(
|
|
191
|
+
self,
|
|
192
|
+
spec: StudioRunSpec,
|
|
193
|
+
user_input: str,
|
|
194
|
+
*,
|
|
195
|
+
runtime_input: Any,
|
|
196
|
+
session_id: str,
|
|
197
|
+
on_event: Callable[[RunEvent], None] | None,
|
|
158
198
|
) -> RunRecord:
|
|
159
199
|
run_id = f"run_{uuid4().hex}"
|
|
160
200
|
session = session_id or f"ses_{uuid4().hex}"
|
|
@@ -193,7 +233,27 @@ class StudioRunService:
|
|
|
193
233
|
if on_event is not None:
|
|
194
234
|
on_event(created)
|
|
195
235
|
|
|
196
|
-
|
|
236
|
+
if self.schedule_assistant is not None and (
|
|
237
|
+
self.schedule_assistant.matches(user_input)
|
|
238
|
+
or self.schedule_assistant.matches_followup(spec.agent_id, session, user_input)
|
|
239
|
+
):
|
|
240
|
+
handled = await self._schedule_run(record, user_input, on_event=on_event)
|
|
241
|
+
if handled is not None:
|
|
242
|
+
return handled
|
|
243
|
+
|
|
244
|
+
provider_runtime_adapter = (
|
|
245
|
+
spec.plugin_bundle_root is not None
|
|
246
|
+
and (
|
|
247
|
+
runtime_type == "codex"
|
|
248
|
+
or bool(spec.request_config.get("provider_runtime_adapter"))
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
# A process-global Codex Kernel can share Agent/cwd with this Build
|
|
252
|
+
# while owning a legacy direct factory. New Builds must retain their
|
|
253
|
+
# exact Provider activation, including when that global Kernel exists.
|
|
254
|
+
kernel_runtime = (
|
|
255
|
+
None if provider_runtime_adapter else self._kernel_runtime_for_spec(spec)
|
|
256
|
+
)
|
|
197
257
|
if kernel_runtime is not None:
|
|
198
258
|
return await self._kernel_run(
|
|
199
259
|
spec,
|
|
@@ -202,7 +262,7 @@ class StudioRunService:
|
|
|
202
262
|
on_event=on_event,
|
|
203
263
|
kernel_runtime=kernel_runtime,
|
|
204
264
|
)
|
|
205
|
-
if spec.plugin_bundle_root is not None:
|
|
265
|
+
if spec.plugin_bundle_root is not None and not provider_runtime_adapter:
|
|
206
266
|
return await self._plugin_run(
|
|
207
267
|
spec,
|
|
208
268
|
user_input,
|
|
@@ -269,10 +329,29 @@ class StudioRunService:
|
|
|
269
329
|
metadata={
|
|
270
330
|
"invocation_id": run_id,
|
|
271
331
|
CONVERSATION_PREPROCESSING_METADATA_KEY: conversation_request,
|
|
272
|
-
**self._native_session_metadata(
|
|
332
|
+
**self._native_session_metadata(
|
|
333
|
+
spec.agent_id,
|
|
334
|
+
session,
|
|
335
|
+
str(
|
|
336
|
+
spec.request_config.get("provider_runtime_type")
|
|
337
|
+
or runtime_type
|
|
338
|
+
),
|
|
339
|
+
spec.build_id,
|
|
340
|
+
),
|
|
273
341
|
},
|
|
274
342
|
)
|
|
275
|
-
|
|
343
|
+
preparation = None
|
|
344
|
+
if provider_runtime_adapter:
|
|
345
|
+
if self.plugin_runtime is None:
|
|
346
|
+
raise StudioError(
|
|
347
|
+
"PLUGIN_RUNTIME_UNAVAILABLE", "Codex Provider Runtime 不可用",
|
|
348
|
+
status_code=503,
|
|
349
|
+
)
|
|
350
|
+
adapter = self.plugin_runtime.kernel_adapter_provider(spec)()
|
|
351
|
+
preparation = RuntimeStartPreparation(context=spec.launch_context, adapter=adapter)
|
|
352
|
+
handle = await self.executor.start(
|
|
353
|
+
spec.launch_context, request, preparation=preparation,
|
|
354
|
+
)
|
|
276
355
|
record.runtime_handle = handle.model_dump(mode="json")
|
|
277
356
|
self.event_store.save(record)
|
|
278
357
|
self._active_handles[run_id] = handle
|
|
@@ -280,6 +359,27 @@ class StudioRunService:
|
|
|
280
359
|
terminal_seen = False
|
|
281
360
|
should_resume = False
|
|
282
361
|
async for event in self.executor.stream(handle):
|
|
362
|
+
if (
|
|
363
|
+
isinstance(event, RunInterrupted)
|
|
364
|
+
and event.interaction_id
|
|
365
|
+
and record.status == RunStatus.WAITING_INPUT
|
|
366
|
+
and event.source.framework == "codex"
|
|
367
|
+
):
|
|
368
|
+
# Codex emits this companion event immediately after a
|
|
369
|
+
# live JSON-RPC approval request. The native turn stays
|
|
370
|
+
# attached and must be released through submit; trying
|
|
371
|
+
# to resume it deadlocks that request and later breaks
|
|
372
|
+
# the app-server pipe.
|
|
373
|
+
self._waiting_modes[run_id] = "live"
|
|
374
|
+
continue
|
|
375
|
+
if isinstance(event, InteractionResolved) and event.source.framework == "codex":
|
|
376
|
+
submitted = self._submitted_interactions.get(run_id, set())
|
|
377
|
+
provider_call_id = str(getattr(event.response, "call_id", None) or "")
|
|
378
|
+
if event.interaction_id in submitted or provider_call_id in submitted:
|
|
379
|
+
# submit_interaction atomically persists the public
|
|
380
|
+
# terminal fact and receipt. Ignore the provider's
|
|
381
|
+
# echo so replay never shows the approval twice.
|
|
382
|
+
continue
|
|
283
383
|
await persist(event)
|
|
284
384
|
if self._cancel_flags.get(run_id):
|
|
285
385
|
raise asyncio.CancelledError()
|
|
@@ -288,9 +388,7 @@ class StudioRunService:
|
|
|
288
388
|
elif (
|
|
289
389
|
isinstance(event, ItemUpdated)
|
|
290
390
|
and event.item_kind == "message"
|
|
291
|
-
and item_phases.get(
|
|
292
|
-
(event.scope_id, event.item_id), "final_answer"
|
|
293
|
-
)
|
|
391
|
+
and item_phases.get((event.scope_id, event.item_id), "final_answer")
|
|
294
392
|
== "final_answer"
|
|
295
393
|
):
|
|
296
394
|
text = event.update.text if isinstance(event.update, TextContent) else ""
|
|
@@ -304,9 +402,7 @@ class StudioRunService:
|
|
|
304
402
|
elif (
|
|
305
403
|
isinstance(event, ItemCompleted)
|
|
306
404
|
and event.item_kind == "message"
|
|
307
|
-
and item_phases.get(
|
|
308
|
-
(event.scope_id, event.item_id), "final_answer"
|
|
309
|
-
)
|
|
405
|
+
and item_phases.get((event.scope_id, event.item_id), "final_answer")
|
|
310
406
|
== "final_answer"
|
|
311
407
|
):
|
|
312
408
|
completed_text_by_item[(event.scope_id, event.item_id)] = "".join(
|
|
@@ -492,7 +588,9 @@ class StudioRunService:
|
|
|
492
588
|
self._cancel_flags.pop(run_id, None)
|
|
493
589
|
self._control_queues.pop(run_id, None)
|
|
494
590
|
self._waiting_modes.pop(run_id, None)
|
|
591
|
+
self._submitted_interactions.pop(run_id, None)
|
|
495
592
|
record.completed_at = datetime.now(timezone.utc)
|
|
593
|
+
self._expire_unresolved_interactions(record, on_event=on_event)
|
|
496
594
|
if runtime_duration_ms is not None:
|
|
497
595
|
record.duration_ms = runtime_duration_ms
|
|
498
596
|
record.duration_source = "runtime"
|
|
@@ -503,6 +601,179 @@ class StudioRunService:
|
|
|
503
601
|
await self._sync_trace(record)
|
|
504
602
|
return record
|
|
505
603
|
|
|
604
|
+
async def _schedule_run(
|
|
605
|
+
self,
|
|
606
|
+
record: RunRecord,
|
|
607
|
+
user_input: str,
|
|
608
|
+
*,
|
|
609
|
+
on_event: Callable[[RunEvent], None] | None,
|
|
610
|
+
) -> RunRecord | None:
|
|
611
|
+
"""Persist real host tool receipts on the canonical conversation stream."""
|
|
612
|
+
started = time.monotonic()
|
|
613
|
+
|
|
614
|
+
def envelope(kind: str) -> dict[str, Any]:
|
|
615
|
+
result = _plugin_event_envelope(record, kind)
|
|
616
|
+
result["source"] = SourceRef(
|
|
617
|
+
framework="ksadk",
|
|
618
|
+
metadata={"runtime": "studio-scheduler", "agent_id": record.agent_id},
|
|
619
|
+
)
|
|
620
|
+
return result
|
|
621
|
+
|
|
622
|
+
async def publish(event: RuntimeEvent) -> None:
|
|
623
|
+
persisted = await self.runtime_events.append_one(record.session_id, event)
|
|
624
|
+
kind, data = project_runtime_event(
|
|
625
|
+
persisted, session_id=record.session_id, public_run_id=record.id
|
|
626
|
+
)
|
|
627
|
+
stored = self.event_store.append(record.id, kind, data)
|
|
628
|
+
if on_event is not None:
|
|
629
|
+
on_event(stored)
|
|
630
|
+
|
|
631
|
+
call_id = None
|
|
632
|
+
try:
|
|
633
|
+
intent = await self.schedule_assistant.plan(
|
|
634
|
+
record.agent_id,
|
|
635
|
+
user_input,
|
|
636
|
+
record.session_id,
|
|
637
|
+
build_id=record.build_id,
|
|
638
|
+
model_name=record.model,
|
|
639
|
+
)
|
|
640
|
+
if self._cancel_flags.get(record.id):
|
|
641
|
+
raise asyncio.CancelledError()
|
|
642
|
+
if intent.action == "ignore":
|
|
643
|
+
return None
|
|
644
|
+
record.status = RunStatus.RUNNING
|
|
645
|
+
record.started_at = datetime.now(timezone.utc)
|
|
646
|
+
record.runtime_handle = {"provider": "studio-scheduler"}
|
|
647
|
+
self.event_store.save(record)
|
|
648
|
+
await publish(RunStarted(**envelope("run.started"), status="running"))
|
|
649
|
+
call_id = f"{record.id}:schedule"
|
|
650
|
+
arguments = intent.model_dump(mode="json", exclude_none=True)
|
|
651
|
+
await publish(
|
|
652
|
+
ItemStarted(
|
|
653
|
+
**envelope("tool.started"),
|
|
654
|
+
item_id=call_id,
|
|
655
|
+
item_kind="tool_call",
|
|
656
|
+
initial=ContentSnapshot(
|
|
657
|
+
parts=(
|
|
658
|
+
ToolCallContent(
|
|
659
|
+
part_id=f"{call_id}:call",
|
|
660
|
+
call_id=call_id,
|
|
661
|
+
name="studio_schedule",
|
|
662
|
+
arguments=arguments,
|
|
663
|
+
),
|
|
664
|
+
)
|
|
665
|
+
),
|
|
666
|
+
)
|
|
667
|
+
)
|
|
668
|
+
result = await self.schedule_assistant.execute(
|
|
669
|
+
record.agent_id, record.session_id, intent
|
|
670
|
+
)
|
|
671
|
+
await publish(
|
|
672
|
+
ItemCompleted(
|
|
673
|
+
**envelope("tool.completed"),
|
|
674
|
+
item_id=call_id,
|
|
675
|
+
item_kind="tool_call",
|
|
676
|
+
snapshot=ContentSnapshot(
|
|
677
|
+
parts=(
|
|
678
|
+
ToolResultContent(
|
|
679
|
+
part_id=f"{call_id}:result", call_id=call_id, result=result
|
|
680
|
+
),
|
|
681
|
+
)
|
|
682
|
+
),
|
|
683
|
+
)
|
|
684
|
+
)
|
|
685
|
+
output = result["message"]
|
|
686
|
+
item_id, part_id = f"{record.id}:assistant", f"{record.id}:text"
|
|
687
|
+
await publish(
|
|
688
|
+
ItemStarted(
|
|
689
|
+
**envelope("item.started"),
|
|
690
|
+
item_id=item_id,
|
|
691
|
+
item_kind="message",
|
|
692
|
+
phase="final_answer",
|
|
693
|
+
)
|
|
694
|
+
)
|
|
695
|
+
await publish(
|
|
696
|
+
ItemUpdated(
|
|
697
|
+
**envelope("item.updated"),
|
|
698
|
+
item_id=item_id,
|
|
699
|
+
item_kind="message",
|
|
700
|
+
op="append",
|
|
701
|
+
update=TextContent(part_id=part_id, text=output),
|
|
702
|
+
)
|
|
703
|
+
)
|
|
704
|
+
await publish(
|
|
705
|
+
ItemCompleted(
|
|
706
|
+
**envelope("item.completed"),
|
|
707
|
+
item_id=item_id,
|
|
708
|
+
item_kind="message",
|
|
709
|
+
snapshot=ContentSnapshot(parts=(TextContent(part_id=part_id, text=output),)),
|
|
710
|
+
)
|
|
711
|
+
)
|
|
712
|
+
if intent._usage is not None and intent._usage.reported:
|
|
713
|
+
record.usage = intent._usage.model_copy(update={"source": "studio-scheduler"})
|
|
714
|
+
await publish(
|
|
715
|
+
UsageReported(
|
|
716
|
+
**envelope("usage.reported"),
|
|
717
|
+
input_tokens=record.usage.input_tokens,
|
|
718
|
+
output_tokens=record.usage.output_tokens,
|
|
719
|
+
total_tokens=record.usage.total_tokens,
|
|
720
|
+
cached_tokens=record.usage.cached_input_tokens,
|
|
721
|
+
reasoning_tokens=record.usage.reasoning_output_tokens,
|
|
722
|
+
)
|
|
723
|
+
)
|
|
724
|
+
await publish(
|
|
725
|
+
RunCompleted(
|
|
726
|
+
**envelope("run.completed"),
|
|
727
|
+
status="completed",
|
|
728
|
+
output_refs=(OutputRef(scope_id=record.id, item_id=item_id, part_id=part_id),),
|
|
729
|
+
)
|
|
730
|
+
)
|
|
731
|
+
record.output = output
|
|
732
|
+
record.status = RunStatus.COMPLETED
|
|
733
|
+
except asyncio.CancelledError:
|
|
734
|
+
record.status = RunStatus.CANCELLED
|
|
735
|
+
record.completed_at = datetime.now(timezone.utc)
|
|
736
|
+
self._cancel_flags.pop(record.id, None)
|
|
737
|
+
await publish(
|
|
738
|
+
RunCanceled(**envelope("run.canceled"), status="canceled", reason="cancelled")
|
|
739
|
+
)
|
|
740
|
+
self.event_store.save(record)
|
|
741
|
+
raise
|
|
742
|
+
except Exception as error:
|
|
743
|
+
code = str(getattr(error, "code", "SCHEDULE_REQUEST_FAILED"))
|
|
744
|
+
record.status = RunStatus.FAILED
|
|
745
|
+
record.error = {"code": code, "message": str(error)}
|
|
746
|
+
if call_id is not None:
|
|
747
|
+
await publish(
|
|
748
|
+
ItemFailed(
|
|
749
|
+
**envelope("tool.failed"),
|
|
750
|
+
item_id=call_id,
|
|
751
|
+
item_kind="tool_call",
|
|
752
|
+
error=ErrorInfo(
|
|
753
|
+
code=code,
|
|
754
|
+
message=str(error),
|
|
755
|
+
source="studio-scheduler",
|
|
756
|
+
scope_id=record.id,
|
|
757
|
+
),
|
|
758
|
+
)
|
|
759
|
+
)
|
|
760
|
+
await publish(
|
|
761
|
+
RunFailed(
|
|
762
|
+
**envelope("run.failed"),
|
|
763
|
+
status="failed",
|
|
764
|
+
error=ErrorInfo(
|
|
765
|
+
code=code, message=str(error), source="studio-scheduler", scope_id=record.id
|
|
766
|
+
),
|
|
767
|
+
)
|
|
768
|
+
)
|
|
769
|
+
record.completed_at = datetime.now(timezone.utc)
|
|
770
|
+
record.duration_ms = int((time.monotonic() - started) * 1000)
|
|
771
|
+
record.duration_source = "studio"
|
|
772
|
+
self._cancel_flags.pop(record.id, None)
|
|
773
|
+
self.event_store.save(record)
|
|
774
|
+
await self._sync_trace(record)
|
|
775
|
+
return record
|
|
776
|
+
|
|
506
777
|
async def _sync_trace(self, record: RunRecord) -> None:
|
|
507
778
|
self.event_store.trace_store.sync(record, await self.events(record.id))
|
|
508
779
|
|
|
@@ -672,9 +943,7 @@ class StudioRunService:
|
|
|
672
943
|
) -> list[RuntimeEvent]:
|
|
673
944
|
item_id = f"{record.id}:assistant"
|
|
674
945
|
part_id = f"{record.id}:text"
|
|
675
|
-
snapshot = ContentSnapshot(
|
|
676
|
-
parts=(TextContent(part_id=part_id, text=output_text),)
|
|
677
|
-
)
|
|
946
|
+
snapshot = ContentSnapshot(parts=(TextContent(part_id=part_id, text=output_text),))
|
|
678
947
|
events: list[RuntimeEvent] = [
|
|
679
948
|
RunStarted(
|
|
680
949
|
**_plugin_event_envelope(record, "run.started"),
|
|
@@ -725,10 +994,7 @@ class StudioRunService:
|
|
|
725
994
|
),
|
|
726
995
|
)
|
|
727
996
|
)
|
|
728
|
-
return [
|
|
729
|
-
await self.runtime_events.append_one(record.session_id, event)
|
|
730
|
-
for event in events
|
|
731
|
-
]
|
|
997
|
+
return [await self.runtime_events.append_one(record.session_id, event) for event in events]
|
|
732
998
|
|
|
733
999
|
async def _kernel_run(
|
|
734
1000
|
self,
|
|
@@ -764,9 +1030,7 @@ class StudioRunService:
|
|
|
764
1030
|
session_id=record.session_id,
|
|
765
1031
|
operations=("enqueue",),
|
|
766
1032
|
)
|
|
767
|
-
idempotency_key = str(
|
|
768
|
-
(spec.request_config or {}).get("idempotency_key") or record.id
|
|
769
|
-
)
|
|
1033
|
+
idempotency_key = str((spec.request_config or {}).get("idempotency_key") or record.id)
|
|
770
1034
|
command = _kernel_ingress.map_studio_request(
|
|
771
1035
|
session_id=record.session_id,
|
|
772
1036
|
idempotency_key=idempotency_key,
|
|
@@ -774,9 +1038,7 @@ class StudioRunService:
|
|
|
774
1038
|
run_id=record.id,
|
|
775
1039
|
trusted=trusted,
|
|
776
1040
|
)
|
|
777
|
-
receipt = await _kernel_ingress.submit_command(
|
|
778
|
-
command, permit=trusted.permit
|
|
779
|
-
)
|
|
1041
|
+
receipt = await _kernel_ingress.submit_command(command, permit=trusted.permit)
|
|
780
1042
|
if receipt.status not in ("accepted", "duplicate"):
|
|
781
1043
|
record.status = RunStatus.FAILED
|
|
782
1044
|
record.error = {
|
|
@@ -859,17 +1121,13 @@ class StudioRunService:
|
|
|
859
1121
|
if active_project != build_project:
|
|
860
1122
|
return None
|
|
861
1123
|
defaults = getattr(runtime.config, "start_request_defaults", {}) or {}
|
|
862
|
-
bound_agent_id = str(
|
|
863
|
-
defaults.get("agent_id") or runtime.config.agent_instance_id
|
|
864
|
-
).strip()
|
|
1124
|
+
bound_agent_id = str(defaults.get("agent_id") or runtime.config.agent_instance_id).strip()
|
|
865
1125
|
if bound_agent_id != spec.agent_id:
|
|
866
1126
|
return None
|
|
867
1127
|
declared_instance = str(
|
|
868
1128
|
(spec.launch_context.config or {}).get("agent_instance_id") or ""
|
|
869
1129
|
).strip()
|
|
870
|
-
if declared_instance and declared_instance != str(
|
|
871
|
-
runtime.config.agent_instance_id
|
|
872
|
-
):
|
|
1130
|
+
if declared_instance and declared_instance != str(runtime.config.agent_instance_id):
|
|
873
1131
|
return None
|
|
874
1132
|
return runtime
|
|
875
1133
|
|
|
@@ -998,11 +1256,8 @@ class StudioRunService:
|
|
|
998
1256
|
"同一幂等键不能提交不同内容",
|
|
999
1257
|
status_code=409,
|
|
1000
1258
|
)
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
record.status = RunStatus.RUNNING
|
|
1004
|
-
self.event_store.save(record)
|
|
1005
|
-
self._waiting_modes.pop(run_id, None)
|
|
1259
|
+
# A receipt replay is read-only. The run may already be waiting
|
|
1260
|
+
# for a different interaction; never clear that newer wait state.
|
|
1006
1261
|
return dict(prior.data.get("receipt") or {})
|
|
1007
1262
|
|
|
1008
1263
|
interaction = next(
|
|
@@ -1039,10 +1294,51 @@ class StudioRunService:
|
|
|
1039
1294
|
status_code=409,
|
|
1040
1295
|
)
|
|
1041
1296
|
kind = str(interaction.data.get("kind") or "form")
|
|
1042
|
-
|
|
1297
|
+
if kind != "approval" and name not in {"cancel", "skip"}:
|
|
1298
|
+
schema = interaction.data.get("inputSchema") or {}
|
|
1299
|
+
errors = list(Draft202012Validator(schema).iter_errors(data))
|
|
1300
|
+
if errors:
|
|
1301
|
+
raise StudioError(
|
|
1302
|
+
"INTERACTION_RESPONSE_INVALID",
|
|
1303
|
+
"请填写必填问题后再提交。",
|
|
1304
|
+
status_code=422,
|
|
1305
|
+
)
|
|
1306
|
+
provider_call_id = str(
|
|
1307
|
+
interaction.data.get("callId") or interaction.data.get("call_id") or ""
|
|
1308
|
+
)
|
|
1309
|
+
if kind == "approval" and not provider_call_id:
|
|
1310
|
+
approval_request = next(
|
|
1311
|
+
(
|
|
1312
|
+
event
|
|
1313
|
+
for event in reversed(events)
|
|
1314
|
+
if event.type == "approval.requested"
|
|
1315
|
+
and str(event.data.get("approvalId") or event.data.get("interactionId") or "")
|
|
1316
|
+
== interaction_id
|
|
1317
|
+
),
|
|
1318
|
+
None,
|
|
1319
|
+
)
|
|
1320
|
+
if approval_request is not None:
|
|
1321
|
+
provider_call_id = str(
|
|
1322
|
+
approval_request.data.get("callId")
|
|
1323
|
+
or approval_request.data.get("call_id")
|
|
1324
|
+
or ""
|
|
1325
|
+
)
|
|
1326
|
+
provider_call_id = provider_call_id or interaction_id
|
|
1327
|
+
submitted = self._submitted_interactions.setdefault(run_id, set())
|
|
1328
|
+
submitted.update({interaction_id, provider_call_id})
|
|
1329
|
+
decision = str(data.get("decision") or name)
|
|
1330
|
+
if kind == "approval" and record.runtime_type == "codex":
|
|
1331
|
+
# The shared Web action is named `reject`; Codex app-server calls
|
|
1332
|
+
# the same decision `deny`/`decline`. Do not let a UI alias fall
|
|
1333
|
+
# through as an unsupported native approval decision.
|
|
1334
|
+
decision = {
|
|
1335
|
+
"reject": "deny",
|
|
1336
|
+
"rejected": "deny",
|
|
1337
|
+
}.get(decision.lower(), decision)
|
|
1338
|
+
payload_data = {**data, "decision": decision}
|
|
1043
1339
|
payload = ResumePayload(
|
|
1044
1340
|
kind="approval_decision" if kind == "approval" else "hitl_answer",
|
|
1045
|
-
call_id=
|
|
1341
|
+
call_id=provider_call_id,
|
|
1046
1342
|
data=payload_data,
|
|
1047
1343
|
)
|
|
1048
1344
|
mode = self._waiting_modes.get(run_id)
|
|
@@ -1051,8 +1347,19 @@ class StudioRunService:
|
|
|
1051
1347
|
if handle is None or not self.executor.is_attached(handle):
|
|
1052
1348
|
raise StudioError("INTERACTION_EXPIRED", "运行时交互已失效", status_code=409)
|
|
1053
1349
|
try:
|
|
1054
|
-
await
|
|
1350
|
+
await asyncio.wait_for(
|
|
1351
|
+
self.executor.submit(handle, payload),
|
|
1352
|
+
timeout=_INTERACTION_SUBMIT_TIMEOUT_SECONDS,
|
|
1353
|
+
)
|
|
1354
|
+
except TimeoutError as exc:
|
|
1355
|
+
submitted.difference_update({interaction_id, provider_call_id})
|
|
1356
|
+
raise StudioError(
|
|
1357
|
+
"INTERACTION_SUBMIT_FAILED",
|
|
1358
|
+
"运行时未及时确认交互提交,请重试",
|
|
1359
|
+
status_code=409,
|
|
1360
|
+
) from exc
|
|
1055
1361
|
except Exception as exc: # noqa: BLE001 - provider errors are user-safe here
|
|
1362
|
+
submitted.difference_update({interaction_id, provider_call_id})
|
|
1056
1363
|
raise StudioError(
|
|
1057
1364
|
"INTERACTION_SUBMIT_FAILED",
|
|
1058
1365
|
str(exc),
|
|
@@ -1065,22 +1372,51 @@ class StudioRunService:
|
|
|
1065
1372
|
submit_ack = asyncio.get_running_loop().create_future()
|
|
1066
1373
|
queue.put_nowait(("resume", payload, submit_ack))
|
|
1067
1374
|
try:
|
|
1068
|
-
await
|
|
1375
|
+
await asyncio.wait_for(
|
|
1376
|
+
submit_ack,
|
|
1377
|
+
timeout=_INTERACTION_SUBMIT_TIMEOUT_SECONDS,
|
|
1378
|
+
)
|
|
1379
|
+
except TimeoutError as exc:
|
|
1380
|
+
submitted.difference_update({interaction_id, provider_call_id})
|
|
1381
|
+
raise StudioError(
|
|
1382
|
+
"INTERACTION_SUBMIT_FAILED",
|
|
1383
|
+
"运行时未及时确认交互提交,请重试",
|
|
1384
|
+
status_code=409,
|
|
1385
|
+
) from exc
|
|
1069
1386
|
except Exception as exc: # noqa: BLE001 - provider errors are user-safe here
|
|
1387
|
+
submitted.difference_update({interaction_id, provider_call_id})
|
|
1070
1388
|
raise StudioError(
|
|
1071
1389
|
"INTERACTION_SUBMIT_FAILED",
|
|
1072
1390
|
str(exc),
|
|
1073
1391
|
status_code=409,
|
|
1074
1392
|
) from exc
|
|
1075
1393
|
else:
|
|
1394
|
+
submitted.difference_update({interaction_id, provider_call_id})
|
|
1076
1395
|
raise StudioError("INTERACTION_EXPIRED", "运行时交互已失效", status_code=409)
|
|
1077
1396
|
|
|
1078
1397
|
next_revision = revision + 1
|
|
1398
|
+
normalized_action = name.lower()
|
|
1399
|
+
if normalized_action in {"approve", "approved", "accept", "accepted"}:
|
|
1400
|
+
outcome = "approved"
|
|
1401
|
+
response_summary = "已同意"
|
|
1402
|
+
elif normalized_action in {"reject", "rejected", "deny", "denied", "decline"}:
|
|
1403
|
+
outcome = "rejected"
|
|
1404
|
+
response_summary = "已拒绝"
|
|
1405
|
+
elif normalized_action in {"cancel", "cancelled", "canceled"}:
|
|
1406
|
+
outcome = "cancelled"
|
|
1407
|
+
response_summary = "已反馈给 Agent" if data.get("feedback") else "已取消"
|
|
1408
|
+
else:
|
|
1409
|
+
outcome = "submitted"
|
|
1410
|
+
response_summary = "已提交"
|
|
1079
1411
|
resolved_data = {
|
|
1080
1412
|
"runId": run_id,
|
|
1081
1413
|
"interactionId": interaction_id,
|
|
1082
|
-
"callId":
|
|
1414
|
+
"callId": provider_call_id,
|
|
1083
1415
|
"name": name,
|
|
1416
|
+
"action": name,
|
|
1417
|
+
"outcome": outcome,
|
|
1418
|
+
"actor": "user",
|
|
1419
|
+
"responseSummary": response_summary,
|
|
1084
1420
|
"data": data,
|
|
1085
1421
|
"revision": next_revision,
|
|
1086
1422
|
"expectedRevision": expected_revision,
|
|
@@ -1092,6 +1428,7 @@ class StudioRunService:
|
|
|
1092
1428
|
interaction.data.get("surfaceId") or interaction.data.get("surface_id") or ""
|
|
1093
1429
|
),
|
|
1094
1430
|
"interactionId": interaction_id,
|
|
1431
|
+
"callId": provider_call_id,
|
|
1095
1432
|
"actionId": f"action-{interaction_id}",
|
|
1096
1433
|
"name": name,
|
|
1097
1434
|
"data": data,
|
|
@@ -1111,6 +1448,65 @@ class StudioRunService:
|
|
|
1111
1448
|
self._waiting_modes.pop(run_id, None)
|
|
1112
1449
|
return receipt
|
|
1113
1450
|
|
|
1451
|
+
def _expire_unresolved_interactions(
|
|
1452
|
+
self,
|
|
1453
|
+
record: RunRecord,
|
|
1454
|
+
*,
|
|
1455
|
+
on_event: Callable[[RunEvent], None] | None = None,
|
|
1456
|
+
) -> None:
|
|
1457
|
+
"""Close orphaned cards whenever their owning run is terminal."""
|
|
1458
|
+
|
|
1459
|
+
if record.status not in {
|
|
1460
|
+
RunStatus.COMPLETED,
|
|
1461
|
+
RunStatus.FAILED,
|
|
1462
|
+
RunStatus.CANCELLED,
|
|
1463
|
+
RunStatus.INTERRUPTED,
|
|
1464
|
+
RunStatus.TIMED_OUT,
|
|
1465
|
+
}:
|
|
1466
|
+
return
|
|
1467
|
+
events = self.event_store.events(record.id)
|
|
1468
|
+
closed_ids = {
|
|
1469
|
+
str(event.data.get("interactionId") or event.data.get("approvalId") or "")
|
|
1470
|
+
for event in events
|
|
1471
|
+
if event.type
|
|
1472
|
+
in {
|
|
1473
|
+
"a2ui.action",
|
|
1474
|
+
"approval.resolved",
|
|
1475
|
+
"interaction.resolved",
|
|
1476
|
+
"interaction.cancelled",
|
|
1477
|
+
"interaction.expired",
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
pending: dict[str, RunEvent] = {}
|
|
1481
|
+
for event in events:
|
|
1482
|
+
if event.type != "a2ui.interaction":
|
|
1483
|
+
continue
|
|
1484
|
+
interaction_id = str(
|
|
1485
|
+
event.data.get("interactionId") or event.data.get("interaction_id") or ""
|
|
1486
|
+
)
|
|
1487
|
+
if interaction_id and interaction_id not in closed_ids:
|
|
1488
|
+
pending[interaction_id] = event
|
|
1489
|
+
for interaction_id, requested in pending.items():
|
|
1490
|
+
data = requested.data
|
|
1491
|
+
expired = self.event_store.append(
|
|
1492
|
+
record.id,
|
|
1493
|
+
"interaction.expired",
|
|
1494
|
+
{
|
|
1495
|
+
"runId": record.id,
|
|
1496
|
+
"interactionId": interaction_id,
|
|
1497
|
+
"approvalId": interaction_id,
|
|
1498
|
+
"callId": str(data.get("callId") or data.get("call_id") or ""),
|
|
1499
|
+
"kind": str(data.get("kind") or "form"),
|
|
1500
|
+
"title": data.get("title"),
|
|
1501
|
+
"message": data.get("message"),
|
|
1502
|
+
"detail": data.get("detail"),
|
|
1503
|
+
"outcome": "expired",
|
|
1504
|
+
"revision": _interaction_revision(data) + 1,
|
|
1505
|
+
},
|
|
1506
|
+
)
|
|
1507
|
+
if on_event is not None:
|
|
1508
|
+
on_event(expired)
|
|
1509
|
+
|
|
1114
1510
|
async def _capture_pcm_evidence(
|
|
1115
1511
|
self,
|
|
1116
1512
|
record: RunRecord,
|
|
@@ -1255,7 +1651,11 @@ class StudioRunService:
|
|
|
1255
1651
|
"runId": record.id,
|
|
1256
1652
|
"surfaceId": surface_id,
|
|
1257
1653
|
"interactionId": approval_id,
|
|
1654
|
+
"callId": event.request.call_id or approval_id,
|
|
1258
1655
|
"kind": "approval",
|
|
1656
|
+
"title": "需要审批",
|
|
1657
|
+
"message": "此次操作需要确认后才能继续。",
|
|
1658
|
+
"detail": detail,
|
|
1259
1659
|
"revision": 1,
|
|
1260
1660
|
"inputSchema": {
|
|
1261
1661
|
"type": "object",
|
|
@@ -1293,16 +1693,30 @@ class StudioRunService:
|
|
|
1293
1693
|
agent_id: str,
|
|
1294
1694
|
session_id: str,
|
|
1295
1695
|
runtime_type: str,
|
|
1696
|
+
build_id: str,
|
|
1296
1697
|
) -> dict[str, str]:
|
|
1297
1698
|
if runtime_type != "codex":
|
|
1298
1699
|
return {}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1700
|
+
runs = self.event_store.list_runs(session_id=session_id, agent_id=agent_id)
|
|
1701
|
+
thread_builds: dict[str, str] = {}
|
|
1702
|
+
for previous in runs:
|
|
1703
|
+
native_ref = previous.runtime_handle.get("native_ref") or {}
|
|
1704
|
+
if isinstance(native_ref, dict) and native_ref.get("thread_id"):
|
|
1705
|
+
# Older Studio versions also saved failed cross-build resumes.
|
|
1706
|
+
# The first occurrence identifies the thread's actual home.
|
|
1707
|
+
thread_builds.setdefault(str(native_ref["thread_id"]), previous.build_id)
|
|
1708
|
+
for previous in reversed(runs):
|
|
1709
|
+
# Each immutable build has its own CODEX_HOME and plugin snapshot.
|
|
1710
|
+
# Starting a thread in that home applies the new capabilities; the
|
|
1711
|
+
# transport-neutral history above preserves the Studio conversation.
|
|
1712
|
+
if previous.build_id != build_id:
|
|
1713
|
+
return {}
|
|
1302
1714
|
native_ref = previous.runtime_handle.get("native_ref")
|
|
1303
1715
|
native_ref = native_ref if isinstance(native_ref, dict) else {}
|
|
1304
1716
|
thread_id = str(native_ref.get("thread_id") or "")
|
|
1305
1717
|
if thread_id:
|
|
1718
|
+
if thread_builds[thread_id] != build_id:
|
|
1719
|
+
return {}
|
|
1306
1720
|
return {"thread_id": thread_id}
|
|
1307
1721
|
return {}
|
|
1308
1722
|
|
|
@@ -1340,17 +1754,13 @@ def _normalized_plugin_usage(usage: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
1340
1754
|
|
|
1341
1755
|
normalized = {
|
|
1342
1756
|
"input_tokens": number("input_tokens", "inputTokens", "prompt_tokens"),
|
|
1343
|
-
"output_tokens": number(
|
|
1344
|
-
"output_tokens", "outputTokens", "completion_tokens"
|
|
1345
|
-
),
|
|
1757
|
+
"output_tokens": number("output_tokens", "outputTokens", "completion_tokens"),
|
|
1346
1758
|
"total_tokens": number("total_tokens", "totalTokens"),
|
|
1347
1759
|
"cached_tokens": number("cached_tokens", "cachedTokens"),
|
|
1348
1760
|
"reasoning_tokens": number("reasoning_tokens", "reasoningTokens"),
|
|
1349
1761
|
}
|
|
1350
1762
|
if not normalized["total_tokens"]:
|
|
1351
|
-
normalized["total_tokens"] =
|
|
1352
|
-
normalized["input_tokens"] + normalized["output_tokens"]
|
|
1353
|
-
)
|
|
1763
|
+
normalized["total_tokens"] = normalized["input_tokens"] + normalized["output_tokens"]
|
|
1354
1764
|
normalized["reported"] = bool(usage) and any(
|
|
1355
1765
|
key in usage
|
|
1356
1766
|
for key in (
|
|
@@ -1520,7 +1930,9 @@ def project_runtime_event(
|
|
|
1520
1930
|
payload = {
|
|
1521
1931
|
"interactionId": event.interaction_id,
|
|
1522
1932
|
"kind": "form",
|
|
1523
|
-
"inputSchema":
|
|
1933
|
+
"inputSchema": event.request.schema_,
|
|
1934
|
+
"message": event.request.prompt or "",
|
|
1935
|
+
"callId": event.source.native_event_id or event.interaction_id,
|
|
1524
1936
|
}
|
|
1525
1937
|
elif isinstance(event, InteractionResolved):
|
|
1526
1938
|
if event.interaction_kind == "approval":
|
|
@@ -1575,9 +1987,7 @@ def project_runtime_event(
|
|
|
1575
1987
|
return projected, payload
|
|
1576
1988
|
|
|
1577
1989
|
|
|
1578
|
-
def _first_content(
|
|
1579
|
-
snapshot: ContentSnapshot | None, content_type: type
|
|
1580
|
-
) -> Any | None:
|
|
1990
|
+
def _first_content(snapshot: ContentSnapshot | None, content_type: type) -> Any | None:
|
|
1581
1991
|
if snapshot is None:
|
|
1582
1992
|
return None
|
|
1583
1993
|
for part in snapshot.parts:
|