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/agui/agent.py
CHANGED
|
@@ -7,6 +7,7 @@ import copy
|
|
|
7
7
|
import hashlib
|
|
8
8
|
import json
|
|
9
9
|
import logging
|
|
10
|
+
import time
|
|
10
11
|
from dataclasses import dataclass, field
|
|
11
12
|
from importlib import import_module
|
|
12
13
|
from typing import Any, AsyncIterator, Callable, Mapping, Optional, cast
|
|
@@ -36,12 +37,34 @@ from ag_ui.core import (
|
|
|
36
37
|
ToolCallStartEvent,
|
|
37
38
|
)
|
|
38
39
|
|
|
39
|
-
from ksadk.agui
|
|
40
|
+
from ksadk.agui import _agent_helpers
|
|
40
41
|
from ksadk.conversations.runtime_metadata import (
|
|
41
42
|
_update_session_metadata_after_assistant_turn,
|
|
42
43
|
prime_session_metadata_for_user_turn,
|
|
43
44
|
)
|
|
44
|
-
from ksadk.events.
|
|
45
|
+
from ksadk.events.canonical import (
|
|
46
|
+
ApprovalResponse,
|
|
47
|
+
ContentSnapshot,
|
|
48
|
+
ContinuationCreated,
|
|
49
|
+
InteractionRequested,
|
|
50
|
+
InteractionResolved,
|
|
51
|
+
ItemCompleted,
|
|
52
|
+
ItemSnapshotReplaced,
|
|
53
|
+
ItemStarted,
|
|
54
|
+
ItemUpdated,
|
|
55
|
+
RunCanceled,
|
|
56
|
+
RunCompleted,
|
|
57
|
+
RunFailed,
|
|
58
|
+
RunInterrupted,
|
|
59
|
+
RunStarted,
|
|
60
|
+
RuntimeEvent,
|
|
61
|
+
SourceRef,
|
|
62
|
+
)
|
|
63
|
+
from ksadk.events.content import (
|
|
64
|
+
TextContent,
|
|
65
|
+
ToolCallContent,
|
|
66
|
+
ToolResultContent,
|
|
67
|
+
)
|
|
45
68
|
from ksadk.runtime.adapter import (
|
|
46
69
|
CancelResult,
|
|
47
70
|
ResumePayload,
|
|
@@ -105,6 +128,7 @@ class _WireState:
|
|
|
105
128
|
reasoning_open: bool = False
|
|
106
129
|
terminal: bool = False
|
|
107
130
|
text_content: str = ""
|
|
131
|
+
reasoning_content: str = ""
|
|
108
132
|
|
|
109
133
|
|
|
110
134
|
class KsadkAGUIAgent:
|
|
@@ -143,6 +167,12 @@ class KsadkAGUIAgent:
|
|
|
143
167
|
return type(self)(name=self.name, _shared=self._shared)
|
|
144
168
|
|
|
145
169
|
async def run(self, input: RunAgentInput) -> AsyncIterator[BaseEvent]:
|
|
170
|
+
from ksadk.kernel import ingress as _kernel_ingress
|
|
171
|
+
|
|
172
|
+
if _kernel_ingress.kernel_route_active():
|
|
173
|
+
async for event in self._kernel_run(input):
|
|
174
|
+
yield event
|
|
175
|
+
return
|
|
146
176
|
wire = _WireState(
|
|
147
177
|
thread_id=input.thread_id,
|
|
148
178
|
run_id=input.run_id,
|
|
@@ -170,7 +200,10 @@ class KsadkAGUIAgent:
|
|
|
170
200
|
|
|
171
201
|
run.active = True
|
|
172
202
|
async for runtime_event in self._shared.executor.stream(run.handle):
|
|
173
|
-
persisted = await self._persist(
|
|
203
|
+
persisted = await self._persist(
|
|
204
|
+
self._event_for_persistence(runtime_event, run),
|
|
205
|
+
session_id=input.thread_id,
|
|
206
|
+
)
|
|
174
207
|
async for event in self._project(persisted, wire, run):
|
|
175
208
|
yield event
|
|
176
209
|
if not wire.terminal:
|
|
@@ -202,6 +235,102 @@ class KsadkAGUIAgent:
|
|
|
202
235
|
if run is not None and not run.cancel_failed:
|
|
203
236
|
run.active = False
|
|
204
237
|
|
|
238
|
+
async def _kernel_run(self, input: RunAgentInput) -> AsyncIterator[BaseEvent]:
|
|
239
|
+
"""kernel 路径(灰度 opt-in):AG-UI run -> AgentControlCommand -> receipt。
|
|
240
|
+
|
|
241
|
+
mutation 只走 kernel.submit;AG-UI 事件 shape 保留,cursor 源自同一
|
|
242
|
+
Session seq(SessionEventSubscription.after_seq)。
|
|
243
|
+
"""
|
|
244
|
+
from ksadk.kernel import ingress as _kernel_ingress
|
|
245
|
+
|
|
246
|
+
yield RunStartedEvent(
|
|
247
|
+
thread_id=input.thread_id,
|
|
248
|
+
run_id=input.run_id,
|
|
249
|
+
parent_run_id=input.parent_run_id,
|
|
250
|
+
input=input,
|
|
251
|
+
)
|
|
252
|
+
message_id = f"{input.run_id}:assistant"
|
|
253
|
+
text = ""
|
|
254
|
+
try:
|
|
255
|
+
trusted = _kernel_ingress.trusted_context(
|
|
256
|
+
source_kind="agui",
|
|
257
|
+
source_ref=input.run_id,
|
|
258
|
+
session_id=input.thread_id,
|
|
259
|
+
operations=("enqueue",),
|
|
260
|
+
launch_context=self._shared.launch_context,
|
|
261
|
+
)
|
|
262
|
+
command = _kernel_ingress.map_agui_request(
|
|
263
|
+
session_id=input.thread_id,
|
|
264
|
+
idempotency_key=input.run_id,
|
|
265
|
+
content=[
|
|
266
|
+
{"role": "user", "content": _agui_user_text(input)}
|
|
267
|
+
],
|
|
268
|
+
run_id=input.run_id,
|
|
269
|
+
trusted=trusted,
|
|
270
|
+
)
|
|
271
|
+
receipt = await _kernel_ingress.submit_command(
|
|
272
|
+
command, permit=trusted.permit
|
|
273
|
+
)
|
|
274
|
+
if receipt.status not in ("accepted", "duplicate"):
|
|
275
|
+
yield RunErrorEvent(
|
|
276
|
+
message=f"agent kernel rejected command: {receipt.status}",
|
|
277
|
+
code=receipt.status.upper(),
|
|
278
|
+
)
|
|
279
|
+
return
|
|
280
|
+
text_open = False
|
|
281
|
+
async for _seq, payload in _kernel_ingress.subscribe_projected(
|
|
282
|
+
input.thread_id,
|
|
283
|
+
trusted=trusted,
|
|
284
|
+
after_seq=int(receipt.accepted_seq or 0),
|
|
285
|
+
projector=_agui_envelope_payload,
|
|
286
|
+
):
|
|
287
|
+
if payload is None:
|
|
288
|
+
continue
|
|
289
|
+
kind, value = payload
|
|
290
|
+
if kind == "delta":
|
|
291
|
+
if not text_open:
|
|
292
|
+
text_open = True
|
|
293
|
+
yield TextMessageStartEvent(message_id=message_id)
|
|
294
|
+
text += value
|
|
295
|
+
yield TextMessageContentEvent(message_id=message_id, delta=value)
|
|
296
|
+
elif kind == "completed":
|
|
297
|
+
final = value or text
|
|
298
|
+
if final and not text_open:
|
|
299
|
+
text_open = True
|
|
300
|
+
yield TextMessageStartEvent(message_id=message_id)
|
|
301
|
+
if final.startswith(text) and len(final) > len(text):
|
|
302
|
+
yield TextMessageContentEvent(
|
|
303
|
+
message_id=message_id, delta=final[len(text):]
|
|
304
|
+
)
|
|
305
|
+
text = final
|
|
306
|
+
if text_open:
|
|
307
|
+
yield TextMessageEndEvent(message_id=message_id)
|
|
308
|
+
yield RunFinishedEvent(
|
|
309
|
+
thread_id=input.thread_id,
|
|
310
|
+
run_id=input.run_id,
|
|
311
|
+
outcome=RunFinishedSuccessOutcome(),
|
|
312
|
+
result={"output_text": text},
|
|
313
|
+
)
|
|
314
|
+
return
|
|
315
|
+
if text_open:
|
|
316
|
+
yield TextMessageEndEvent(message_id=message_id)
|
|
317
|
+
yield RunFinishedEvent(
|
|
318
|
+
thread_id=input.thread_id,
|
|
319
|
+
run_id=input.run_id,
|
|
320
|
+
outcome=RunFinishedSuccessOutcome(),
|
|
321
|
+
result={"output_text": text},
|
|
322
|
+
)
|
|
323
|
+
except Exception:
|
|
324
|
+
logger.exception(
|
|
325
|
+
"AG-UI kernel ingress failed for thread=%s run=%s",
|
|
326
|
+
input.thread_id,
|
|
327
|
+
input.run_id,
|
|
328
|
+
)
|
|
329
|
+
yield RunErrorEvent(
|
|
330
|
+
message="Agent kernel ingress failed",
|
|
331
|
+
code="KERNEL_ERROR",
|
|
332
|
+
)
|
|
333
|
+
|
|
205
334
|
async def _resolve_run(self, input: RunAgentInput) -> tuple[_ThreadRun, bool]:
|
|
206
335
|
async with self._shared.lock:
|
|
207
336
|
if input.resume:
|
|
@@ -331,155 +460,183 @@ class KsadkAGUIAgent:
|
|
|
331
460
|
default=str,
|
|
332
461
|
)
|
|
333
462
|
decision = self._approval_decision_for_audit(entry.status, entry.payload)
|
|
334
|
-
event =
|
|
335
|
-
|
|
463
|
+
event = InteractionResolved(
|
|
464
|
+
schema_version=2,
|
|
336
465
|
event_id=f"evt_agui_resume_{hashlib.sha256(event_key.encode()).hexdigest()}",
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
466
|
+
seq=0,
|
|
467
|
+
timestamp=time.time(),
|
|
468
|
+
run_id=run.handle.run_id,
|
|
469
|
+
scope_id=f"ksadk:{run.handle.run_id}",
|
|
470
|
+
source=SourceRef(
|
|
471
|
+
framework="ksadk",
|
|
472
|
+
metadata={
|
|
473
|
+
"agent_id": str(run.handle.native_ref.get("agent_id") or self.name),
|
|
474
|
+
"user_id": str(run.handle.native_ref.get("user_id") or "agui-user"),
|
|
475
|
+
"session_id": input.thread_id,
|
|
476
|
+
"protocol": "ag-ui",
|
|
477
|
+
"resume_fingerprint": fingerprint,
|
|
478
|
+
},
|
|
479
|
+
),
|
|
480
|
+
interaction_id=entry.interrupt_id,
|
|
481
|
+
interaction_kind="approval",
|
|
482
|
+
response=ApprovalResponse(
|
|
483
|
+
response_type="approval",
|
|
484
|
+
decision=(
|
|
485
|
+
decision if decision in ("approved", "rejected", "canceled") else "rejected"
|
|
486
|
+
),
|
|
487
|
+
data={"call_id": entry.interrupt_id},
|
|
488
|
+
),
|
|
349
489
|
)
|
|
350
490
|
if index == 0:
|
|
351
|
-
_persisted, reservation_created = await self._reserve(
|
|
491
|
+
_persisted, reservation_created = await self._reserve(
|
|
492
|
+
event, session_id=input.thread_id
|
|
493
|
+
)
|
|
352
494
|
if not reservation_created:
|
|
353
495
|
return False
|
|
354
496
|
else:
|
|
355
|
-
await self._persist(event)
|
|
497
|
+
await self._persist(event, session_id=input.thread_id)
|
|
356
498
|
return reservation_created
|
|
357
499
|
|
|
358
|
-
@staticmethod
|
|
359
|
-
def _approval_decision_for_audit(status: str, payload: Any) -> str:
|
|
360
|
-
"""Persist a stable decision value while accepting official AG-UI envelopes."""
|
|
361
|
-
|
|
362
|
-
if status != "resolved":
|
|
363
|
-
return "rejected"
|
|
364
|
-
if payload is True:
|
|
365
|
-
return "approved"
|
|
366
|
-
if isinstance(payload, Mapping):
|
|
367
|
-
for key in ("approve", "approved"):
|
|
368
|
-
if key in payload:
|
|
369
|
-
return "approved" if bool(payload[key]) else "rejected"
|
|
370
|
-
for key in ("decision", "type"):
|
|
371
|
-
if key in payload:
|
|
372
|
-
return KsadkAGUIAgent._approval_decision_for_audit(status, payload[key])
|
|
373
|
-
return "rejected"
|
|
374
|
-
if isinstance(payload, str) and payload.strip().lower() in {"approve", "approved"}:
|
|
375
|
-
return "approved"
|
|
376
|
-
return "rejected"
|
|
377
|
-
|
|
378
500
|
async def _project(
|
|
379
501
|
self,
|
|
380
502
|
event: RuntimeEvent,
|
|
381
503
|
wire: _WireState,
|
|
382
504
|
run: _ThreadRun,
|
|
383
505
|
) -> AsyncIterator[BaseEvent]:
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if event_type in (EventType.TEXT_DELTA, EventType.TEXT_COMPLETED):
|
|
506
|
+
# ---- message (text) ----
|
|
507
|
+
if isinstance(event, (ItemUpdated, ItemSnapshotReplaced)) and event.item_kind == "message":
|
|
388
508
|
if not wire.text_open:
|
|
389
509
|
wire.text_open = True
|
|
390
510
|
yield TextMessageStartEvent(message_id=wire.message_id)
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
511
|
+
if isinstance(event, ItemSnapshotReplaced):
|
|
512
|
+
# atomic snapshot replace: close and reopen with full text
|
|
513
|
+
wire.text_open = False
|
|
514
|
+
wire.text_content = ""
|
|
515
|
+
yield TextMessageEndEvent(message_id=wire.message_id)
|
|
516
|
+
wire.text_open = True
|
|
517
|
+
yield TextMessageStartEvent(message_id=wire.message_id)
|
|
518
|
+
text = self._extract_text(event.snapshot)
|
|
519
|
+
elif event.op == "replace":
|
|
520
|
+
wire.text_open = False
|
|
521
|
+
wire.text_content = ""
|
|
522
|
+
yield TextMessageEndEvent(message_id=wire.message_id)
|
|
523
|
+
wire.text_open = True
|
|
524
|
+
yield TextMessageStartEvent(message_id=wire.message_id)
|
|
525
|
+
text = event.update.text if isinstance(event.update, TextContent) else ""
|
|
526
|
+
else:
|
|
527
|
+
text = event.update.text if isinstance(event.update, TextContent) else ""
|
|
394
528
|
if text:
|
|
395
529
|
yield TextMessageContentEvent(message_id=wire.message_id, delta=text)
|
|
396
530
|
wire.text_content += text
|
|
397
|
-
if event_type == EventType.TEXT_COMPLETED:
|
|
398
|
-
wire.text_open = False
|
|
399
|
-
yield TextMessageEndEvent(message_id=wire.message_id)
|
|
400
531
|
return
|
|
401
532
|
|
|
402
|
-
if
|
|
533
|
+
if isinstance(event, ItemCompleted) and event.item_kind == "message":
|
|
534
|
+
if not wire.text_open:
|
|
535
|
+
wire.text_open = True
|
|
536
|
+
yield TextMessageStartEvent(message_id=wire.message_id)
|
|
537
|
+
# ItemCompleted is the authoritative snapshot; do NOT re-append
|
|
538
|
+
# the full text when deltas already covered the content.
|
|
539
|
+
if not wire.text_content:
|
|
540
|
+
text = self._extract_text(event.snapshot)
|
|
541
|
+
if text:
|
|
542
|
+
yield TextMessageContentEvent(message_id=wire.message_id, delta=text)
|
|
543
|
+
wire.text_content += text
|
|
544
|
+
wire.text_open = False
|
|
545
|
+
yield TextMessageEndEvent(message_id=wire.message_id)
|
|
546
|
+
return
|
|
547
|
+
|
|
548
|
+
if isinstance(event, ItemStarted) and event.item_kind == "message":
|
|
549
|
+
# ItemStarted for messages is a tracking signal; the text message
|
|
550
|
+
# opens lazily on the first content delta or completed snapshot.
|
|
551
|
+
return
|
|
552
|
+
|
|
553
|
+
# ---- reasoning ----
|
|
554
|
+
if (
|
|
555
|
+
isinstance(event, (ItemUpdated, ItemSnapshotReplaced))
|
|
556
|
+
and event.item_kind == "reasoning"
|
|
557
|
+
):
|
|
403
558
|
if not wire.reasoning_open:
|
|
404
559
|
wire.reasoning_open = True
|
|
405
560
|
yield ReasoningStartEvent(message_id=wire.reasoning_id)
|
|
406
561
|
yield ReasoningMessageStartEvent(message_id=wire.reasoning_id, role="reasoning")
|
|
407
|
-
|
|
562
|
+
if isinstance(event, ItemSnapshotReplaced):
|
|
563
|
+
wire.reasoning_content = ""
|
|
564
|
+
text = self._extract_text(event.snapshot)
|
|
565
|
+
else:
|
|
566
|
+
text = event.update.text if isinstance(event.update, TextContent) else ""
|
|
408
567
|
if text:
|
|
409
568
|
yield ReasoningMessageContentEvent(message_id=wire.reasoning_id, delta=text)
|
|
410
|
-
|
|
411
|
-
wire.reasoning_open = False
|
|
412
|
-
yield ReasoningMessageEndEvent(message_id=wire.reasoning_id)
|
|
413
|
-
yield ReasoningEndEvent(message_id=wire.reasoning_id)
|
|
569
|
+
wire.reasoning_content += text
|
|
414
570
|
return
|
|
415
571
|
|
|
416
|
-
if
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
572
|
+
if isinstance(event, ItemCompleted) and event.item_kind == "reasoning":
|
|
573
|
+
if not wire.reasoning_open:
|
|
574
|
+
wire.reasoning_open = True
|
|
575
|
+
yield ReasoningStartEvent(message_id=wire.reasoning_id)
|
|
576
|
+
yield ReasoningMessageStartEvent(message_id=wire.reasoning_id, role="reasoning")
|
|
577
|
+
if not wire.reasoning_content:
|
|
578
|
+
text = self._extract_text(event.snapshot)
|
|
579
|
+
if text:
|
|
580
|
+
yield ReasoningMessageContentEvent(message_id=wire.reasoning_id, delta=text)
|
|
581
|
+
wire.reasoning_content += text
|
|
582
|
+
wire.reasoning_open = False
|
|
583
|
+
yield ReasoningMessageEndEvent(message_id=wire.reasoning_id)
|
|
584
|
+
yield ReasoningEndEvent(message_id=wire.reasoning_id)
|
|
585
|
+
return
|
|
586
|
+
|
|
587
|
+
if isinstance(event, ItemStarted) and event.item_kind == "reasoning":
|
|
588
|
+
return
|
|
589
|
+
|
|
590
|
+
# ---- tool call ----
|
|
591
|
+
if isinstance(event, ItemStarted) and event.item_kind == "tool_call":
|
|
592
|
+
part = self._first_part(event.initial)
|
|
593
|
+
if isinstance(part, ToolCallContent):
|
|
594
|
+
call_id = part.call_id
|
|
595
|
+
yield ToolCallStartEvent(
|
|
596
|
+
tool_call_id=call_id,
|
|
597
|
+
tool_call_name=part.name,
|
|
598
|
+
parent_message_id=wire.message_id,
|
|
599
|
+
)
|
|
424
600
|
yield ToolCallArgsEvent(
|
|
425
601
|
tool_call_id=call_id,
|
|
426
|
-
delta=json.dumps(
|
|
602
|
+
delta=json.dumps(part.arguments, ensure_ascii=False, default=str),
|
|
427
603
|
)
|
|
428
604
|
return
|
|
429
605
|
|
|
430
|
-
if
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
payload.get("result") if payload.get("error") is None else payload.get("error")
|
|
434
|
-
)
|
|
435
|
-
# AG-UI closes the active call at TOOL_CALL_END. Sending a result
|
|
436
|
-
# first makes official clients discard the call, then reject this
|
|
437
|
-
# end event as orphaned.
|
|
606
|
+
if isinstance(event, ItemCompleted) and event.item_kind == "tool_call":
|
|
607
|
+
part = self._first_part(event.snapshot)
|
|
608
|
+
call_id = part.call_id if isinstance(part, ToolCallContent) else "tool"
|
|
438
609
|
yield ToolCallEndEvent(tool_call_id=call_id)
|
|
439
|
-
yield ToolCallResultEvent(
|
|
440
|
-
message_id=f"{wire.run_id}:tool:{call_id}",
|
|
441
|
-
tool_call_id=call_id,
|
|
442
|
-
content=json.dumps(content, ensure_ascii=False, default=str),
|
|
443
|
-
role="tool",
|
|
444
|
-
)
|
|
445
610
|
return
|
|
446
611
|
|
|
447
|
-
if
|
|
448
|
-
|
|
612
|
+
if isinstance(event, ItemCompleted) and event.item_kind == "tool_result":
|
|
613
|
+
part = self._first_part(event.snapshot)
|
|
614
|
+
if isinstance(part, ToolResultContent):
|
|
615
|
+
call_id = part.call_id
|
|
616
|
+
content = part.result
|
|
617
|
+
yield ToolCallResultEvent(
|
|
618
|
+
message_id=f"{wire.run_id}:tool:{call_id}",
|
|
619
|
+
tool_call_id=call_id,
|
|
620
|
+
content=json.dumps(content, ensure_ascii=False, default=str),
|
|
621
|
+
role="tool",
|
|
622
|
+
)
|
|
449
623
|
return
|
|
450
624
|
|
|
451
|
-
if
|
|
452
|
-
interrupt_id = str(payload.get("approval_id") or payload.get("call_id") or "")
|
|
453
|
-
checkpoint_id = str(run.handle.native_ref.get("checkpoint_id") or "")
|
|
454
|
-
if not checkpoint_id:
|
|
455
|
-
known = run.handle.native_ref.get("known_checkpoint_ids") or []
|
|
456
|
-
checkpoint_id = str(known[-1]) if known else ""
|
|
457
|
-
raw_detail = payload.get("detail")
|
|
458
|
-
detail: dict[str, Any] = raw_detail if isinstance(raw_detail, dict) else {}
|
|
459
|
-
interrupt = Interrupt(
|
|
460
|
-
id=interrupt_id,
|
|
461
|
-
reason=str(detail.get("reason") or payload.get("kind") or "approval"),
|
|
462
|
-
message=self._approval_message(detail, payload),
|
|
463
|
-
tool_call_id=str(payload.get("call_id") or "") or None,
|
|
464
|
-
response_schema=detail.get("response_schema"),
|
|
465
|
-
metadata=self._approval_metadata(detail, payload),
|
|
466
|
-
)
|
|
467
|
-
run.pending[interrupt_id] = _PendingInterrupt(interrupt, checkpoint_id)
|
|
625
|
+
if isinstance(event, ItemStarted) and event.item_kind == "tool_result":
|
|
468
626
|
return
|
|
469
627
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
628
|
+
# ---- A2UI surface (item_kind="data" + source.protocol="a2ui") ----
|
|
629
|
+
if (
|
|
630
|
+
isinstance(event, (ItemStarted, ItemUpdated, ItemCompleted))
|
|
631
|
+
and event.item_kind == "data"
|
|
632
|
+
and event.source.protocol == "a2ui"
|
|
633
|
+
):
|
|
634
|
+
surface_id = str(event.source.metadata.get("surface_id") or "")
|
|
635
|
+
operations = self._a2ui_operations(event, surface_id)
|
|
476
636
|
if operations:
|
|
477
|
-
surface_id = str(payload.get("surface_id") or payload.get("surfaceId") or "")
|
|
478
637
|
yield ActivitySnapshotEvent(
|
|
479
638
|
message_id=f"{wire.run_id}:a2ui:{surface_id}",
|
|
480
639
|
activity_type="a2ui-surface",
|
|
481
|
-
# The client renderer addresses a surface by this value.
|
|
482
|
-
# ``message_id`` is a transport id, not the A2UI surface id.
|
|
483
640
|
content={
|
|
484
641
|
"surfaceId": surface_id,
|
|
485
642
|
"a2ui_operations": operations,
|
|
@@ -488,18 +645,62 @@ class KsadkAGUIAgent:
|
|
|
488
645
|
)
|
|
489
646
|
return
|
|
490
647
|
|
|
491
|
-
|
|
648
|
+
# ---- checkpoint ----
|
|
649
|
+
if isinstance(event, ContinuationCreated):
|
|
650
|
+
# Track checkpoint id in handle native_ref for downstream approval
|
|
651
|
+
# resolution (pending interrupts need a resumable checkpoint_id).
|
|
652
|
+
ckpt_id = str(event.ref.get("checkpoint_id") or "")
|
|
653
|
+
if ckpt_id:
|
|
654
|
+
run.handle.native_ref["checkpoint_id"] = ckpt_id
|
|
655
|
+
known = run.handle.native_ref.setdefault("known_checkpoint_ids", [])
|
|
656
|
+
if ckpt_id not in known:
|
|
657
|
+
known.append(ckpt_id)
|
|
658
|
+
yield StateSnapshotEvent(snapshot={"checkpoint": copy.deepcopy(event.ref)})
|
|
659
|
+
return
|
|
660
|
+
|
|
661
|
+
# ---- approval ----
|
|
662
|
+
if isinstance(event, InteractionRequested):
|
|
663
|
+
interrupt = self._interrupt_from_interaction(event)
|
|
664
|
+
checkpoint_id = str(run.handle.native_ref.get("checkpoint_id") or "")
|
|
665
|
+
if not checkpoint_id:
|
|
666
|
+
known = run.handle.native_ref.get("known_checkpoint_ids") or []
|
|
667
|
+
checkpoint_id = str(known[-1]) if known else ""
|
|
668
|
+
run.pending[interrupt.id] = _PendingInterrupt(interrupt, checkpoint_id)
|
|
669
|
+
return
|
|
670
|
+
|
|
671
|
+
# ---- run lifecycle ----
|
|
672
|
+
if isinstance(event, RunInterrupted):
|
|
492
673
|
async for close_event in self._close_open_messages(wire):
|
|
493
674
|
yield close_event
|
|
494
675
|
if not run.pending:
|
|
495
676
|
raise ValueError("runtime interrupted without a pending approval")
|
|
496
|
-
checkpoint_id
|
|
677
|
+
# If checkpoint_id wasn't set by ContinuationCreated (e.g. langgraph
|
|
678
|
+
# canonical stream without checkpoint_ref on first run), try to
|
|
679
|
+
# extract it from the RunInterrupted event's continuation_id or
|
|
680
|
+
# the executor's checkpoint descriptor.
|
|
681
|
+
if event.continuation_id:
|
|
682
|
+
checkpoint_id = str(event.continuation_id)
|
|
683
|
+
else:
|
|
684
|
+
checkpoint_id = str(run.handle.native_ref.get("checkpoint_id") or "")
|
|
497
685
|
if not checkpoint_id:
|
|
498
686
|
known = run.handle.native_ref.get("known_checkpoint_ids") or []
|
|
499
687
|
checkpoint_id = str(known[-1]) if known else ""
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
688
|
+
if not checkpoint_id:
|
|
689
|
+
# Last resort: query the executor for the native checkpoint.
|
|
690
|
+
try:
|
|
691
|
+
descriptor = await self._shared.executor.checkpoint(run.handle)
|
|
692
|
+
checkpoint_id = str(descriptor.checkpoint_id or "")
|
|
693
|
+
if checkpoint_id:
|
|
694
|
+
run.handle.native_ref["checkpoint_id"] = checkpoint_id
|
|
695
|
+
known = run.handle.native_ref.setdefault("known_checkpoint_ids", [])
|
|
696
|
+
if checkpoint_id not in known:
|
|
697
|
+
known.append(checkpoint_id)
|
|
698
|
+
except Exception:
|
|
699
|
+
pass
|
|
700
|
+
if checkpoint_id:
|
|
701
|
+
for pending in run.pending.values():
|
|
702
|
+
if not pending.checkpoint_id:
|
|
703
|
+
pending.checkpoint_id = checkpoint_id
|
|
503
704
|
run.interrupted = True
|
|
504
705
|
wire.terminal = True
|
|
505
706
|
yield RunFinishedEvent(
|
|
@@ -511,23 +712,30 @@ class KsadkAGUIAgent:
|
|
|
511
712
|
)
|
|
512
713
|
return
|
|
513
714
|
|
|
514
|
-
if
|
|
715
|
+
if isinstance(event, RunCompleted):
|
|
515
716
|
async for finish_event in self._finish_success(wire):
|
|
516
717
|
yield finish_event
|
|
517
718
|
return
|
|
518
719
|
|
|
519
|
-
if
|
|
720
|
+
if isinstance(event, RunCanceled):
|
|
520
721
|
async for close_event in self._close_open_messages(wire):
|
|
521
722
|
yield close_event
|
|
522
723
|
wire.terminal = True
|
|
523
724
|
yield RunErrorEvent(
|
|
524
|
-
message=
|
|
525
|
-
|
|
526
|
-
if event_type == EventType.RUN_CANCELED
|
|
527
|
-
else "Runtime execution failed"
|
|
528
|
-
),
|
|
529
|
-
code=("CANCELLED" if event_type == EventType.RUN_CANCELED else "RUNTIME_ERROR"),
|
|
725
|
+
message=event.reason or "Runtime run was cancelled",
|
|
726
|
+
code="CANCELLED",
|
|
530
727
|
)
|
|
728
|
+
return
|
|
729
|
+
|
|
730
|
+
if isinstance(event, RunFailed):
|
|
731
|
+
async for close_event in self._close_open_messages(wire):
|
|
732
|
+
yield close_event
|
|
733
|
+
wire.terminal = True
|
|
734
|
+
yield RunErrorEvent(
|
|
735
|
+
message=event.error.message or "Runtime execution failed",
|
|
736
|
+
code="RUNTIME_ERROR",
|
|
737
|
+
)
|
|
738
|
+
return
|
|
531
739
|
|
|
532
740
|
async def _finish_success(self, wire: _WireState) -> AsyncIterator[BaseEvent]:
|
|
533
741
|
async for event in self._close_open_messages(wire):
|
|
@@ -550,14 +758,17 @@ class KsadkAGUIAgent:
|
|
|
550
758
|
wire.text_open = False
|
|
551
759
|
yield TextMessageEndEvent(message_id=wire.message_id)
|
|
552
760
|
|
|
553
|
-
async def _persist(self, event: RuntimeEvent) -> RuntimeEvent:
|
|
761
|
+
async def _persist(self, event: RuntimeEvent, *, session_id: str = "") -> RuntimeEvent:
|
|
554
762
|
factory = self._shared.event_store_factory
|
|
555
763
|
if factory is None:
|
|
556
764
|
return event
|
|
557
765
|
store = factory()
|
|
558
|
-
|
|
766
|
+
sid = str(event.source.metadata.get("session_id") or session_id or "")
|
|
767
|
+
return cast(RuntimeEvent, await store.append_one(sid, event))
|
|
559
768
|
|
|
560
|
-
async def _reserve(
|
|
769
|
+
async def _reserve(
|
|
770
|
+
self, event: RuntimeEvent, *, session_id: str = ""
|
|
771
|
+
) -> tuple[RuntimeEvent, bool]:
|
|
561
772
|
factory = self._shared.event_store_factory
|
|
562
773
|
if factory is None:
|
|
563
774
|
return event, True
|
|
@@ -566,7 +777,8 @@ class KsadkAGUIAgent:
|
|
|
566
777
|
if callable(reserve):
|
|
567
778
|
persisted, created = await reserve(event)
|
|
568
779
|
return cast(RuntimeEvent, persisted), bool(created)
|
|
569
|
-
|
|
780
|
+
sid = str(event.source.metadata.get("session_id") or session_id or "")
|
|
781
|
+
return cast(RuntimeEvent, await store.append_one(sid, event)), True
|
|
570
782
|
|
|
571
783
|
async def _persist_user_input(
|
|
572
784
|
self,
|
|
@@ -576,21 +788,27 @@ class KsadkAGUIAgent:
|
|
|
576
788
|
) -> None:
|
|
577
789
|
event_key = json.dumps([input.thread_id, input.run_id, "user"], ensure_ascii=False)
|
|
578
790
|
await self._persist(
|
|
579
|
-
|
|
580
|
-
|
|
791
|
+
RunStarted(
|
|
792
|
+
schema_version=2,
|
|
581
793
|
event_id=f"evt_agui_input_{hashlib.sha256(event_key.encode()).hexdigest()}",
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
794
|
+
seq=0,
|
|
795
|
+
timestamp=time.time(),
|
|
796
|
+
run_id=input.run_id,
|
|
797
|
+
scope_id=f"ksadk:{input.run_id}",
|
|
798
|
+
source=SourceRef(
|
|
799
|
+
framework="ksadk",
|
|
800
|
+
metadata={
|
|
801
|
+
"agent_id": self.name,
|
|
802
|
+
"user_id": request.user_id,
|
|
803
|
+
"session_id": input.thread_id,
|
|
804
|
+
"input": self._json_safe(request.input),
|
|
805
|
+
"source": "ag-ui",
|
|
806
|
+
"runtime_type": handle.runtime_type,
|
|
807
|
+
},
|
|
808
|
+
),
|
|
809
|
+
status="running",
|
|
810
|
+
),
|
|
811
|
+
session_id=input.thread_id,
|
|
594
812
|
)
|
|
595
813
|
await self._prime_session_metadata_for_user_turn(
|
|
596
814
|
session_id=input.thread_id,
|
|
@@ -638,21 +856,22 @@ class KsadkAGUIAgent:
|
|
|
638
856
|
logger.debug("failed to update AG-UI session metadata", exc_info=True)
|
|
639
857
|
|
|
640
858
|
def _event_for_persistence(self, event: RuntimeEvent, run: _ThreadRun) -> RuntimeEvent:
|
|
641
|
-
if event
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
return event.model_copy(update={"
|
|
646
|
-
if event
|
|
859
|
+
if isinstance(event, (InteractionRequested, InteractionResolved)):
|
|
860
|
+
new_source = event.source.model_copy(
|
|
861
|
+
update={"metadata": {**event.source.metadata, "protocol": "ag-ui"}}
|
|
862
|
+
)
|
|
863
|
+
return event.model_copy(update={"source": new_source})
|
|
864
|
+
if not isinstance(event, RunInterrupted):
|
|
647
865
|
return event
|
|
648
|
-
|
|
866
|
+
new_source = event.source.model_copy(
|
|
649
867
|
update={
|
|
650
|
-
"
|
|
651
|
-
**event.
|
|
868
|
+
"metadata": {
|
|
869
|
+
**event.source.metadata,
|
|
652
870
|
"runtime_handle": self._durable_handle(run.handle),
|
|
653
871
|
}
|
|
654
872
|
}
|
|
655
873
|
)
|
|
874
|
+
return event.model_copy(update={"source": new_source})
|
|
656
875
|
|
|
657
876
|
async def _restore_durable_run(
|
|
658
877
|
self,
|
|
@@ -663,13 +882,15 @@ class KsadkAGUIAgent:
|
|
|
663
882
|
if not events:
|
|
664
883
|
return None, False
|
|
665
884
|
resolved = {
|
|
666
|
-
str(event.
|
|
885
|
+
str(event.interaction_id): event
|
|
667
886
|
for event in events
|
|
668
|
-
if event
|
|
887
|
+
if isinstance(event, InteractionResolved)
|
|
669
888
|
}
|
|
670
889
|
if fingerprints and all(interrupt_id in resolved for interrupt_id in fingerprints):
|
|
671
890
|
for interrupt_id, fingerprint in fingerprints.items():
|
|
672
|
-
persisted = str(
|
|
891
|
+
persisted = str(
|
|
892
|
+
resolved[interrupt_id].source.metadata.get("resume_fingerprint") or ""
|
|
893
|
+
)
|
|
673
894
|
if persisted and persisted != fingerprint:
|
|
674
895
|
raise ValueError(f"interrupt {interrupt_id!r} was resolved differently")
|
|
675
896
|
return None, True
|
|
@@ -677,22 +898,21 @@ class KsadkAGUIAgent:
|
|
|
677
898
|
raise ValueError("resume set is only partially resolved")
|
|
678
899
|
|
|
679
900
|
interrupted = next(
|
|
680
|
-
(event for event in reversed(events) if event
|
|
901
|
+
(event for event in reversed(events) if isinstance(event, RunInterrupted)),
|
|
681
902
|
None,
|
|
682
903
|
)
|
|
683
904
|
if interrupted is None:
|
|
684
905
|
return None, False
|
|
685
|
-
raw_handle = interrupted.
|
|
906
|
+
raw_handle = interrupted.source.metadata.get("runtime_handle")
|
|
686
907
|
if not isinstance(raw_handle, dict):
|
|
687
908
|
return None, False
|
|
688
909
|
handle = RunHandle.model_validate(raw_handle)
|
|
689
910
|
requests = [
|
|
690
911
|
event
|
|
691
912
|
for event in events
|
|
692
|
-
if event
|
|
693
|
-
and event.
|
|
694
|
-
and str(event.
|
|
695
|
-
not in resolved
|
|
913
|
+
if isinstance(event, InteractionRequested)
|
|
914
|
+
and event.run_id == interrupted.run_id
|
|
915
|
+
and str(event.interaction_id) not in resolved
|
|
696
916
|
]
|
|
697
917
|
pending: dict[str, _PendingInterrupt] = {}
|
|
698
918
|
checkpoint_id = str(handle.native_ref.get("checkpoint_id") or "")
|
|
@@ -700,7 +920,7 @@ class KsadkAGUIAgent:
|
|
|
700
920
|
known = handle.native_ref.get("known_checkpoint_ids") or []
|
|
701
921
|
checkpoint_id = str(known[-1]) if known else ""
|
|
702
922
|
for request in requests:
|
|
703
|
-
interrupt = self.
|
|
923
|
+
interrupt = self._interrupt_from_interaction(request)
|
|
704
924
|
pending[interrupt.id] = _PendingInterrupt(interrupt, checkpoint_id)
|
|
705
925
|
if not pending:
|
|
706
926
|
return None, False
|
|
@@ -721,55 +941,6 @@ class KsadkAGUIAgent:
|
|
|
721
941
|
return []
|
|
722
942
|
return list(await list_events(session_id))
|
|
723
943
|
|
|
724
|
-
@staticmethod
|
|
725
|
-
def _durable_handle(handle: RunHandle) -> dict[str, Any]:
|
|
726
|
-
allowed = {
|
|
727
|
-
"agent_id",
|
|
728
|
-
"user_id",
|
|
729
|
-
"checkpoint_id",
|
|
730
|
-
"known_checkpoint_ids",
|
|
731
|
-
"pending_approval_ids",
|
|
732
|
-
"framework_ref",
|
|
733
|
-
"thread_id",
|
|
734
|
-
"checkpoint_ns",
|
|
735
|
-
"resume_thread_id",
|
|
736
|
-
}
|
|
737
|
-
native_ref = {key: value for key, value in handle.native_ref.items() if key in allowed}
|
|
738
|
-
return {
|
|
739
|
-
"run_id": handle.run_id,
|
|
740
|
-
"session_id": handle.session_id,
|
|
741
|
-
"runtime_type": handle.runtime_type,
|
|
742
|
-
"native_ref": KsadkAGUIAgent._json_safe(native_ref),
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
@staticmethod
|
|
746
|
-
def _interrupt_from_payload(payload: Mapping[str, Any]) -> Interrupt:
|
|
747
|
-
interrupt_id = str(payload.get("approval_id") or payload.get("call_id") or "")
|
|
748
|
-
raw_detail = payload.get("detail")
|
|
749
|
-
detail = raw_detail if isinstance(raw_detail, dict) else {}
|
|
750
|
-
return Interrupt(
|
|
751
|
-
id=interrupt_id,
|
|
752
|
-
reason=str(detail.get("reason") or payload.get("kind") or "approval"),
|
|
753
|
-
message=KsadkAGUIAgent._approval_message(detail, payload),
|
|
754
|
-
tool_call_id=str(payload.get("call_id") or "") or None,
|
|
755
|
-
response_schema=detail.get("response_schema"),
|
|
756
|
-
metadata=KsadkAGUIAgent._approval_metadata(detail, payload),
|
|
757
|
-
)
|
|
758
|
-
|
|
759
|
-
@staticmethod
|
|
760
|
-
def _duplicate_run(input: RunAgentInput) -> _ThreadRun:
|
|
761
|
-
return _ThreadRun(
|
|
762
|
-
handle=RunHandle(
|
|
763
|
-
run_id=input.run_id,
|
|
764
|
-
session_id=input.thread_id,
|
|
765
|
-
runtime_type="ag-ui-duplicate",
|
|
766
|
-
)
|
|
767
|
-
)
|
|
768
|
-
|
|
769
|
-
@staticmethod
|
|
770
|
-
def _json_safe(value: Any) -> Any:
|
|
771
|
-
return json.loads(json.dumps(value, ensure_ascii=False, default=str))
|
|
772
|
-
|
|
773
944
|
async def _close_thread(self, thread_id: str, run: _ThreadRun) -> None:
|
|
774
945
|
try:
|
|
775
946
|
await self._shared.executor.close(run.handle)
|
|
@@ -793,80 +964,93 @@ class KsadkAGUIAgent:
|
|
|
793
964
|
run.active = True
|
|
794
965
|
return result
|
|
795
966
|
|
|
967
|
+
@staticmethod
|
|
968
|
+
def _approval_decision_for_audit(status: str, payload: Any) -> str:
|
|
969
|
+
return _agent_helpers.approval_decision_for_audit(status, payload)
|
|
970
|
+
|
|
971
|
+
@staticmethod
|
|
972
|
+
def _durable_handle(handle: RunHandle) -> dict[str, Any]:
|
|
973
|
+
return _agent_helpers.durable_handle(handle)
|
|
974
|
+
|
|
975
|
+
@staticmethod
|
|
976
|
+
def _interrupt_from_payload(payload: Mapping[str, Any]) -> Interrupt:
|
|
977
|
+
return _agent_helpers.interrupt_from_payload(payload)
|
|
978
|
+
|
|
979
|
+
@staticmethod
|
|
980
|
+
def _interrupt_from_interaction(event: InteractionRequested) -> Interrupt:
|
|
981
|
+
return _agent_helpers.interrupt_from_interaction(event)
|
|
982
|
+
|
|
983
|
+
@staticmethod
|
|
984
|
+
def _extract_text(snapshot: ContentSnapshot | None) -> str:
|
|
985
|
+
return _agent_helpers.extract_text(snapshot)
|
|
986
|
+
|
|
987
|
+
@staticmethod
|
|
988
|
+
def _first_part(snapshot: ContentSnapshot | None) -> Any:
|
|
989
|
+
return _agent_helpers.first_part(snapshot)
|
|
990
|
+
|
|
991
|
+
@staticmethod
|
|
992
|
+
def _a2ui_operations(
|
|
993
|
+
event: ItemStarted | ItemUpdated | ItemCompleted,
|
|
994
|
+
surface_id: str,
|
|
995
|
+
) -> list[dict[str, Any]]:
|
|
996
|
+
return _agent_helpers.a2ui_operations(event, surface_id)
|
|
997
|
+
|
|
998
|
+
@staticmethod
|
|
999
|
+
def _duplicate_run(input: RunAgentInput) -> _ThreadRun:
|
|
1000
|
+
return _agent_helpers.duplicate_run(input)
|
|
1001
|
+
|
|
1002
|
+
@staticmethod
|
|
1003
|
+
def _json_safe(value: Any) -> Any:
|
|
1004
|
+
return _agent_helpers.json_safe(value)
|
|
1005
|
+
|
|
796
1006
|
@staticmethod
|
|
797
1007
|
def _latest_user_input(input: RunAgentInput) -> Any:
|
|
798
|
-
|
|
799
|
-
if getattr(message, "role", None) == "user":
|
|
800
|
-
return getattr(message, "content", "")
|
|
801
|
-
return ""
|
|
1008
|
+
return _agent_helpers.latest_user_input(input)
|
|
802
1009
|
|
|
803
1010
|
@staticmethod
|
|
804
1011
|
def _input_text(value: Any) -> str:
|
|
805
|
-
|
|
806
|
-
return value.strip()
|
|
807
|
-
if isinstance(value, Mapping):
|
|
808
|
-
return str(value.get("text") or value.get("content") or "").strip()
|
|
809
|
-
return str(value or "").strip()
|
|
1012
|
+
return _agent_helpers.input_text(value)
|
|
810
1013
|
|
|
811
1014
|
@staticmethod
|
|
812
1015
|
def _approval_action(detail: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
813
|
-
|
|
814
|
-
actions = (
|
|
815
|
-
nested_request.get("action_requests")
|
|
816
|
-
if isinstance(nested_request, Mapping)
|
|
817
|
-
else detail.get("action_requests")
|
|
818
|
-
)
|
|
819
|
-
if isinstance(actions, list):
|
|
820
|
-
for action in actions:
|
|
821
|
-
if isinstance(action, Mapping):
|
|
822
|
-
return action
|
|
823
|
-
return {}
|
|
1016
|
+
return _agent_helpers.approval_action(detail)
|
|
824
1017
|
|
|
825
1018
|
@staticmethod
|
|
826
1019
|
def _approval_metadata(
|
|
827
1020
|
detail: Mapping[str, Any],
|
|
828
1021
|
payload: Mapping[str, Any],
|
|
829
1022
|
) -> dict[str, Any]:
|
|
830
|
-
|
|
831
|
-
arguments = (
|
|
832
|
-
action.get("args")
|
|
833
|
-
or action.get("arguments")
|
|
834
|
-
or detail.get("arguments")
|
|
835
|
-
or detail.get("args")
|
|
836
|
-
or payload.get("args")
|
|
837
|
-
)
|
|
838
|
-
metadata: dict[str, Any] = {
|
|
839
|
-
"tool_name": str(
|
|
840
|
-
action.get("name")
|
|
841
|
-
or detail.get("tool_name")
|
|
842
|
-
or payload.get("name")
|
|
843
|
-
or payload.get("kind")
|
|
844
|
-
or "approval"
|
|
845
|
-
),
|
|
846
|
-
"arguments": arguments if arguments is not None else {},
|
|
847
|
-
}
|
|
848
|
-
approval_level = (
|
|
849
|
-
action.get("approval_level")
|
|
850
|
-
or detail.get("approval_level")
|
|
851
|
-
or payload.get("approval_level")
|
|
852
|
-
)
|
|
853
|
-
if approval_level:
|
|
854
|
-
metadata["approval_level"] = str(approval_level)
|
|
855
|
-
return metadata
|
|
1023
|
+
return _agent_helpers.approval_metadata(detail, payload)
|
|
856
1024
|
|
|
857
1025
|
@staticmethod
|
|
858
1026
|
def _approval_message(detail: Mapping[str, Any], payload: Mapping[str, Any]) -> str:
|
|
859
|
-
|
|
860
|
-
return str(
|
|
861
|
-
action.get("description")
|
|
862
|
-
or detail.get("message")
|
|
863
|
-
or payload.get("message")
|
|
864
|
-
or "Approval required"
|
|
865
|
-
)
|
|
1027
|
+
return _agent_helpers.approval_message(detail, payload)
|
|
866
1028
|
|
|
867
1029
|
@staticmethod
|
|
868
1030
|
def _resume_fingerprint(status: str, payload: Any) -> Any:
|
|
869
|
-
return
|
|
1031
|
+
return _agent_helpers.resume_fingerprint(status, payload)
|
|
870
1032
|
|
|
871
1033
|
|
|
872
1034
|
__all__ = ["KsadkAGUIAgent"]
|
|
1035
|
+
|
|
1036
|
+
def _agui_user_text(input: RunAgentInput) -> str:
|
|
1037
|
+
parts = []
|
|
1038
|
+
for message in input.messages or []:
|
|
1039
|
+
content = getattr(message, "content", "")
|
|
1040
|
+
if isinstance(content, str):
|
|
1041
|
+
parts.append(content)
|
|
1042
|
+
elif content is not None:
|
|
1043
|
+
parts.append(str(content))
|
|
1044
|
+
return "\n".join(parts)
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
def _agui_envelope_payload(envelope) -> tuple[str, str] | None:
|
|
1048
|
+
"""Session envelope -> AG-UI 文本投影;cursor 仍用 envelope.seq。"""
|
|
1049
|
+
|
|
1050
|
+
payload = envelope.payload or {}
|
|
1051
|
+
if envelope.event_type == "run.completed":
|
|
1052
|
+
return "completed", str(payload.get("output_text") or "")
|
|
1053
|
+
text = str(payload.get("delta") or payload.get("text") or "")
|
|
1054
|
+
if text:
|
|
1055
|
+
return "delta", text
|
|
1056
|
+
return None
|