agentengine-sdk-python 0.8.1__py3-none-any.whl → 0.8.2__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.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +22 -2
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/RECORD +356 -222
- ksadk/a2a/_space_client_events.py +381 -0
- ksadk/a2a/event_adapter.py +156 -64
- ksadk/a2a/executor.py +179 -63
- ksadk/a2a/space_client.py +6 -333
- ksadk/a2ui/core.py +222 -53
- ksadk/agui/_agent_helpers.py +243 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +443 -259
- ksadk/api/client.py +525 -27
- ksadk/builders/code_builder.py +284 -8
- ksadk/builders/container_builder.py +8 -1
- ksadk/builders/managed_runtime_builder.py +39 -35
- ksadk/cli/__init__.py +17 -0
- ksadk/cli/cmd_dashboard.py +15 -1
- ksadk/cli/cmd_deploy.py +10 -2
- ksadk/cli/cmd_eval.py +66 -9
- ksadk/cli/cmd_evalset.py +284 -0
- ksadk/cli/cmd_files.py +5 -1
- ksadk/cli/cmd_hermes.py +1 -126
- ksadk/cli/cmd_invoke.py +28 -38
- ksadk/cli/cmd_managed_runtime.py +95 -0
- ksadk/cli/cmd_observe.py +85 -0
- ksadk/cli/cmd_openclaw.py +1 -435
- ksadk/cli/cmd_replay.py +28 -4
- ksadk/cli/cmd_studio.py +99 -8
- ksadk/cli/cmd_web.py +10 -2
- ksadk/cli/hermes_env.py +151 -0
- ksadk/cli/invoke_payload.py +49 -0
- ksadk/cli/openclaw_env.py +458 -0
- ksadk/codex/client.py +180 -30
- ksadk/codex/runtime.py +428 -326
- ksadk/configs/env_registry.py +66 -12
- ksadk/configs/env_registry_pcm.py +181 -0
- ksadk/configs/env_var_spec.py +18 -0
- ksadk/configs/global_config.py +5 -0
- ksadk/context_engine/__init__.py +98 -0
- ksadk/context_engine/assembler.py +176 -0
- ksadk/context_engine/baseline.py +419 -0
- ksadk/context_engine/cache_observability.py +228 -0
- ksadk/context_engine/capabilities.py +443 -0
- ksadk/context_engine/contributors.py +344 -0
- ksadk/context_engine/hosted_pipeline.py +417 -0
- ksadk/context_engine/models.py +117 -0
- ksadk/context_engine/planner.py +698 -0
- ksadk/context_engine/policies.py +319 -0
- ksadk/context_engine/projection.py +31 -0
- ksadk/context_engine/shadow_plan.py +266 -0
- ksadk/context_engine/tokenizer.py +164 -0
- ksadk/conversations/context.py +126 -6
- ksadk/conversations/message_projection.py +292 -28
- ksadk/conversations/model_context.py +49 -3
- ksadk/conversations/runtime_compaction.py +207 -5
- ksadk/conversations/runtime_input.py +184 -2
- ksadk/conversations/runtime_invocation.py +81 -3
- ksadk/conversations/runtime_observability.py +141 -0
- ksadk/conversations/runtime_payloads.py +42 -0
- ksadk/conversations/runtime_preparation.py +272 -2
- ksadk/conversations/runtime_resume.py +20 -1
- ksadk/conversations/runtime_stream_events.py +94 -9
- ksadk/conversations/semantic_summary.py +311 -1
- ksadk/conversations/session_lock.py +51 -0
- ksadk/deployment/env_forward.py +72 -0
- ksadk/deployment/managed_runtime.py +5 -0
- ksadk/deployment/providers/serverless.py +143 -69
- ksadk/evaluation/__init__.py +32 -0
- ksadk/evaluation/a2a_adapter.py +9 -1
- ksadk/evaluation/adapters.py +18 -5
- ksadk/evaluation/agent_eval_client.py +395 -0
- ksadk/evaluation/cloud_binding.py +80 -0
- ksadk/evaluation/cloud_converter.py +194 -0
- ksadk/evaluation/cloud_service.py +199 -0
- ksadk/evaluation/contracts.py +73 -4
- ksadk/evaluation/evaluators.py +183 -17
- ksadk/evaluation/evidence.py +258 -0
- ksadk/evaluation/executor.py +31 -6
- ksadk/evaluation/local_adapter.py +550 -0
- ksadk/evaluation/service_env.py +27 -0
- ksadk/evaluation/studio_build_adapter.py +253 -0
- ksadk/evaluation/target.py +15 -6
- ksadk/events/__init__.py +13 -13
- ksadk/events/_v1_compat/__init__.py +1 -0
- ksadk/events/_v1_compat/models.py +299 -0
- ksadk/events/_v1_compat/parser.py +247 -0
- ksadk/events/_v1_compat/projection.py +753 -0
- ksadk/events/adapters/__init__.py +34 -0
- ksadk/events/adapters/_a2a_snapshot.py +622 -0
- ksadk/events/adapters/_a2a_support.py +275 -0
- ksadk/events/adapters/_codex_interactions.py +375 -0
- ksadk/events/adapters/_codex_items.py +801 -0
- ksadk/events/adapters/_codex_validators.py +311 -0
- ksadk/events/adapters/_langgraph_support.py +785 -0
- ksadk/events/adapters/a2a.py +841 -0
- ksadk/events/adapters/adk.py +503 -0
- ksadk/events/adapters/codex.py +717 -0
- ksadk/events/adapters/langgraph.py +745 -0
- ksadk/events/canonical.py +440 -0
- ksadk/events/canonical_replay.py +497 -0
- ksadk/events/canonical_store.py +468 -0
- ksadk/events/cold_recovery.py +257 -0
- ksadk/events/content.py +89 -0
- ksadk/events/identity.py +86 -0
- ksadk/events/pipeline.py +455 -0
- ksadk/events/projections.py +66 -0
- ksadk/events/reducer.py +661 -0
- ksadk/events/replay.py +3 -36
- ksadk/events/runtime_event.py +20 -265
- ksadk/events/session_event.py +324 -0
- ksadk/events/store.py +3 -316
- ksadk/events/v1_compat.py +41 -0
- ksadk/harness/runtime.py +160 -57
- ksadk/identity/resolver.py +4 -3
- ksadk/interaction/__init__.py +28 -0
- ksadk/interaction/contracts.py +136 -0
- ksadk/interaction/ledger.py +189 -0
- ksadk/interaction/provider.py +122 -0
- ksadk/interaction/providers/__init__.py +52 -0
- ksadk/interaction/providers/adk.py +40 -0
- ksadk/interaction/providers/codex.py +94 -0
- ksadk/interaction/providers/langgraph.py +58 -0
- ksadk/kernel/__init__.py +117 -0
- ksadk/kernel/authorization.py +258 -0
- ksadk/kernel/bootstrap.py +1074 -0
- ksadk/kernel/contract_fingerprints.py +61 -0
- ksadk/kernel/contracts.py +362 -0
- ksadk/kernel/control.py +219 -0
- ksadk/kernel/errors.py +79 -0
- ksadk/kernel/ingress.py +1102 -0
- ksadk/kernel/mapping.py +111 -0
- ksadk/kernel/memory_store.py +1133 -0
- ksadk/kernel/postgres_store.py +1756 -0
- ksadk/kernel/recovery.py +452 -0
- ksadk/kernel/runtime_identity.py +103 -0
- ksadk/kernel/sql/001_agent_kernel.sql +120 -0
- ksadk/kernel/sqlite_store.py +1410 -0
- ksadk/kernel/state.py +145 -0
- ksadk/kernel/store.py +232 -0
- ksadk/kernel/worker.py +953 -0
- ksadk/knowledge_base/client.py +7 -0
- ksadk/knowledge_base/service.py +32 -5
- ksadk/memory/__init__.py +61 -0
- ksadk/memory/adk/backends/base_ltm_backend.py +96 -1
- ksadk/memory/adk/backends/http_ltm_backend.py +14 -5
- ksadk/memory/adk/backends/inmemory_ltm_backend.py +136 -3
- ksadk/memory/adk/backends/sdk_ltm_backend.py +384 -2
- ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
- ksadk/memory/coordinator.py +461 -0
- ksadk/memory/events.py +202 -0
- ksadk/memory/extraction.py +228 -0
- ksadk/memory/ltm_backend_factory.py +16 -3
- ksadk/memory/models.py +316 -0
- ksadk/memory/policy.py +215 -0
- ksadk/memory/provider.py +47 -0
- ksadk/memory/provider_adapter.py +159 -0
- ksadk/memory/provider_resolver.py +71 -0
- ksadk/memory/providers/__init__.py +5 -0
- ksadk/memory/providers/local_sqlite.py +490 -0
- ksadk/memory/resolved_policy.py +145 -0
- ksadk/memory/service.py +188 -6
- ksadk/model_proxy/bootstrap.py +16 -9
- ksadk/model_proxy/detect.py +202 -9
- ksadk/model_proxy/namespace.py +39 -15
- ksadk/model_proxy/server.py +24 -5
- ksadk/model_proxy/transform.py +60 -2
- ksadk/observability/__init__.py +25 -0
- ksadk/observability/session_log.py +420 -0
- ksadk/observability/trajectory.py +105 -0
- ksadk/prompts/__init__.py +71 -0
- ksadk/prompts/compiler.py +215 -0
- ksadk/prompts/models.py +82 -0
- ksadk/prompts/projection.py +89 -0
- ksadk/prompts/resolved.py +137 -0
- ksadk/prompts/sources.py +233 -0
- ksadk/runners/_langgraph_runner_streams.py +822 -0
- ksadk/runners/adk_runner.py +5 -5
- ksadk/runners/base_runner.py +16 -0
- ksadk/runners/factory.py +1 -2
- ksadk/runners/langgraph_runner.py +198 -437
- ksadk/runtime/_runner_adapter/__init__.py +1 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
- ksadk/runtime/adapter.py +118 -2
- ksadk/runtime/conversation_execution.py +316 -182
- ksadk/runtime/executor.py +144 -3
- ksadk/runtime/factory.py +193 -7
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +14 -1
- ksadk/runtime/preprocessing.py +25 -3
- ksadk/runtime/runner_adapter.py +288 -508
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/backends/e2b.py +35 -2
- ksadk/server/composition.py +8 -0
- ksadk/server/factory.py +69 -6
- ksadk/server/routes/kernel_ingress.py +258 -0
- ksadk/server/routes/openai_compat.py +88 -8
- ksadk/server/routes/projection.py +35 -20
- ksadk/server/routes/run.py +94 -0
- ksadk/server/routes/sessions.py +2 -0
- ksadk/server/routes/streaming.py +5 -2
- ksadk/server/static/assets/{ArtifactsPanel-CakCqxEN.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-CynLknyO.js → CodeBlock-DOH6MVcn.js} +4 -4
- ksadk/server/static/assets/{MathMessageMarkdown-3sQdOysS.js → MathMessageMarkdown-BL8my1R2.js} +4 -4
- ksadk/server/static/assets/MathMessageMarkdown-BorAY7qD.css +1 -0
- ksadk/server/static/assets/MermaidBlock-Dz4IP-Tx.js +312 -0
- ksadk/server/static/assets/NativeTerminalPanel-DUrK0JpZ.js +1 -0
- ksadk/server/static/assets/abnfDiagram-VCTEODGH-g20pFzNV.js +1 -0
- ksadk/server/static/assets/arc-C4FzinUA.js +1 -0
- ksadk/server/static/assets/architecture-7GRP2DOG-DjKratdf.js +1 -0
- ksadk/server/static/assets/architectureDiagram-5GKGNRK7-DpIqL5h4.js +36 -0
- ksadk/server/static/assets/blockDiagram-NRAW4CY4-BjkljTNz.js +129 -0
- ksadk/server/static/assets/c4Diagram-UCG6FXSJ-Dk_ieq2X.js +38 -0
- ksadk/server/static/assets/channel-4cQHKtx1.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-DmgWkESh.js +1 -0
- ksadk/server/static/assets/{chunk-FMBD7UC4-B_fH2YuH.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D6rFLaVV.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-B9drTgOW.js → chunk-JWPE2WC7-vYvVJb_M.js} +1 -1
- ksadk/server/static/assets/chunk-LCL6LL3I-BcI6ysPT.js +206 -0
- ksadk/server/static/assets/chunk-POPQ4Y6H-C030x_Z1.js +1 -0
- ksadk/server/static/assets/chunk-RHFEMEQ7-yyGpsz4n.js +168 -0
- ksadk/server/static/assets/chunk-SVP7TREG-BLTlmMU7.js +88 -0
- ksadk/server/static/assets/chunk-XXDRQBXY-C_32ArgP.js +1 -0
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DLFd9Xi0.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-S5V4N54A-ChNs_Mdk.js → cose-bilkent-JH36ORCC-9YQYwdl0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DjEM48Qp.js +1 -0
- ksadk/server/static/assets/cynefinDiagram-5FMLGOSQ-ErLF5N13.js +62 -0
- ksadk/server/static/assets/cytoscape.esm-CyCl8rPi.js +321 -0
- ksadk/server/static/assets/dagre-3AP2YEHR-DFiQF-6f.js +4 -0
- ksadk/server/static/assets/dagre-BuhGnRI1.js +1 -0
- ksadk/server/static/assets/diagram-S7CK7UJ4-Bt1v8-GC.js +30 -0
- ksadk/server/static/assets/diagram-UQ7AKVKN-DSCxJdBK.js +41 -0
- ksadk/server/static/assets/diagram-VSXAHHWV-DHfYwp_9.js +3 -0
- ksadk/server/static/assets/diagram-VX7I27RA-DdzD-4Le.js +24 -0
- ksadk/server/static/assets/diagram-Z3DM3KII-Du-nAJ9F.js +24 -0
- ksadk/server/static/assets/{dist-Dli7qW-B.js → dist-8hqcx0sU.js} +1 -1
- ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
- ksadk/server/static/assets/{dist-C1sz5Eo3.js → dist-BE7bu-DL.js} +1 -1
- ksadk/server/static/assets/{dist-fhOuWds5.js → dist-BVDffZ0U.js} +1 -1
- ksadk/server/static/assets/{dist-BjOdlDjj.js → dist-BX8z72IC.js} +1 -1
- ksadk/server/static/assets/{dist-DsHPdk3W.js → dist-Bf2M8m3N.js} +1 -1
- ksadk/server/static/assets/{dist-o2OVmKvt.js → dist-BjU6y-A2.js} +1 -1
- ksadk/server/static/assets/{dist-DWKByxWV.js → dist-BytlxIDT.js} +1 -1
- ksadk/server/static/assets/{dist-DJN_6Y39.js → dist-CSh_DE14.js} +1 -1
- ksadk/server/static/assets/{dist-DQU9EWw-.js → dist-CXYYBw3_.js} +1 -1
- ksadk/server/static/assets/{dist-4N2NMVYg.js → dist-C_wsv-Qd.js} +1 -1
- ksadk/server/static/assets/{dist-gLnrGsoU.js → dist-ClxGviKw.js} +1 -1
- ksadk/server/static/assets/{dist-j6Dxmf_j.js → dist-CttYUqzS.js} +1 -1
- ksadk/server/static/assets/{dist-D6MpCZtz.js → dist-DNp6rLRA.js} +1 -1
- ksadk/server/static/assets/{dist-BB3-OwTQ.js → dist-DUX-id_F.js} +1 -1
- ksadk/server/static/assets/{dist-_pHPTyZ-.js → dist-DmldrHd_.js} +1 -1
- ksadk/server/static/assets/{dist-CWV4lDr1.js → dist-DnfXs8Vn.js} +2 -2
- ksadk/server/static/assets/{dist-B5oS1zcj.js → dist-Dq9gLD7L.js} +1 -1
- ksadk/server/static/assets/{dist-B-jNR6Vn.js → dist-W-TIVntx.js} +1 -1
- ksadk/server/static/assets/{dist-BIlKoW0k.js → dist-dDdADKFA.js} +1 -1
- ksadk/server/static/assets/{dist-X4TnqwOK.js → dist-dydu68Fl.js} +1 -1
- ksadk/server/static/assets/{dist-CmZHzlwZ.js → dist-ngtN0DJB.js} +1 -1
- ksadk/server/static/assets/ebnfDiagram-PWID7BFC-Da9C9NO1.js +1 -0
- ksadk/server/static/assets/erDiagram-SSCWMZ5O-EAGqqR79.js +99 -0
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CMgMaJrC.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BBKL0x3P.js +1 -0
- ksadk/server/static/assets/ganttDiagram-EL5Y4UJY-DqJsKb59.js +292 -0
- ksadk/server/static/assets/gitGraph-4MIJSDKK-Dw63mrhw.js +1 -0
- ksadk/server/static/assets/gitGraphDiagram-WWUBYQGX-B6g4dtDi.js +106 -0
- ksadk/server/static/assets/index-8ipRcQ-M.js +240 -0
- ksadk/server/static/assets/index-ByFCqjlh.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-B6iAblII.js +1 -0
- ksadk/server/static/assets/infoDiagram-RXCK75RN-Djm_nbd5.js +2 -0
- ksadk/server/static/assets/{ishikawaDiagram-YF4QCWOH-K0OOfVna.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-8LeOJaZp.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-C6uCgZrW.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
- ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
- ksadk/server/static/assets/{linear-hdBcYzM8.js → linear-BHjG8b-J.js} +1 -1
- ksadk/server/static/assets/mermaid-parser.core-KGSy4jWT.js +166 -0
- ksadk/server/static/assets/{mindmap-definition-RKZ34NQL-Bjy_2v4_.js → mindmap-definition-FBJOCRG2-9-HC88D4.js} +29 -29
- ksadk/server/static/assets/packet-AYTQ26CC-BOYAipuq.js +1 -0
- ksadk/server/static/assets/pegDiagram-XKGWAZYB-DrEZd4fD.js +1 -0
- ksadk/server/static/assets/pie-WAS4IAKB-Ctq0Kbku.js +1 -0
- ksadk/server/static/assets/pieDiagram-E7YTZNPT-DpjqOFFp.js +39 -0
- ksadk/server/static/assets/{quadrantDiagram-W4KKPZXB-BmkRbwCg.js → quadrantDiagram-AXDQQJYC-BiNhgOXX.js} +6 -6
- ksadk/server/static/assets/radar-RG4KPBEZ-DN0-ul_0.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-C6cC_to0.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BimjIuRc.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CvY65ABq.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-D72Iq_Tv.js +1 -0
- ksadk/server/static/assets/railroadDiagram-O6MQD6OU-_Y3Ojg6G.js +1 -0
- ksadk/server/static/assets/requirementDiagram-EFPCY7ZU-DeCFdg9K.js +84 -0
- ksadk/server/static/assets/{sankeyDiagram-5OEKKPKP-l6iXmU65.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-Cq6UBeQB.js → sequenceDiagram-WJ2MYXX4-OEpQQdr4.js} +10 -10
- ksadk/server/static/assets/sizeCapture-X5ZJPWSS-heUErzhI.js +1 -0
- ksadk/server/static/assets/stateDiagram-HBIQ2CUA-DvA3jSMB.js +1 -0
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BgQY03nz.js +1 -0
- ksadk/server/static/assets/swimlanes-XN3QIQJK-CR-dfN_t.js +1 -0
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-DLVw3q5Q.js +8 -0
- ksadk/server/static/assets/{timeline-definition-PNZ67QCA-DEz24vV0.js → timeline-definition-24CTP7MA-DAVJf1TX.js} +7 -7
- ksadk/server/static/assets/treeView-Q6P3EWNA-BMpO0wsB.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Et0aqzU3.js +1 -0
- ksadk/server/static/assets/vennDiagram-4TSXK5OY-DwM8eDkh.js +34 -0
- ksadk/server/static/assets/wardley-WFR3VGLG-CbY0mhpl.js +1 -0
- ksadk/server/static/assets/wardleyDiagram-VM6X3IG4-DZL-Zz2t.js +78 -0
- ksadk/server/static/assets/xychartDiagram-S5SC5T6Z-Dy6Yh_hu.js +7 -0
- ksadk/server/static/index.html +2 -2
- ksadk/sessions/__init__.py +26 -9
- ksadk/sessions/_local_service_sync.py +688 -0
- ksadk/sessions/_local_tables.py +21 -0
- ksadk/sessions/_postgres_schema.py +305 -0
- ksadk/sessions/_postgres_tables.py +15 -0
- ksadk/sessions/base.py +80 -1
- ksadk/sessions/in_memory.py +53 -2
- ksadk/sessions/local_service.py +63 -604
- ksadk/sessions/postgres_service.py +58 -148
- ksadk/sessions/resilient.py +35 -1
- ksadk/studio/api.py +577 -25
- ksadk/studio/api_contracts.py +114 -5
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/authoring.py +252 -27
- ksadk/studio/authoring_coordinator.py +799 -67
- ksadk/studio/builder.py +88 -11
- ksadk/studio/capabilities.py +17 -0
- ksadk/studio/cloud.py +1916 -95
- ksadk/studio/codex_agent_service.py +125 -14
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +138 -25
- ksadk/studio/codex_manifest.py +51 -22
- ksadk/studio/codex_run.py +46 -3
- ksadk/studio/compiler.py +1 -0
- ksadk/studio/contracts.py +114 -3
- ksadk/studio/event_store.py +25 -95
- ksadk/studio/framework_run.py +231 -3
- ksadk/studio/hosted_kernel.py +317 -0
- ksadk/studio/manifest_resolver.py +131 -0
- ksadk/studio/model_client.py +95 -9
- ksadk/studio/model_profile_service.py +1 -1
- ksadk/studio/operations.py +37 -5
- ksadk/studio/otel_trace.py +348 -42
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/repository.py +23 -2
- ksadk/studio/resource_catalog.py +43 -0
- ksadk/studio/run_service.py +563 -137
- ksadk/studio/runtime_source.py +42 -16
- ksadk/studio/service.py +1180 -72
- ksadk/studio/shared_web.py +32 -22
- ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
- ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
- ksadk/studio/static/index.html +2 -2
- ksadk/studio/templates.py +100 -8
- ksadk/studio/validator.py +19 -0
- ksadk/studio/workspace.py +30 -32
- ksadk/tracing/setup.py +304 -3
- ksadk/version.py +1 -1
- ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
- ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
- ksadk/events/parser.py +0 -191
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
- ksadk/server/static/assets/MermaidBlock-NERD_ef7.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-CiHWf82q.js +0 -1
- ksadk/server/static/assets/arc-DrgjcKhl.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CpZLRCcY.js +0 -1
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-BXoVRbQ6.js +0 -36
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-BnaB3Ywv.js +0 -132
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-Dw4weZcp.js +0 -10
- ksadk/server/static/assets/channel-Dt3rQTFI.js +0 -1
- ksadk/server/static/assets/chunk-2J33WTMH-ChjpLK7j.js +0 -1
- ksadk/server/static/assets/chunk-55IACEB6-CK4ROATy.js +0 -1
- ksadk/server/static/assets/chunk-727SXJPM-B9KtTTgw.js +0 -206
- ksadk/server/static/assets/chunk-AQP2D5EJ-1O1mki3m.js +0 -231
- ksadk/server/static/assets/chunk-QZHKN3VN-iXEZtKQc.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-DIveV17Q.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-DIveV17Q.js +0 -1
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
- ksadk/server/static/assets/dagre-BM42HDAG-D0QXg_MQ.js +0 -4
- ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
- ksadk/server/static/assets/diagram-2AECGRRQ-DBDDKwBQ.js +0 -43
- ksadk/server/static/assets/diagram-5GNKFQAL-BkwDOxmO.js +0 -10
- ksadk/server/static/assets/diagram-KO2AKTUF-Bv8waYvY.js +0 -3
- ksadk/server/static/assets/diagram-LMA3HP47-e1VECDdu.js +0 -24
- ksadk/server/static/assets/diagram-OG6HWLK6-Ds9adfRl.js +0 -24
- ksadk/server/static/assets/dist-B5J2uhNk.js +0 -1
- ksadk/server/static/assets/erDiagram-TEJ5UH35-BPItFKH6.js +0 -85
- ksadk/server/static/assets/eventmodeling-FCH6USID-DYFSxbqr.js +0 -1
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-BbYB9w5Y.js +0 -162
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-TQXa0KXv.js +0 -292
- ksadk/server/static/assets/gitGraph-WXDBUCRP-DyNYp6BN.js +0 -1
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-bKblCnpa.js +0 -106
- ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
- ksadk/server/static/assets/index-R52pJJvg.js +0 -177
- ksadk/server/static/assets/index-jJr3_955.css +0 -2
- ksadk/server/static/assets/info-J43DQDTF-WUx7qTde.js +0 -1
- ksadk/server/static/assets/infoDiagram-5YYISTIA-BGVT7J_i.js +0 -2
- ksadk/server/static/assets/katex-CYWseY5E.js +0 -265
- ksadk/server/static/assets/mermaid-parser.core-BWrDjSZM.js +0 -161
- ksadk/server/static/assets/packet-YPE3B663-BN13y_xl.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-ftSLXhhc.js +0 -1
- ksadk/server/static/assets/pieDiagram-4H26LBE5-GmmqNiVH.js +0 -30
- ksadk/server/static/assets/radar-GUYGQ44K-jaICkIeO.js +0 -1
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DSWFqL7c.js +0 -84
- ksadk/server/static/assets/stateDiagram-AJRCARHV-qzTQpg3Y.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-BYCoYGAN.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-Cpib_vlz.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-DQxfmVHK.js +0 -1
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-CMCixki2.js +0 -34
- ksadk/server/static/assets/wardley-L42UT6IY-BQYHnnkU.js +0 -1
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-CVzB8F9K.js +0 -78
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-BFBqBLc1.js +0 -7
- ksadk/studio/evaluation.py +0 -192
- ksadk/studio/static/assets/index-CaEN0eTR.css +0 -1
- ksadk/studio/static/assets/index-DI2eY_NH.js +0 -252
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.1.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
ksadk/runtime/runner_adapter.py
CHANGED
|
@@ -13,22 +13,32 @@ from __future__ import annotations
|
|
|
13
13
|
import asyncio
|
|
14
14
|
import copy
|
|
15
15
|
import inspect
|
|
16
|
-
import json
|
|
17
16
|
import logging
|
|
17
|
+
import time
|
|
18
18
|
from collections.abc import Mapping
|
|
19
|
-
from contextlib import nullcontext
|
|
20
19
|
from dataclasses import dataclass, field
|
|
21
20
|
from typing import Any, AsyncIterator, Dict, Optional, cast
|
|
22
21
|
|
|
23
|
-
from
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
from pydantic import JsonValue
|
|
23
|
+
|
|
24
|
+
from ksadk.events.canonical import (
|
|
25
|
+
ApprovalRequest,
|
|
26
|
+
InteractionRequested,
|
|
27
|
+
OutputRef,
|
|
28
|
+
RunCanceled,
|
|
29
|
+
RunCompleted,
|
|
30
|
+
RunInterrupted,
|
|
31
|
+
RunStarted,
|
|
32
|
+
RuntimeEvent,
|
|
33
|
+
SourceRef,
|
|
34
|
+
)
|
|
35
|
+
from ksadk.events.identity import (
|
|
36
|
+
stable_event_id,
|
|
37
|
+
stable_item_id,
|
|
38
|
+
stable_scope_id,
|
|
30
39
|
)
|
|
31
|
-
from ksadk.
|
|
40
|
+
from ksadk.kernel.contracts import RuntimeCapability, RuntimeCapabilityMatrix
|
|
41
|
+
from ksadk.kernel.errors import UnsupportedControlError
|
|
32
42
|
from ksadk.runners.base_runner import BaseRunner
|
|
33
43
|
from ksadk.runtime.adapter import (
|
|
34
44
|
RESUME_START_REQUEST_NATIVE_KEY,
|
|
@@ -44,79 +54,21 @@ from ksadk.runtime.adapter import (
|
|
|
44
54
|
)
|
|
45
55
|
from ksadk.runtime.preprocessing import PreparedRuntimeStart, prepare_runtime_start
|
|
46
56
|
from ksadk.runtime.runner_loading import ensure_runner_loaded
|
|
47
|
-
from ksadk.runtime_context import platform_invocation_scope
|
|
48
|
-
from ksadk.tools.gateway import approval_interrupt_info_from_result
|
|
49
57
|
|
|
50
58
|
logger = logging.getLogger(__name__)
|
|
51
59
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
async def _anext_or_stop(gen: AsyncIterator[Any]) -> Any:
|
|
57
|
-
"""取下一个 chunk;流结束返回 _STREAM_STOP sentinel(便于竞速)。"""
|
|
58
|
-
try:
|
|
59
|
-
return await gen.__anext__()
|
|
60
|
-
except StopAsyncIteration:
|
|
61
|
-
return _STREAM_STOP
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def _a2ui_surface_event(chunk: Any) -> tuple[str, dict[str, Any]] | None:
|
|
65
|
-
"""Recognize a validated A2UI tool envelope and make it a first-class event.
|
|
60
|
+
# 保留既有 monkeypatch patch 点:stream_mapping 在调用时经本模块属性解析。
|
|
61
|
+
from ksadk.conversations.runtime_observability import ( # noqa: E402,F401
|
|
62
|
+
_conversation_span_scope,
|
|
63
|
+
)
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"""
|
|
65
|
+
# dict-chunk 退化路径的流竞速/事件映射实现拆至 _runner_adapter 子包(纯移动,行为不变)。
|
|
66
|
+
from ksadk.runtime._runner_adapter.stream_mapping import ( # noqa: E402
|
|
67
|
+
_STREAM_STOP,
|
|
68
|
+
_RunnerStreamMappingMixin,
|
|
69
|
+
)
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
return None
|
|
76
|
-
value = chunk.get("tool_output", chunk.get("output"))
|
|
77
|
-
if value is not None and hasattr(value, "content"):
|
|
78
|
-
value = value.content
|
|
79
|
-
if isinstance(value, str):
|
|
80
|
-
try:
|
|
81
|
-
value = json.loads(value)
|
|
82
|
-
except (TypeError, ValueError):
|
|
83
|
-
return None
|
|
84
|
-
if not isinstance(value, Mapping):
|
|
85
|
-
return None
|
|
86
|
-
operations_raw = value.get("a2ui_operations")
|
|
87
|
-
if not isinstance(operations_raw, list) or not operations_raw:
|
|
88
|
-
return None
|
|
89
|
-
operations = [dict(operation) for operation in operations_raw if isinstance(operation, Mapping)]
|
|
90
|
-
if not operations:
|
|
91
|
-
return None
|
|
92
|
-
|
|
93
|
-
known: list[tuple[str, str]] = []
|
|
94
|
-
for operation in operations:
|
|
95
|
-
for key, event_type in (
|
|
96
|
-
("createSurface", EventType.A2UI_SURFACE_BEGIN),
|
|
97
|
-
("updateComponents", EventType.A2UI_SURFACE_UPDATE),
|
|
98
|
-
("updateDataModel", EventType.A2UI_SURFACE_UPDATE),
|
|
99
|
-
("deleteSurface", EventType.A2UI_SURFACE_END),
|
|
100
|
-
):
|
|
101
|
-
detail = operation.get(key)
|
|
102
|
-
if isinstance(detail, Mapping) and isinstance(detail.get("surfaceId"), str):
|
|
103
|
-
surface_id = detail["surfaceId"].strip()
|
|
104
|
-
if surface_id:
|
|
105
|
-
known.append((surface_id, event_type))
|
|
106
|
-
break
|
|
107
|
-
if not known:
|
|
108
|
-
return None
|
|
109
|
-
surface_ids = {surface_id for surface_id, _event_type in known}
|
|
110
|
-
if len(surface_ids) != 1:
|
|
111
|
-
logger.warning("ignoring A2UI tool result with multiple surfaces")
|
|
112
|
-
return None
|
|
113
|
-
surface_id = known[0][0]
|
|
114
|
-
event_type = (
|
|
115
|
-
EventType.A2UI_SURFACE_BEGIN
|
|
116
|
-
if any(kind == EventType.A2UI_SURFACE_BEGIN for _surface_id, kind in known)
|
|
117
|
-
else known[0][1]
|
|
118
|
-
)
|
|
119
|
-
return event_type, {"surface_id": surface_id, "operations": operations}
|
|
71
|
+
_ResumeKey = tuple[str, str, str, str, str]
|
|
120
72
|
|
|
121
73
|
|
|
122
74
|
def _coerce_literal(value: Any, allowed: tuple[str, ...], default: str) -> Any:
|
|
@@ -161,9 +113,13 @@ class _ActiveRun:
|
|
|
161
113
|
skip_runner: bool = False
|
|
162
114
|
done: bool = False
|
|
163
115
|
completion_metrics: dict[str, Any] = field(default_factory=dict)
|
|
116
|
+
# dict-chunk 退化路径:追踪已 ItemStarted 的 item key,避免重复发 Started。
|
|
117
|
+
started_items: set[tuple[str, str]] = field(default_factory=set)
|
|
118
|
+
# dict-chunk 退化路径:final_answer message 的 item_id,供 RunCompleted.output_refs 引用。
|
|
119
|
+
final_answer_item_id: Optional[str] = None
|
|
164
120
|
|
|
165
121
|
|
|
166
|
-
class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
122
|
+
class RunnerRuntimeAdapter(_RunnerStreamMappingMixin, RuntimeAdapter):
|
|
167
123
|
"""把 ``BaseRunner`` 映射为平台六动词的通用 adapter。"""
|
|
168
124
|
|
|
169
125
|
def __init__(self, runner: BaseRunner, *, runtime_type: str) -> None:
|
|
@@ -182,6 +138,63 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
182
138
|
|
|
183
139
|
# ---- 框架钩子(子类按需 override) ----
|
|
184
140
|
|
|
141
|
+
def capabilities(self) -> RuntimeCapabilityMatrix:
|
|
142
|
+
"""诚实矩阵:cancel 经 asyncio 任务打断(emulated,过 conformance);
|
|
143
|
+
resume/checkpoint 依赖 runner 声明的原生 checkpoint;attach/durable_restore
|
|
144
|
+
依赖 ``attach_runtime_handle`` seam 与跨进程持久化,内存表不算数。
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
def _unavailable(reason: str) -> RuntimeCapability:
|
|
148
|
+
return RuntimeCapability(supported=False, mode="unavailable", reason=reason)
|
|
149
|
+
|
|
150
|
+
checkpoint_capability = self._checkpoint_capability()
|
|
151
|
+
attach_seam = callable(getattr(self._runner, "attach_runtime_handle", None))
|
|
152
|
+
checkpoint_supported = bool(checkpoint_capability.supported)
|
|
153
|
+
durable_supported = bool(
|
|
154
|
+
checkpoint_capability.durable
|
|
155
|
+
and checkpoint_capability.shared_across_pods
|
|
156
|
+
and attach_seam
|
|
157
|
+
)
|
|
158
|
+
return RuntimeCapabilityMatrix(
|
|
159
|
+
cancel=RuntimeCapability(
|
|
160
|
+
supported=True,
|
|
161
|
+
mode="emulated",
|
|
162
|
+
reason="runner_stream_task_interrupt",
|
|
163
|
+
),
|
|
164
|
+
pause=_unavailable("runtime_no_native_pause"),
|
|
165
|
+
resume=(
|
|
166
|
+
RuntimeCapability(supported=True, mode="native")
|
|
167
|
+
if checkpoint_supported
|
|
168
|
+
else _unavailable("runtime_no_native_checkpoint")
|
|
169
|
+
),
|
|
170
|
+
submit_interaction=_unavailable("runtime_no_live_interaction_channel"),
|
|
171
|
+
attach=(
|
|
172
|
+
RuntimeCapability(supported=True, mode="native")
|
|
173
|
+
if attach_seam
|
|
174
|
+
else _unavailable("runner_no_durable_attach_seam")
|
|
175
|
+
),
|
|
176
|
+
steer=_unavailable("runtime_no_native_steer"),
|
|
177
|
+
inject=_unavailable("runtime_no_native_inject"),
|
|
178
|
+
checkpoint=(
|
|
179
|
+
RuntimeCapability(supported=True, mode="native")
|
|
180
|
+
if checkpoint_supported
|
|
181
|
+
else _unavailable("runtime_no_native_checkpoint")
|
|
182
|
+
),
|
|
183
|
+
durable_restore=(
|
|
184
|
+
RuntimeCapability(supported=True, mode="native")
|
|
185
|
+
if durable_supported
|
|
186
|
+
else _unavailable("durable_restore_requires_cross_process_checkpoint")
|
|
187
|
+
),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
async def durable_restore(self, handle: RunHandle) -> RunHandle:
|
|
191
|
+
if not self.capabilities().durable_restore.supported:
|
|
192
|
+
raise UnsupportedControlError(
|
|
193
|
+
f"{self._runtime_type} has no cross-process checkpoint backend for run "
|
|
194
|
+
f"{handle.run_id!r}"
|
|
195
|
+
)
|
|
196
|
+
return await self.attach(handle)
|
|
197
|
+
|
|
185
198
|
def _checkpoint_capability(self) -> CheckpointCapability:
|
|
186
199
|
"""诚实暴露 checkpoint 粒度。默认读 runner.describe_checkpoint_capability。"""
|
|
187
200
|
raw = {}
|
|
@@ -285,7 +298,7 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
285
298
|
)
|
|
286
299
|
attach = getattr(self._runner, "attach_runtime_handle", None)
|
|
287
300
|
if not callable(attach):
|
|
288
|
-
raise
|
|
301
|
+
raise UnsupportedControlError(
|
|
289
302
|
f"runner for {self._runtime_type!r} has no durable "
|
|
290
303
|
"attach_runtime_handle capability"
|
|
291
304
|
)
|
|
@@ -408,7 +421,7 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
408
421
|
capability = self._require_native_checkpoint_capability()
|
|
409
422
|
checkpoint_id = str(handle.native_ref.get("checkpoint_id") or "").strip()
|
|
410
423
|
if not checkpoint_id:
|
|
411
|
-
raise
|
|
424
|
+
raise UnsupportedControlError(
|
|
412
425
|
f"{self._runtime_type} runner has no native checkpoint for run "
|
|
413
426
|
f"{handle.run_id!r}"
|
|
414
427
|
)
|
|
@@ -425,7 +438,7 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
425
438
|
if capability.supported:
|
|
426
439
|
return capability
|
|
427
440
|
detail = capability.reason or "runner does not expose framework checkpoints"
|
|
428
|
-
raise
|
|
441
|
+
raise UnsupportedControlError(
|
|
429
442
|
f"{self._runtime_type} native checkpoint capability is unavailable: {detail}"
|
|
430
443
|
)
|
|
431
444
|
|
|
@@ -495,30 +508,19 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
495
508
|
# 消费 pending cancel:start 时若已记 pending,立即中断该 turn。
|
|
496
509
|
if handle.run_id in self._pending_cancels:
|
|
497
510
|
self._pending_cancels.discard(handle.run_id)
|
|
498
|
-
yield self.
|
|
499
|
-
handle,
|
|
500
|
-
EventType.RUN_CANCELED,
|
|
501
|
-
{
|
|
502
|
-
"status": "cancelled",
|
|
503
|
-
"cancel_result": CancelResult.PENDING_CANCEL_RECORDED.value,
|
|
504
|
-
},
|
|
505
|
-
)
|
|
511
|
+
yield self._make_run_canceled(handle, reason=CancelResult.PENDING_CANCEL_RECORDED.value)
|
|
506
512
|
return
|
|
507
513
|
|
|
508
514
|
if run.skip_runner:
|
|
509
515
|
run.done = True
|
|
510
516
|
self._active_runs.pop(handle.run_id, None)
|
|
511
|
-
yield self.
|
|
512
|
-
handle,
|
|
513
|
-
EventType.RUN_COMPLETED,
|
|
514
|
-
self._completion_payload(handle, status="already_resumed"),
|
|
515
|
-
)
|
|
517
|
+
yield self._make_run_completed(handle)
|
|
516
518
|
return
|
|
517
519
|
|
|
518
520
|
if run.resume_key is not None:
|
|
519
521
|
self._consumed_resumes.add(run.resume_key)
|
|
520
522
|
|
|
521
|
-
yield self.
|
|
523
|
+
yield self._make_run_started(handle)
|
|
522
524
|
|
|
523
525
|
request = run.__dict__.get("_start_request")
|
|
524
526
|
runner_input = self._build_runner_input(handle, request)
|
|
@@ -530,43 +532,35 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
530
532
|
run.stream = gen
|
|
531
533
|
async for event in gen:
|
|
532
534
|
yield event
|
|
533
|
-
if event.event_type ==
|
|
535
|
+
if event.event_type == "interaction.requested":
|
|
534
536
|
approval_interrupted = True
|
|
537
|
+
# Track pending approval for canonical streams that bypass
|
|
538
|
+
# _chunk_to_event (e.g. stream_canonical_events).
|
|
539
|
+
if isinstance(event, InteractionRequested):
|
|
540
|
+
call_id = str(event.interaction_id or "")
|
|
541
|
+
if call_id:
|
|
542
|
+
run.pending_approvals.add(call_id)
|
|
543
|
+
pending_ids = handle.native_ref.setdefault("pending_approval_ids", [])
|
|
544
|
+
if call_id not in pending_ids:
|
|
545
|
+
pending_ids.append(call_id)
|
|
535
546
|
if event.event_type in {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
547
|
+
"run.completed",
|
|
548
|
+
"run.failed",
|
|
549
|
+
"run.canceled",
|
|
550
|
+
"run.interrupted",
|
|
540
551
|
}:
|
|
541
552
|
terminal_event_seen = True
|
|
542
|
-
if event.event_type in {
|
|
553
|
+
if event.event_type in {"run.failed", "run.canceled"}:
|
|
543
554
|
return
|
|
544
555
|
|
|
545
556
|
if run.interrupt_event.is_set() and not terminal_event_seen:
|
|
546
|
-
yield self.
|
|
547
|
-
handle,
|
|
548
|
-
EventType.RUN_CANCELED,
|
|
549
|
-
{
|
|
550
|
-
"status": "cancelled",
|
|
551
|
-
"cancel_result": CancelResult.INTERRUPTED_ACTIVE_TURN.value,
|
|
552
|
-
},
|
|
557
|
+
yield self._make_run_canceled(
|
|
558
|
+
handle, reason=CancelResult.INTERRUPTED_ACTIVE_TURN.value
|
|
553
559
|
)
|
|
554
560
|
elif approval_interrupted and not terminal_event_seen:
|
|
555
|
-
yield self.
|
|
556
|
-
handle,
|
|
557
|
-
EventType.RUN_INTERRUPTED,
|
|
558
|
-
{"status": "input_required"},
|
|
559
|
-
)
|
|
561
|
+
yield self._make_run_interrupted(handle, reason="input_required")
|
|
560
562
|
elif not terminal_event_seen:
|
|
561
|
-
yield self.
|
|
562
|
-
handle,
|
|
563
|
-
EventType.RUN_COMPLETED,
|
|
564
|
-
self._completion_payload(
|
|
565
|
-
handle,
|
|
566
|
-
status="completed",
|
|
567
|
-
metrics=run.completion_metrics,
|
|
568
|
-
),
|
|
569
|
-
)
|
|
563
|
+
yield self._make_run_completed(handle, run=run, metrics=run.completion_metrics)
|
|
570
564
|
finally:
|
|
571
565
|
run.stream = None
|
|
572
566
|
run.done = True
|
|
@@ -585,15 +579,17 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
585
579
|
else {}
|
|
586
580
|
)
|
|
587
581
|
base_metadata = merged.get("metadata")
|
|
588
|
-
merged.update(
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
582
|
+
merged.update(
|
|
583
|
+
{
|
|
584
|
+
"input": override.get("input"),
|
|
585
|
+
"session_id": handle.session_id,
|
|
586
|
+
"invocation_id": handle.run_id,
|
|
587
|
+
"metadata": {
|
|
588
|
+
**(dict(base_metadata) if isinstance(base_metadata, Mapping) else {}),
|
|
589
|
+
**dict(override.get("metadata") or {}),
|
|
590
|
+
},
|
|
591
|
+
}
|
|
592
|
+
)
|
|
597
593
|
for key, value in override.items():
|
|
598
594
|
if key not in ("input", "metadata"):
|
|
599
595
|
merged[key] = value
|
|
@@ -617,355 +613,19 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
617
613
|
"metadata": metadata,
|
|
618
614
|
}
|
|
619
615
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
run = self._active_runs.get(handle.run_id)
|
|
624
|
-
interrupt = run.interrupt_event if run is not None else None
|
|
625
|
-
prepared_start = run.__dict__.get("_prepared_start") if run is not None else None
|
|
626
|
-
invocation_context = (
|
|
627
|
-
prepared_start.context if isinstance(prepared_start, PreparedRuntimeStart) else None
|
|
628
|
-
)
|
|
629
|
-
scope = (
|
|
630
|
-
platform_invocation_scope(invocation_context)
|
|
631
|
-
if invocation_context is not None
|
|
632
|
-
else nullcontext()
|
|
633
|
-
)
|
|
634
|
-
runner_name = _runner_name(self._runner)
|
|
635
|
-
accumulated_output = ""
|
|
636
|
-
usage: dict[str, Any] = {}
|
|
637
|
-
runner_gen: Optional[AsyncIterator[Any]] = None
|
|
638
|
-
async with _conversation_span_scope(runner_name) as span:
|
|
639
|
-
if isinstance(prepared_start, PreparedRuntimeStart):
|
|
640
|
-
_set_conversation_span_attributes(
|
|
641
|
-
span,
|
|
642
|
-
agent_id=str(handle.native_ref.get("agent_id") or "agent"),
|
|
643
|
-
user_id=str(handle.native_ref.get("user_id") or "user"),
|
|
644
|
-
session_id=handle.session_id,
|
|
645
|
-
invocation_id=handle.run_id,
|
|
646
|
-
runner_name=runner_name,
|
|
647
|
-
model=prepared_start.context.model,
|
|
648
|
-
response_id=prepared_start.response_id,
|
|
649
|
-
)
|
|
650
|
-
_set_conversation_input_attributes(span, prepared_start.input_text)
|
|
651
|
-
try:
|
|
652
|
-
with scope:
|
|
653
|
-
canonical_stream = getattr(self._runner, "stream_runtime_events", None)
|
|
654
|
-
stream_result = (
|
|
655
|
-
canonical_stream(runner_input)
|
|
656
|
-
if callable(canonical_stream)
|
|
657
|
-
else self._runner.stream(runner_input)
|
|
658
|
-
)
|
|
659
|
-
if inspect.iscoroutine(stream_result):
|
|
660
|
-
# runner.stream 若声明为 async def -> AsyncIterator(非 async generator),
|
|
661
|
-
# 调用返回 coroutine,需 await 得到迭代器。
|
|
662
|
-
stream_result = await stream_result
|
|
663
|
-
runner_gen = cast(AsyncIterator[Any], stream_result)
|
|
664
|
-
while True:
|
|
665
|
-
# 竞速:下一个 runner chunk vs cancel 中断事件。
|
|
666
|
-
chunk_task = asyncio.ensure_future(_anext_or_stop(runner_gen))
|
|
667
|
-
if run is not None:
|
|
668
|
-
run.chunk_task = chunk_task
|
|
669
|
-
wait_set = {chunk_task}
|
|
670
|
-
interrupt_task = (
|
|
671
|
-
asyncio.ensure_future(interrupt.wait())
|
|
672
|
-
if interrupt is not None
|
|
673
|
-
else None
|
|
674
|
-
)
|
|
675
|
-
if interrupt_task is not None:
|
|
676
|
-
wait_set.add(interrupt_task)
|
|
677
|
-
done, pending = await asyncio.wait(
|
|
678
|
-
wait_set, return_when=asyncio.FIRST_COMPLETED
|
|
679
|
-
)
|
|
680
|
-
for task in pending:
|
|
681
|
-
task.cancel()
|
|
682
|
-
if pending:
|
|
683
|
-
await asyncio.gather(*pending, return_exceptions=True)
|
|
684
|
-
if interrupt_task is not None and interrupt_task in done:
|
|
685
|
-
# cancel 中断:安全关闭 runner 流(同一 task)并停止。
|
|
686
|
-
chunk_task.cancel()
|
|
687
|
-
await asyncio.gather(chunk_task, return_exceptions=True)
|
|
688
|
-
return
|
|
689
|
-
try:
|
|
690
|
-
chunk = chunk_task.result()
|
|
691
|
-
except asyncio.CancelledError:
|
|
692
|
-
if interrupt is not None and interrupt.is_set():
|
|
693
|
-
return
|
|
694
|
-
raise
|
|
695
|
-
finally:
|
|
696
|
-
if run is not None:
|
|
697
|
-
run.chunk_task = None
|
|
698
|
-
if chunk is _STREAM_STOP:
|
|
699
|
-
return
|
|
700
|
-
if isinstance(chunk, RuntimeEvent):
|
|
701
|
-
if chunk.event_type in {
|
|
702
|
-
EventType.TEXT_DELTA,
|
|
703
|
-
EventType.TEXT_COMPLETED,
|
|
704
|
-
} and chunk.phase == "final_answer":
|
|
705
|
-
text = self._coerce(chunk.payload.get("text"))
|
|
706
|
-
if chunk.event_type == EventType.TEXT_COMPLETED:
|
|
707
|
-
accumulated_output = text
|
|
708
|
-
else:
|
|
709
|
-
accumulated_output += text
|
|
710
|
-
elif chunk.event_type == EventType.USAGE_REPORTED:
|
|
711
|
-
usage.update(chunk.payload)
|
|
712
|
-
if isinstance(chunk, dict):
|
|
713
|
-
chunk_type = str(chunk.get("type") or "")
|
|
714
|
-
if chunk_type == "final" and run is not None:
|
|
715
|
-
for source_key, target_key in (
|
|
716
|
-
("duration_ms", "duration_ms"),
|
|
717
|
-
("started_at", "started_at"),
|
|
718
|
-
("completed_at", "completed_at"),
|
|
719
|
-
("metrics_source", "source"),
|
|
720
|
-
):
|
|
721
|
-
if chunk.get(source_key) is not None:
|
|
722
|
-
run.completion_metrics[target_key] = chunk[source_key]
|
|
723
|
-
if chunk_type in {"final", "text", "text_delta"}:
|
|
724
|
-
text = self._coerce(
|
|
725
|
-
chunk.get("delta") or chunk.get("output") or chunk.get("data")
|
|
726
|
-
)
|
|
727
|
-
if text:
|
|
728
|
-
if chunk_type == "final" or chunk.get("replace"):
|
|
729
|
-
accumulated_output = text
|
|
730
|
-
else:
|
|
731
|
-
accumulated_output += text
|
|
732
|
-
raw_usage = chunk.get("usage")
|
|
733
|
-
if isinstance(raw_usage, dict):
|
|
734
|
-
usage.update(raw_usage)
|
|
735
|
-
event = self._chunk_to_event(handle, run, chunk)
|
|
736
|
-
if event is not None:
|
|
737
|
-
yield event
|
|
738
|
-
a2ui_surface = _a2ui_surface_event(chunk)
|
|
739
|
-
if a2ui_surface is not None:
|
|
740
|
-
event_type, payload = a2ui_surface
|
|
741
|
-
yield self._event(handle, event_type, payload)
|
|
742
|
-
finally:
|
|
743
|
-
if accumulated_output:
|
|
744
|
-
_set_conversation_output_attributes(span, accumulated_output)
|
|
745
|
-
_set_conversation_usage_attributes(span, usage)
|
|
746
|
-
if runner_gen is not None:
|
|
747
|
-
aclose = getattr(runner_gen, "aclose", None)
|
|
748
|
-
if callable(aclose):
|
|
749
|
-
try:
|
|
750
|
-
await aclose()
|
|
751
|
-
except Exception: # noqa: BLE001
|
|
752
|
-
pass
|
|
753
|
-
if run is not None:
|
|
754
|
-
run.cancellation_ack.set()
|
|
755
|
-
|
|
756
|
-
def _chunk_to_event(
|
|
757
|
-
self, handle: RunHandle, run: Optional[_ActiveRun], chunk: Any
|
|
758
|
-
) -> Optional[RuntimeEvent]:
|
|
759
|
-
if isinstance(chunk, RuntimeEvent):
|
|
760
|
-
# Outer adapter owns the public lifecycle envelope. A native
|
|
761
|
-
# Runtime may emit its own RUN_STARTED with private identifiers;
|
|
762
|
-
# suppress that duplicate and rebind all other canonical events
|
|
763
|
-
# to the public handle without flattening their payloads.
|
|
764
|
-
if chunk.event_type == EventType.RUN_STARTED:
|
|
765
|
-
return None
|
|
766
|
-
return RuntimeEvent.create(
|
|
767
|
-
chunk.event_type,
|
|
768
|
-
agent_id=str(handle.native_ref.get("agent_id") or "agent"),
|
|
769
|
-
user_id=str(handle.native_ref.get("user_id") or "user"),
|
|
770
|
-
session_id=handle.session_id,
|
|
771
|
-
invocation_id=handle.run_id,
|
|
772
|
-
seq_id=self._next_seq(),
|
|
773
|
-
phase=chunk.phase,
|
|
774
|
-
payload=dict(chunk.payload),
|
|
775
|
-
event_id=chunk.event_id,
|
|
776
|
-
timestamp=chunk.timestamp,
|
|
777
|
-
)
|
|
778
|
-
if not isinstance(chunk, dict):
|
|
779
|
-
return self._event(
|
|
780
|
-
handle, EventType.TEXT_DELTA, {"text": str(chunk)}, phase="commentary"
|
|
781
|
-
)
|
|
782
|
-
chunk_type = chunk.get("type")
|
|
783
|
-
if chunk_type in ("reasoning", "reasoning_delta", "thinking"):
|
|
784
|
-
text = self._coerce(
|
|
785
|
-
chunk.get("delta")
|
|
786
|
-
or chunk.get("content")
|
|
787
|
-
or chunk.get("output")
|
|
788
|
-
or chunk.get("data")
|
|
789
|
-
)
|
|
790
|
-
if not text:
|
|
791
|
-
return None
|
|
792
|
-
event_type = (
|
|
793
|
-
EventType.REASONING_COMPLETED
|
|
794
|
-
if chunk.get("status") in ("completed", "done")
|
|
795
|
-
else EventType.REASONING_DELTA
|
|
796
|
-
)
|
|
797
|
-
return self._event(
|
|
798
|
-
handle,
|
|
799
|
-
event_type,
|
|
800
|
-
{"text": text},
|
|
801
|
-
phase="commentary",
|
|
802
|
-
)
|
|
803
|
-
if chunk_type in ("tool_call", "tool_start"):
|
|
804
|
-
call_id = str(
|
|
805
|
-
chunk.get("tool_call_id")
|
|
806
|
-
or chunk.get("call_id")
|
|
807
|
-
or chunk.get("run_id")
|
|
808
|
-
or chunk.get("id")
|
|
809
|
-
or ""
|
|
810
|
-
)
|
|
811
|
-
name = str(chunk.get("tool_name") or chunk.get("name") or "tool")
|
|
812
|
-
return self._event(
|
|
813
|
-
handle,
|
|
814
|
-
EventType.TOOL_CALL_BEGIN,
|
|
815
|
-
{
|
|
816
|
-
"call_id": call_id or name,
|
|
817
|
-
"name": name,
|
|
818
|
-
"args": chunk.get("tool_args", chunk.get("args")),
|
|
819
|
-
},
|
|
820
|
-
)
|
|
821
|
-
if chunk_type in ("tool_result", "tool_end"):
|
|
822
|
-
call_id = str(
|
|
823
|
-
chunk.get("tool_call_id")
|
|
824
|
-
or chunk.get("call_id")
|
|
825
|
-
or chunk.get("run_id")
|
|
826
|
-
or chunk.get("id")
|
|
827
|
-
or ""
|
|
828
|
-
)
|
|
829
|
-
name = str(chunk.get("tool_name") or chunk.get("name") or "tool")
|
|
830
|
-
tool_args = chunk.get("tool_args", chunk.get("args"))
|
|
831
|
-
result = chunk.get("tool_output", chunk.get("output"))
|
|
832
|
-
approval_detail = approval_interrupt_info_from_result(
|
|
833
|
-
result,
|
|
834
|
-
fallback_tool_name=name,
|
|
835
|
-
tool_args=tool_args,
|
|
836
|
-
run_id=call_id or None,
|
|
837
|
-
)
|
|
838
|
-
if approval_detail is not None:
|
|
839
|
-
return self._approval_requested_event(
|
|
840
|
-
handle,
|
|
841
|
-
run,
|
|
842
|
-
detail=approval_detail,
|
|
843
|
-
call_id=call_id,
|
|
844
|
-
)
|
|
845
|
-
return self._event(
|
|
846
|
-
handle,
|
|
847
|
-
EventType.TOOL_CALL_END,
|
|
848
|
-
{
|
|
849
|
-
"call_id": call_id or name,
|
|
850
|
-
"name": name,
|
|
851
|
-
"result": result,
|
|
852
|
-
"error": chunk.get("error"),
|
|
853
|
-
},
|
|
854
|
-
)
|
|
855
|
-
if chunk_type in ("interrupt", "approval", "approval_required"):
|
|
856
|
-
raw_detail = chunk.get("interrupt_info") or chunk.get("detail") or {}
|
|
857
|
-
detail = dict(raw_detail) if isinstance(raw_detail, Mapping) else {}
|
|
858
|
-
call_id = str(
|
|
859
|
-
chunk.get("call_id")
|
|
860
|
-
or chunk.get("approval_id")
|
|
861
|
-
or chunk.get("id")
|
|
862
|
-
or ""
|
|
863
|
-
)
|
|
864
|
-
return self._approval_requested_event(
|
|
865
|
-
handle,
|
|
866
|
-
run,
|
|
867
|
-
detail=detail,
|
|
868
|
-
call_id=call_id,
|
|
869
|
-
)
|
|
870
|
-
if chunk_type == "checkpoint":
|
|
871
|
-
raw_metadata = chunk.get("metadata")
|
|
872
|
-
metadata: dict[str, Any] = raw_metadata if isinstance(raw_metadata, dict) else {}
|
|
873
|
-
raw_agentengine = metadata.get("agentengine")
|
|
874
|
-
agentengine: dict[str, Any] = (
|
|
875
|
-
raw_agentengine if isinstance(raw_agentengine, dict) else {}
|
|
876
|
-
)
|
|
877
|
-
framework = str(agentengine.get("framework") or self._runtime_type)
|
|
878
|
-
framework_ref = agentengine.get("framework_ref") or {}
|
|
879
|
-
runtime_ref = (
|
|
880
|
-
framework_ref.get(framework) if isinstance(framework_ref, dict) else {}
|
|
881
|
-
) or {}
|
|
882
|
-
checkpoint_id = str(
|
|
883
|
-
runtime_ref.get("checkpoint_id") if isinstance(runtime_ref, dict) else ""
|
|
884
|
-
)
|
|
885
|
-
if not checkpoint_id:
|
|
886
|
-
return None
|
|
887
|
-
handle.native_ref["checkpoint_id"] = checkpoint_id
|
|
888
|
-
known_checkpoint_ids = handle.native_ref.setdefault("known_checkpoint_ids", [])
|
|
889
|
-
if checkpoint_id not in known_checkpoint_ids:
|
|
890
|
-
known_checkpoint_ids.append(checkpoint_id)
|
|
891
|
-
handle.native_ref["framework_ref"] = framework_ref
|
|
892
|
-
if isinstance(runtime_ref, dict):
|
|
893
|
-
handle.native_ref.update(runtime_ref)
|
|
894
|
-
return self._event(
|
|
895
|
-
handle,
|
|
896
|
-
EventType.CHECKPOINT_CREATED,
|
|
897
|
-
{
|
|
898
|
-
"checkpoint_id": checkpoint_id,
|
|
899
|
-
"granularity": self._checkpoint_capability().granularity,
|
|
900
|
-
"run_id": str(agentengine.get("run_id") or handle.run_id),
|
|
901
|
-
"framework": framework,
|
|
902
|
-
"framework_ref": framework_ref,
|
|
903
|
-
"resume_target": framework_ref,
|
|
904
|
-
},
|
|
905
|
-
)
|
|
906
|
-
if chunk_type == "graph_update":
|
|
907
|
-
return self._event(
|
|
908
|
-
handle,
|
|
909
|
-
EventType.RUN_PROGRESS,
|
|
910
|
-
{
|
|
911
|
-
"status": "in_progress",
|
|
912
|
-
"node": str(chunk.get("node") or ""),
|
|
913
|
-
"state_update": self._coerce(chunk.get("output")),
|
|
914
|
-
},
|
|
915
|
-
)
|
|
916
|
-
if chunk_type == "usage":
|
|
917
|
-
raw_usage = chunk.get("usage")
|
|
918
|
-
usage: dict[str, Any] = raw_usage if isinstance(raw_usage, dict) else {}
|
|
919
|
-
return self._event(
|
|
920
|
-
handle,
|
|
921
|
-
EventType.USAGE_REPORTED,
|
|
922
|
-
{
|
|
923
|
-
"input_tokens": int(usage.get("input_tokens") or 0),
|
|
924
|
-
"output_tokens": int(usage.get("output_tokens") or 0),
|
|
925
|
-
"total_tokens": int(usage.get("total_tokens") or 0),
|
|
926
|
-
"cached_tokens": int(usage.get("cached_tokens") or 0),
|
|
927
|
-
"reasoning_tokens": int(usage.get("reasoning_tokens") or 0),
|
|
928
|
-
"source": str(usage.get("source") or self._runtime_type),
|
|
929
|
-
},
|
|
930
|
-
)
|
|
931
|
-
if chunk_type == "error":
|
|
932
|
-
error = self._coerce(chunk.get("message") or chunk.get("error"))
|
|
933
|
-
return self._event(
|
|
934
|
-
handle,
|
|
935
|
-
EventType.RUN_FAILED,
|
|
936
|
-
{
|
|
937
|
-
"status": "failed",
|
|
938
|
-
"error": error or "runner failed",
|
|
939
|
-
},
|
|
940
|
-
)
|
|
941
|
-
if chunk_type == "final":
|
|
942
|
-
return self._event(
|
|
943
|
-
handle,
|
|
944
|
-
EventType.TEXT_COMPLETED,
|
|
945
|
-
{"text": self._coerce(chunk.get("output"))},
|
|
946
|
-
phase="final_answer",
|
|
947
|
-
)
|
|
948
|
-
text = self._coerce(chunk.get("delta") or chunk.get("output") or chunk.get("data"))
|
|
949
|
-
if not text:
|
|
950
|
-
return None
|
|
951
|
-
payload: dict[str, Any] = {"text": text}
|
|
952
|
-
if chunk.get("replace"):
|
|
953
|
-
payload["replace"] = True
|
|
954
|
-
return self._event(handle, EventType.TEXT_DELTA, payload, phase="commentary")
|
|
955
|
-
|
|
956
|
-
def _approval_requested_event(
|
|
616
|
+
# ---- canonical event construction helpers ----
|
|
617
|
+
|
|
618
|
+
def _interaction_requested_from_approval(
|
|
957
619
|
self,
|
|
958
620
|
handle: RunHandle,
|
|
959
621
|
run: Optional[_ActiveRun],
|
|
960
622
|
*,
|
|
961
623
|
detail: Mapping[str, Any],
|
|
962
624
|
call_id: str,
|
|
963
|
-
) -> RuntimeEvent:
|
|
964
|
-
"""
|
|
625
|
+
) -> list[RuntimeEvent]:
|
|
626
|
+
"""把 ToolGateway 结果中携带的审批请求转为 canonical InteractionRequested。"""
|
|
965
627
|
|
|
966
|
-
approval_id = str(
|
|
967
|
-
detail.get("approval_request_id") or detail.get("id") or call_id or ""
|
|
968
|
-
)
|
|
628
|
+
approval_id = str(detail.get("approval_request_id") or detail.get("id") or call_id or "")
|
|
969
629
|
resolved_call_id = str(call_id or approval_id)
|
|
970
630
|
if run is not None and approval_id:
|
|
971
631
|
run.pending_approvals.add(approval_id)
|
|
@@ -973,52 +633,172 @@ class RunnerRuntimeAdapter(RuntimeAdapter):
|
|
|
973
633
|
pending_approval_ids = handle.native_ref.setdefault("pending_approval_ids", [])
|
|
974
634
|
if approval_id not in pending_approval_ids:
|
|
975
635
|
pending_approval_ids.append(approval_id)
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
636
|
+
framework = self._runtime_type
|
|
637
|
+
run_id = handle.run_id
|
|
638
|
+
scope_id = stable_scope_id(framework, run_id)
|
|
639
|
+
interaction_id = resolved_call_id or stable_item_id(framework, run_id, "interaction")
|
|
640
|
+
item_id = stable_item_id(framework, run_id, "interaction")
|
|
641
|
+
detail_value: JsonValue = (
|
|
642
|
+
cast(JsonValue, dict(detail)) if isinstance(detail, Mapping) else None
|
|
643
|
+
)
|
|
644
|
+
return [
|
|
645
|
+
InteractionRequested(
|
|
646
|
+
**self._canonical_kwargs(
|
|
647
|
+
handle,
|
|
648
|
+
scope_id=scope_id,
|
|
649
|
+
item_id=item_id,
|
|
650
|
+
event_type="interaction.requested",
|
|
651
|
+
part_id="interaction",
|
|
652
|
+
),
|
|
653
|
+
interaction_id=interaction_id,
|
|
654
|
+
interaction_kind="approval",
|
|
655
|
+
request=ApprovalRequest(
|
|
656
|
+
call_id=resolved_call_id or None,
|
|
657
|
+
kind="tool",
|
|
658
|
+
detail=detail_value,
|
|
659
|
+
),
|
|
660
|
+
)
|
|
661
|
+
]
|
|
662
|
+
|
|
663
|
+
def _make_source(self, handle: RunHandle, *, protocol: str | None = None) -> SourceRef:
|
|
664
|
+
# SourceRef.framework 是封闭枚举;测试 fixture 或自定义 runtime_type 落到
|
|
665
|
+
# 通用 "ksadk",原生框架名原样保留。
|
|
666
|
+
framework = self._runtime_type
|
|
667
|
+
if framework not in {"adk", "langgraph", "codex", "a2a", "ksadk"}:
|
|
668
|
+
framework = "ksadk"
|
|
669
|
+
return SourceRef(
|
|
670
|
+
framework=framework,
|
|
671
|
+
protocol=protocol,
|
|
672
|
+
native_run_id=handle.run_id,
|
|
673
|
+
metadata={
|
|
674
|
+
"agent_id": str(handle.native_ref.get("agent_id") or "agent"),
|
|
675
|
+
"user_id": str(handle.native_ref.get("user_id") or "user"),
|
|
676
|
+
"session_id": handle.session_id,
|
|
677
|
+
"invocation_id": handle.run_id,
|
|
984
678
|
},
|
|
985
679
|
)
|
|
986
680
|
|
|
987
|
-
def
|
|
681
|
+
def _canonical_kwargs(
|
|
988
682
|
self,
|
|
989
683
|
handle: RunHandle,
|
|
990
|
-
event_type: str,
|
|
991
|
-
payload: dict,
|
|
992
684
|
*,
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
685
|
+
scope_id: str,
|
|
686
|
+
item_id: str,
|
|
687
|
+
event_type: str,
|
|
688
|
+
part_id: str,
|
|
689
|
+
) -> dict[str, Any]:
|
|
690
|
+
"""Build common EventEnvelope kwargs for the dict-chunk degraded path."""
|
|
691
|
+
framework = self._runtime_type
|
|
692
|
+
run_id = handle.run_id
|
|
693
|
+
# TODO(runtime-event-v2): dict chunk 退化路径,chunk_ordinal 用 seq counter;
|
|
694
|
+
# LangGraph/Codex 切 stream_canonical_events 后清理
|
|
695
|
+
n = self._next_seq()
|
|
696
|
+
return {
|
|
697
|
+
"schema_version": 2,
|
|
698
|
+
"event_id": stable_event_id(
|
|
699
|
+
framework, scope_id, item_id, event_type, part_id, run_id, n
|
|
700
|
+
),
|
|
701
|
+
"seq": n,
|
|
702
|
+
"timestamp": time.time(),
|
|
703
|
+
"run_id": run_id,
|
|
704
|
+
"scope_id": scope_id,
|
|
705
|
+
"source": self._make_source(handle),
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
def _make_run_started(self, handle: RunHandle) -> RunStarted:
|
|
709
|
+
framework = self._runtime_type
|
|
710
|
+
run_id = handle.run_id
|
|
711
|
+
scope_id = stable_scope_id(framework, run_id)
|
|
712
|
+
item_id = stable_item_id(framework, run_id, "$run")
|
|
713
|
+
return RunStarted(
|
|
714
|
+
schema_version=2,
|
|
715
|
+
event_id=stable_event_id(framework, scope_id, item_id, "run.started", "run", run_id, 0),
|
|
716
|
+
seq=self._next_seq(),
|
|
717
|
+
timestamp=time.time(),
|
|
718
|
+
run_id=run_id,
|
|
719
|
+
scope_id=scope_id,
|
|
720
|
+
source=self._make_source(handle),
|
|
721
|
+
status="running",
|
|
1004
722
|
)
|
|
1005
723
|
|
|
1006
|
-
def
|
|
724
|
+
def _make_run_completed(
|
|
1007
725
|
self,
|
|
1008
726
|
handle: RunHandle,
|
|
1009
727
|
*,
|
|
1010
|
-
|
|
728
|
+
run: Optional[_ActiveRun] = None,
|
|
1011
729
|
metrics: Mapping[str, Any] | None = None,
|
|
1012
|
-
) ->
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
730
|
+
) -> RunCompleted:
|
|
731
|
+
framework = self._runtime_type
|
|
732
|
+
run_id = handle.run_id
|
|
733
|
+
scope_id = stable_scope_id(framework, run_id)
|
|
734
|
+
item_id = stable_item_id(framework, run_id, "$run")
|
|
735
|
+
output_refs: tuple[OutputRef, ...] = ()
|
|
736
|
+
if run is not None and run.final_answer_item_id:
|
|
737
|
+
output_refs = (
|
|
738
|
+
OutputRef(
|
|
739
|
+
scope_id=scope_id,
|
|
740
|
+
item_id=run.final_answer_item_id,
|
|
741
|
+
part_id="text-0",
|
|
742
|
+
),
|
|
743
|
+
)
|
|
744
|
+
source = self._make_source(handle)
|
|
745
|
+
if metrics:
|
|
746
|
+
source = source.model_copy(
|
|
747
|
+
update={"metadata": {**source.metadata, "metrics": dict(metrics)}}
|
|
748
|
+
)
|
|
749
|
+
return RunCompleted(
|
|
750
|
+
schema_version=2,
|
|
751
|
+
event_id=stable_event_id(
|
|
752
|
+
framework, scope_id, item_id, "run.completed", "run", run_id, 0
|
|
753
|
+
),
|
|
754
|
+
seq=self._next_seq(),
|
|
755
|
+
timestamp=time.time(),
|
|
756
|
+
run_id=run_id,
|
|
757
|
+
scope_id=scope_id,
|
|
758
|
+
source=source,
|
|
759
|
+
status="completed",
|
|
760
|
+
output_refs=output_refs,
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
def _make_run_canceled(self, handle: RunHandle, *, reason: str | None = None) -> RunCanceled:
|
|
764
|
+
framework = self._runtime_type
|
|
765
|
+
run_id = handle.run_id
|
|
766
|
+
scope_id = stable_scope_id(framework, run_id)
|
|
767
|
+
item_id = stable_item_id(framework, run_id, "$run")
|
|
768
|
+
return RunCanceled(
|
|
769
|
+
schema_version=2,
|
|
770
|
+
event_id=stable_event_id(
|
|
771
|
+
framework, scope_id, item_id, "run.canceled", "run", run_id, 0
|
|
772
|
+
),
|
|
773
|
+
seq=self._next_seq(),
|
|
774
|
+
timestamp=time.time(),
|
|
775
|
+
run_id=run_id,
|
|
776
|
+
scope_id=scope_id,
|
|
777
|
+
source=self._make_source(handle),
|
|
778
|
+
status="canceled",
|
|
779
|
+
reason=reason,
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
def _make_run_interrupted(
|
|
783
|
+
self, handle: RunHandle, *, reason: str | None = None
|
|
784
|
+
) -> RunInterrupted:
|
|
785
|
+
framework = self._runtime_type
|
|
786
|
+
run_id = handle.run_id
|
|
787
|
+
scope_id = stable_scope_id(framework, run_id)
|
|
788
|
+
item_id = stable_item_id(framework, run_id, "$run")
|
|
789
|
+
return RunInterrupted(
|
|
790
|
+
schema_version=2,
|
|
791
|
+
event_id=stable_event_id(
|
|
792
|
+
framework, scope_id, item_id, "run.interrupted", "run", run_id, 0
|
|
793
|
+
),
|
|
794
|
+
seq=self._next_seq(),
|
|
795
|
+
timestamp=time.time(),
|
|
796
|
+
run_id=run_id,
|
|
797
|
+
scope_id=scope_id,
|
|
798
|
+
source=self._make_source(handle),
|
|
799
|
+
status="interrupted",
|
|
800
|
+
reason=reason,
|
|
801
|
+
)
|
|
1022
802
|
|
|
1023
803
|
@staticmethod
|
|
1024
804
|
def _coerce(value: Any) -> str:
|