agentengine-sdk-python 0.8.0__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.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/METADATA +43 -7
- agentengine_sdk_python-0.8.2.dist-info/RECORD +778 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/WHEEL +1 -1
- ksadk/a2a/__init__.py +2 -0
- ksadk/a2a/_space_client_events.py +381 -0
- ksadk/a2a/bootstrap.py +0 -2
- ksadk/a2a/card.py +6 -111
- ksadk/a2a/control_plane.py +239 -1
- ksadk/a2a/event_adapter.py +156 -64
- ksadk/a2a/executor.py +195 -172
- ksadk/a2a/routes.py +12 -5
- ksadk/a2a/server.py +1 -8
- ksadk/a2a/service_env.py +33 -0
- ksadk/a2a/space_client.py +43 -349
- ksadk/a2a_card.py +101 -0
- ksadk/a2ui/core.py +222 -53
- ksadk/agui/_agent_helpers.py +243 -0
- ksadk/agui/a2ui_projection.py +12 -5
- ksadk/agui/agent.py +474 -275
- ksadk/agui/config.py +11 -5
- ksadk/agui/routes.py +7 -15
- ksadk/api/client.py +530 -40
- ksadk/api/environment.py +27 -0
- ksadk/builders/code_builder.py +352 -53
- ksadk/builders/container_builder.py +71 -44
- ksadk/builders/framework_requirements.py +2 -1
- ksadk/builders/ks3_uploader.py +2 -2
- ksadk/builders/managed_runtime_builder.py +60 -28
- ksadk/cli/__init__.py +25 -0
- ksadk/cli/cmd_a2a.py +18 -31
- ksadk/cli/cmd_create.py +13 -26
- ksadk/cli/cmd_dashboard.py +15 -1
- ksadk/cli/cmd_deploy.py +28 -3
- ksadk/cli/cmd_eval.py +443 -0
- ksadk/cli/cmd_evalset.py +284 -0
- ksadk/cli/cmd_files.py +5 -1
- ksadk/cli/cmd_hermes.py +137 -163
- ksadk/cli/cmd_invoke.py +28 -38
- ksadk/cli/cmd_launch.py +12 -0
- ksadk/cli/cmd_managed_runtime.py +95 -0
- ksadk/cli/cmd_observe.py +85 -0
- ksadk/cli/cmd_openclaw.py +85 -479
- ksadk/cli/cmd_replay.py +28 -4
- ksadk/cli/cmd_run.py +29 -67
- ksadk/cli/cmd_studio.py +201 -0
- ksadk/cli/cmd_web.py +15 -6
- ksadk/cli/dry_run.py +2 -1
- ksadk/cli/env_options.py +83 -0
- ksadk/cli/global_options.py +3 -1
- ksadk/cli/hermes_env.py +151 -0
- ksadk/cli/invoke_payload.py +49 -0
- ksadk/cli/network_options.py +7 -5
- ksadk/cli/openclaw_env.py +458 -0
- ksadk/cli/runtime_bootstrap.py +51 -0
- ksadk/cli/ui.py +6 -0
- ksadk/cli/workflow_common.py +5 -5
- ksadk/codex/__init__.py +3 -3
- ksadk/codex/client.py +833 -49
- ksadk/codex/phase.py +1 -1
- ksadk/codex/runtime.py +720 -127
- ksadk/common/kop_client.py +232 -0
- ksadk/configs/__init__.py +1 -3
- ksadk/configs/env_registry.py +244 -45
- ksadk/configs/env_registry_pcm.py +181 -0
- ksadk/configs/env_var_spec.py +18 -0
- ksadk/configs/global_config.py +6 -1
- ksadk/configs/settings.py +5 -108
- 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/__init__.py +85 -94
- 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 +193 -3
- ksadk/conversations/runtime_invocation.py +81 -3
- ksadk/conversations/runtime_observability.py +157 -4
- ksadk/conversations/runtime_payloads.py +42 -0
- ksadk/conversations/runtime_preparation.py +280 -2
- ksadk/conversations/runtime_resume.py +71 -32
- ksadk/conversations/runtime_stream_events.py +94 -9
- ksadk/conversations/runtime_streaming.py +175 -22
- 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 +38 -0
- ksadk/deployment/manager.py +24 -8
- ksadk/deployment/providers/serverless.py +228 -92
- ksadk/evaluation/__init__.py +116 -0
- ksadk/evaluation/a2a_adapter.py +452 -0
- ksadk/evaluation/adapters.py +67 -0
- 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 +478 -0
- ksadk/evaluation/evalset.py +351 -0
- ksadk/evaluation/evaluators.py +627 -0
- ksadk/evaluation/evidence.py +258 -0
- ksadk/evaluation/executor.py +143 -0
- ksadk/evaluation/local_adapter.py +550 -0
- ksadk/evaluation/service_env.py +27 -0
- ksadk/evaluation/storage.py +68 -0
- ksadk/evaluation/studio_build_adapter.py +253 -0
- ksadk/evaluation/target.py +82 -0
- 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 -256
- ksadk/events/session_event.py +324 -0
- ksadk/events/store.py +3 -316
- ksadk/events/v1_compat.py +41 -0
- ksadk/harness/__init__.py +3 -2
- ksadk/harness/app.py +114 -123
- ksadk/harness/config.py +1 -1
- ksadk/harness/runtime.py +467 -0
- ksadk/hermes_terminal.py +5 -0
- 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 +22 -4
- ksadk/knowledge_base/service.py +32 -5
- ksadk/managed_a2a_card.py +160 -0
- ksadk/managed_runtime.py +16 -9
- 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 +394 -5
- ksadk/memory/adk/backends/sqlite_ltm_backend.py +95 -0
- ksadk/memory/adk/long_term_memory.py +3 -2
- 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 +198 -8
- ksadk/memory/tool.py +4 -0
- ksadk/model_proxy/bootstrap.py +16 -9
- ksadk/model_proxy/config.py +22 -1
- ksadk/model_proxy/detect.py +202 -9
- ksadk/model_proxy/namespace.py +67 -15
- ksadk/model_proxy/server.py +168 -6
- ksadk/model_proxy/transform.py +105 -3
- 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 +14 -31
- ksadk/runners/base_runner.py +44 -3
- ksadk/runners/factory.py +3 -3
- ksadk/runners/langgraph_runner.py +252 -433
- ksadk/runners/utils/__init__.py +0 -10
- ksadk/runners/utils/loader.py +16 -0
- ksadk/runtime/__init__.py +67 -41
- ksadk/runtime/_runner_adapter/__init__.py +1 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +788 -0
- ksadk/runtime/adapter.py +199 -16
- ksadk/runtime/conversation_execution.py +687 -0
- ksadk/runtime/executor.py +392 -0
- ksadk/runtime/factory.py +342 -0
- ksadk/runtime/framework_adapters.py +6 -12
- ksadk/runtime/hosted_finalizer.py +268 -0
- ksadk/runtime/launch.py +61 -0
- ksadk/runtime/preprocessing.py +49 -14
- ksadk/runtime/runner_adapter.py +330 -391
- ksadk/runtime/runner_loading.py +36 -0
- ksadk/runtime/usage.py +33 -0
- ksadk/sandbox/backends/e2b.py +36 -3
- ksadk/server/__init__.py +39 -4
- ksadk/server/app.py +18 -492
- ksadk/server/composition.py +36 -2
- ksadk/server/factory.py +210 -149
- ksadk/server/routes/common.py +15 -46
- ksadk/server/routes/control.py +13 -9
- ksadk/server/routes/kernel_ingress.py +258 -0
- ksadk/server/routes/misc.py +10 -33
- ksadk/server/routes/models.py +14 -6
- ksadk/server/routes/openai_compat.py +129 -27
- ksadk/server/routes/projection.py +84 -16
- ksadk/server/routes/run.py +347 -460
- ksadk/server/routes/sessions.py +37 -40
- ksadk/server/routes/streaming.py +52 -7
- ksadk/server/routes/workspace.py +54 -21
- ksadk/server/static/assets/{ArtifactsPanel-Cjnqt-8W.js → ArtifactsPanel-DSU1sWD_.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BqyqZfuB.js → CodeBlock-DOH6MVcn.js} +4 -4
- ksadk/server/static/assets/{MathMessageMarkdown-BpH7jiFM.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-BGhvzDYt.js → chunk-5VM5RSS4-BVHAchFb.js} +1 -1
- ksadk/server/static/assets/{chunk-ND2GUHAM-D98vPd-E.js → chunk-F27PBJKO-C-ipQzuS.js} +1 -1
- ksadk/server/static/assets/chunk-G27WJ6UU-C2EyJbIK.js +231 -0
- ksadk/server/static/assets/{chunk-4BX2VUAB-CsWIQRhc.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-CX3yotHq.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-D82mtD2s.js → dist-8hqcx0sU.js} +1 -1
- ksadk/server/static/assets/dist-B7seoj3d.js +1 -0
- ksadk/server/static/assets/{dist-DHn6nBzr.js → dist-BE7bu-DL.js} +1 -1
- ksadk/server/static/assets/{dist-eoW6tZXA.js → dist-BVDffZ0U.js} +1 -1
- ksadk/server/static/assets/{dist-C2xjE7cO.js → dist-BX8z72IC.js} +1 -1
- ksadk/server/static/assets/{dist-CgF3fj15.js → dist-Bf2M8m3N.js} +1 -1
- ksadk/server/static/assets/{dist-Bs-jQcRX.js → dist-BjU6y-A2.js} +1 -1
- ksadk/server/static/assets/{dist-Djgl2wVZ.js → dist-BytlxIDT.js} +1 -1
- ksadk/server/static/assets/{dist-CVQRZjPu.js → dist-CSh_DE14.js} +1 -1
- ksadk/server/static/assets/{dist-6CVKuTAe.js → dist-CXYYBw3_.js} +1 -1
- ksadk/server/static/assets/{dist-DlzCRy0S.js → dist-C_wsv-Qd.js} +1 -1
- ksadk/server/static/assets/{dist-DF06ORQo.js → dist-ClxGviKw.js} +1 -1
- ksadk/server/static/assets/{dist-Cf23NY4L.js → dist-CttYUqzS.js} +1 -1
- ksadk/server/static/assets/{dist-ivOya1LD.js → dist-DNp6rLRA.js} +1 -1
- ksadk/server/static/assets/{dist-BibcG1V9.js → dist-DUX-id_F.js} +1 -1
- ksadk/server/static/assets/{dist-BUHRxvDG.js → dist-DmldrHd_.js} +1 -1
- ksadk/server/static/assets/{dist-BZ9n9AjO.js → dist-DnfXs8Vn.js} +2 -2
- ksadk/server/static/assets/{dist-DqNnNFrw.js → dist-Dq9gLD7L.js} +1 -1
- ksadk/server/static/assets/{dist-CGcp2ex8.js → dist-W-TIVntx.js} +1 -1
- ksadk/server/static/assets/{dist-Cwt7koer.js → dist-dDdADKFA.js} +1 -1
- ksadk/server/static/assets/{dist-C7-3jInC.js → dist-dydu68Fl.js} +1 -1
- ksadk/server/static/assets/{dist-C99THtIA.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-DLOHGvWw.js → ishikawaDiagram-5VMMS53U-DWya9SG2.js} +6 -6
- ksadk/server/static/assets/{journeyDiagram-JHISSGLW-BIzKeejT.js → journeyDiagram-EYS64GPL-DutxhSNI.js} +6 -6
- ksadk/server/static/assets/{kanban-definition-UN3LZRKU-BWHoFSw2.js → kanban-definition-3QL26DDD-DJdOF8Fm.js} +10 -10
- ksadk/server/static/assets/katex-vFWytM5c.js +257 -0
- ksadk/server/static/assets/{linear-CvMBw9cA.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-CSAQxEAe.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-CxIR4JXI.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-DpGa6EAV.js → sankeyDiagram-P5KCCOFB-CPH75rhw.js} +7 -7
- ksadk/server/static/assets/{sequenceDiagram-3UESZ5HK-NTKNGGe5.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-jqoYs3jQ.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/skills/runtime/backends/e2b.py +1 -1
- ksadk/skills/service_client.py +13 -3
- ksadk/studio/__init__.py +5 -0
- ksadk/studio/agent_avatar_assets.py +120 -0
- ksadk/studio/agent_lifecycle.py +51 -0
- ksadk/studio/api.py +1598 -0
- ksadk/studio/api_catalog_routes.py +324 -0
- ksadk/studio/api_contracts.py +286 -0
- ksadk/studio/api_helpers.py +132 -0
- ksadk/studio/api_memory_routes.py +82 -0
- ksadk/studio/authoring.py +749 -0
- ksadk/studio/authoring_coordinator.py +1017 -0
- ksadk/studio/builder.py +397 -0
- ksadk/studio/capabilities.py +368 -0
- ksadk/studio/cloud.py +2099 -0
- ksadk/studio/codex_agent_service.py +694 -0
- ksadk/studio/codex_authoring.py +469 -0
- ksadk/studio/codex_builder.py +437 -0
- ksadk/studio/codex_manifest.py +307 -0
- ksadk/studio/codex_run.py +395 -0
- ksadk/studio/compiler.py +190 -0
- ksadk/studio/contracts.py +755 -0
- ksadk/studio/errors.py +47 -0
- ksadk/studio/event_store.py +214 -0
- ksadk/studio/framework_run.py +342 -0
- ksadk/studio/hosted_kernel.py +317 -0
- ksadk/studio/identifiers.py +33 -0
- ksadk/studio/manifest_resolver.py +131 -0
- ksadk/studio/mcp_runtime.py +229 -0
- ksadk/studio/model_client.py +629 -0
- ksadk/studio/model_profile_service.py +214 -0
- ksadk/studio/operations.py +275 -0
- ksadk/studio/otel_trace.py +1060 -0
- ksadk/studio/pagination.py +182 -0
- ksadk/studio/pcm_memory.py +85 -0
- ksadk/studio/python_tool_inspection.py +183 -0
- ksadk/studio/repository.py +327 -0
- ksadk/studio/resource_catalog.py +1260 -0
- ksadk/studio/run_service.py +1133 -0
- ksadk/studio/runtime_catalog.py +74 -0
- ksadk/studio/runtime_source.py +365 -0
- ksadk/studio/service.py +2249 -0
- ksadk/studio/shared_web.py +1004 -0
- ksadk/studio/skill_discovery.py +628 -0
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +3 -0
- ksadk/studio/static/assets/index-BLpcdrgW.css +1 -0
- ksadk/studio/static/assets/index-CYekR2Xv.js +260 -0
- ksadk/studio/static/assets/react-vendor-BNmTiJ-I.js +9 -0
- ksadk/studio/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- ksadk/studio/static/index.html +15 -0
- ksadk/studio/templates.py +722 -0
- ksadk/studio/validator.py +265 -0
- ksadk/studio/workspace.py +135 -0
- ksadk/tools/gateway.py +9 -0
- ksadk/toolsets/__init__.py +27 -1
- ksadk/toolsets/a2a.py +426 -0
- ksadk/tracing/__init__.py +19 -21
- ksadk/tracing/setup.py +317 -403
- ksadk/tracing/span_utils.py +0 -44
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/registry.py +56 -56
- ksadk_runtime_common/schemas/runtime_event_v1.json +37 -0
- ksadk_runtime_common/schemas/runtime_event_v2.json +271 -0
- ksadk_runtime_common/workspace_files/router.py +8 -2
- agentengine_sdk_python-0.8.0.dist-info/RECORD +0 -578
- ksadk/a2a/card_builder.py +0 -64
- ksadk/a2a/client.py +0 -309
- ksadk/events/parser.py +0 -191
- ksadk/harness/runner.py +0 -211
- ksadk/runners/codex_runner.py +0 -132
- ksadk/runners/utils/langfuse.py +0 -230
- ksadk/server/static/assets/MathMessageMarkdown-DeYh8QPr.css +0 -1
- ksadk/server/static/assets/MermaidBlock-DWuxETaJ.js +0 -303
- ksadk/server/static/assets/NativeTerminalPanel-MDTopWMO.js +0 -1
- ksadk/server/static/assets/arc-CFKwSk_B.js +0 -1
- ksadk/server/static/assets/architecture-7EHR7CIX-CynqOWjZ.js +0 -1
- ksadk/server/static/assets/architectureDiagram-3BPJPVTR-Dej8jX8c.js +0 -36
- ksadk/server/static/assets/blockDiagram-GPEHLZMM-1F64jqvy.js +0 -132
- ksadk/server/static/assets/c4Diagram-AAUBKEIU-9q7AUAKb.js +0 -10
- ksadk/server/static/assets/channel-iUGv2N24.js +0 -1
- ksadk/server/static/assets/chunk-2J33WTMH-6qgwJm7Q.js +0 -1
- ksadk/server/static/assets/chunk-55IACEB6-BK8paA20.js +0 -1
- ksadk/server/static/assets/chunk-727SXJPM-B-JEhy7h.js +0 -206
- ksadk/server/static/assets/chunk-AQP2D5EJ-DYBvMHAa.js +0 -231
- ksadk/server/static/assets/chunk-QZHKN3VN-YQIEXeF6.js +0 -1
- ksadk/server/static/assets/classDiagram-4FO5ZUOK-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-Q7XG4LA2-CDAUuoXK.js +0 -1
- ksadk/server/static/assets/cytoscape.esm-DelgaX4f.js +0 -321
- ksadk/server/static/assets/dagre-BM42HDAG-C7TguAWo.js +0 -4
- ksadk/server/static/assets/dagre-Bx709z4p.js +0 -1
- ksadk/server/static/assets/diagram-2AECGRRQ-Dd17_kws.js +0 -43
- ksadk/server/static/assets/diagram-5GNKFQAL-DVIClIil.js +0 -10
- ksadk/server/static/assets/diagram-KO2AKTUF-Df_3gYQa.js +0 -3
- ksadk/server/static/assets/diagram-LMA3HP47-BhLk6ZtA.js +0 -24
- ksadk/server/static/assets/diagram-OG6HWLK6-D4GNGvuu.js +0 -24
- ksadk/server/static/assets/dist-DyvYLMW9.js +0 -1
- ksadk/server/static/assets/erDiagram-TEJ5UH35-CnfRcY2M.js +0 -85
- ksadk/server/static/assets/eventmodeling-FCH6USID-ChYO-ijM.js +0 -1
- ksadk/server/static/assets/flowDiagram-I6XJVG4X-DGaJjGNJ.js +0 -162
- ksadk/server/static/assets/ganttDiagram-6RSMTGT7-DpCoB2g9.js +0 -292
- ksadk/server/static/assets/gitGraph-WXDBUCRP-BN_0Fk-j.js +0 -1
- ksadk/server/static/assets/gitGraphDiagram-PVQCEYII-9IKVFBVT.js +0 -106
- ksadk/server/static/assets/graphlib-B8gBHxth.js +0 -1
- ksadk/server/static/assets/index-QSwCHuB8.js +0 -177
- ksadk/server/static/assets/index-jOPmTOZH.css +0 -2
- ksadk/server/static/assets/info-J43DQDTF-Cp6o3vId.js +0 -1
- ksadk/server/static/assets/infoDiagram-5YYISTIA-CYIIsb8y.js +0 -2
- ksadk/server/static/assets/katex-DATssjp1.js +0 -265
- ksadk/server/static/assets/mermaid-parser.core-mGAcEwcq.js +0 -161
- ksadk/server/static/assets/packet-YPE3B663-wQzct3cT.js +0 -1
- ksadk/server/static/assets/pie-LRSECV5Y-BgTQiv-9.js +0 -1
- ksadk/server/static/assets/pieDiagram-4H26LBE5-By-ra07M.js +0 -30
- ksadk/server/static/assets/radar-GUYGQ44K-BIq5fXsn.js +0 -1
- ksadk/server/static/assets/requirementDiagram-4Y6WPE33-DpW90iu3.js +0 -84
- ksadk/server/static/assets/stateDiagram-AJRCARHV-DGpd9yFG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-BHNVJYJU-B3o579IQ.js +0 -1
- ksadk/server/static/assets/treeView-BLDUP644-Dqi-E0EM.js +0 -1
- ksadk/server/static/assets/treemap-LRROVOQU-ClQP9CJ9.js +0 -1
- ksadk/server/static/assets/vennDiagram-CIIHVFJN-l3Z7-wbP.js +0 -34
- ksadk/server/static/assets/wardley-L42UT6IY-8XLvnNIs.js +0 -1
- ksadk/server/static/assets/wardleyDiagram-YWT4CUSO-BR54GPmr.js +0 -78
- ksadk/server/static/assets/xychartDiagram-2RQKCTM6-SkiH8GsK.js +0 -7
- ksadk/tracing/exporters/langfuse_exporter.py +0 -460
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.0.dist-info → agentengine_sdk_python-0.8.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,785 @@
|
|
|
1
|
+
"""LangGraph adapter 的常量、状态 dataclass 与映射辅助(纯移动自 adapters.langgraph,行为不变)。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import math
|
|
7
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Any, Literal, NoReturn, cast
|
|
10
|
+
|
|
11
|
+
from langchain_core.messages import AIMessage
|
|
12
|
+
from pydantic import JsonValue
|
|
13
|
+
|
|
14
|
+
from ksadk.events.canonical import (
|
|
15
|
+
ItemCompleted,
|
|
16
|
+
ItemStarted,
|
|
17
|
+
ItemUpdated,
|
|
18
|
+
RuntimeEvent,
|
|
19
|
+
SourceRef,
|
|
20
|
+
)
|
|
21
|
+
from ksadk.events.content import (
|
|
22
|
+
ContentSnapshot,
|
|
23
|
+
ContentValue,
|
|
24
|
+
DataContent,
|
|
25
|
+
TextContent,
|
|
26
|
+
ToolCallContent,
|
|
27
|
+
ToolResultContent,
|
|
28
|
+
)
|
|
29
|
+
from ksadk.events.identity import (
|
|
30
|
+
stable_event_id,
|
|
31
|
+
stable_item_id,
|
|
32
|
+
stable_part_id,
|
|
33
|
+
stable_scope_id,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Native content-block types that carry a tool call identity.
|
|
37
|
+
_TOOL_CALL_BLOCKS = frozenset(
|
|
38
|
+
"tool_call tool_call_chunk server_tool_call server_tool_call_chunk".split()
|
|
39
|
+
)
|
|
40
|
+
# Native tool-call delta shapes accepted without a payload translation.
|
|
41
|
+
_TOOL_DELTA_TYPES = frozenset(
|
|
42
|
+
"tool_call tool_call_chunk tool_call-delta server_tool_call server_tool_call_chunk".split()
|
|
43
|
+
)
|
|
44
|
+
# Lifecycle native types that close the nested scope without a run-progress event.
|
|
45
|
+
_LIFECYCLE_QUIET_TYPES = frozenset({"interrupted"})
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _fail(code: str, field_name: str, message: str) -> NoReturn:
|
|
49
|
+
raise LangGraphMappingError(code, field_name, message)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class LangGraphMappingError(ValueError):
|
|
53
|
+
"""A LangGraph v3 event violates the native identity contract."""
|
|
54
|
+
|
|
55
|
+
def __init__(self, code: str, field_name: str, message: str) -> None:
|
|
56
|
+
super().__init__(message)
|
|
57
|
+
self.code = code
|
|
58
|
+
self.field_name = field_name
|
|
59
|
+
self.source = "langgraph"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class LangGraphAdapterContext:
|
|
64
|
+
"""Invocation facts and deterministic pre-store reducer ordering.
|
|
65
|
+
|
|
66
|
+
``graph_run_id`` is supplied by the runner invocation/config because the
|
|
67
|
+
in-process ProtocolEvent envelope identifies LLM runs but not the enclosing
|
|
68
|
+
graph run. Allocated ``seq`` values are placeholders only; RuntimeEventStore
|
|
69
|
+
remains the canonical session sequence allocator.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
run_id: str
|
|
73
|
+
graph_run_id: str
|
|
74
|
+
initial_seq: int = 0
|
|
75
|
+
checkpoint_ref: Mapping[str, str] | None = None
|
|
76
|
+
_next_seq: int = field(init=False, repr=False)
|
|
77
|
+
|
|
78
|
+
def __post_init__(self) -> None:
|
|
79
|
+
self.run_id = _required_string(self.run_id, "runtime run_id")
|
|
80
|
+
self.graph_run_id = _required_string(self.graph_run_id, "graph_run_id")
|
|
81
|
+
if self.initial_seq < 0:
|
|
82
|
+
raise ValueError("LangGraph initial_seq must be non-negative")
|
|
83
|
+
self._next_seq = self.initial_seq
|
|
84
|
+
if self.checkpoint_ref is not None:
|
|
85
|
+
self.checkpoint_ref = dict(self.checkpoint_ref)
|
|
86
|
+
|
|
87
|
+
def allocate_placeholder_seq(self) -> int:
|
|
88
|
+
value = self._next_seq
|
|
89
|
+
self._next_seq += 1
|
|
90
|
+
return value
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class _Frame:
|
|
95
|
+
"""Per-ProtocolEvent routing facts shared by all method lanes."""
|
|
96
|
+
|
|
97
|
+
namespace: tuple[str, ...]
|
|
98
|
+
scope_id: str
|
|
99
|
+
parent_scope_id: str | None
|
|
100
|
+
source_seq: int
|
|
101
|
+
native_event_id: str | None
|
|
102
|
+
occurrence_key: str
|
|
103
|
+
timestamp: float
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass
|
|
107
|
+
class _ItemLane:
|
|
108
|
+
item_id: str
|
|
109
|
+
item_kind: Literal["message", "reasoning", "tool_call", "tool_result"]
|
|
110
|
+
phase: Literal["commentary", "final_answer"]
|
|
111
|
+
native_item_id: str
|
|
112
|
+
parts: dict[int, ContentValue] = field(default_factory=dict)
|
|
113
|
+
completed: bool = False
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class _MessageState:
|
|
118
|
+
scope_id: str
|
|
119
|
+
parent_scope_id: str | None
|
|
120
|
+
llm_run_id: str
|
|
121
|
+
message_id: str
|
|
122
|
+
node: str
|
|
123
|
+
lanes: dict[str, _ItemLane] = field(default_factory=dict)
|
|
124
|
+
block_lanes: dict[int, str] = field(default_factory=dict)
|
|
125
|
+
finished_blocks: set[int] = field(default_factory=set)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@dataclass
|
|
129
|
+
class _ToolState:
|
|
130
|
+
scope_id: str
|
|
131
|
+
parent_scope_id: str | None
|
|
132
|
+
call_id: str
|
|
133
|
+
name: str
|
|
134
|
+
item_id: str
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass
|
|
138
|
+
class _LifecycleState:
|
|
139
|
+
scope_id: str
|
|
140
|
+
parent_scope_id: str | None
|
|
141
|
+
item_id: str
|
|
142
|
+
namespace: tuple[str, ...]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _map_data_channel(
|
|
146
|
+
*,
|
|
147
|
+
context: LangGraphAdapterContext,
|
|
148
|
+
frame: _Frame,
|
|
149
|
+
method: str,
|
|
150
|
+
source: SourceRef,
|
|
151
|
+
value: Any,
|
|
152
|
+
) -> tuple[RuntimeEvent, ...]:
|
|
153
|
+
env = _envelope(context, frame.occurrence_key, frame.timestamp)
|
|
154
|
+
item_id = stable_item_id("langgraph", frame.scope_id, "channel", method, frame.source_seq)
|
|
155
|
+
part_id = _part_id(item_id, "channel", method)
|
|
156
|
+
content = DataContent(part_id=part_id, data=_json_value(value))
|
|
157
|
+
envelope = lambda event_type: env( # noqa: E731
|
|
158
|
+
frame.scope_id, frame.parent_scope_id, item_id, event_type, part_id, source
|
|
159
|
+
)
|
|
160
|
+
return (
|
|
161
|
+
ItemStarted(
|
|
162
|
+
**envelope("item.started"),
|
|
163
|
+
item_id=item_id,
|
|
164
|
+
item_kind="data",
|
|
165
|
+
phase="commentary",
|
|
166
|
+
),
|
|
167
|
+
ItemCompleted(
|
|
168
|
+
**envelope("item.completed"),
|
|
169
|
+
item_id=item_id,
|
|
170
|
+
item_kind="data",
|
|
171
|
+
snapshot=ContentSnapshot(parts=(content,)),
|
|
172
|
+
),
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _new_lane(
|
|
177
|
+
state: _MessageState,
|
|
178
|
+
item_kind: Literal["message", "reasoning", "tool_call", "tool_result"],
|
|
179
|
+
native_item_id: str,
|
|
180
|
+
) -> _ItemLane:
|
|
181
|
+
if item_kind == "message":
|
|
182
|
+
item_id = stable_item_id(
|
|
183
|
+
"langgraph", state.scope_id, "message", state.llm_run_id, state.message_id
|
|
184
|
+
)
|
|
185
|
+
phase: Literal["commentary", "final_answer"] = "final_answer"
|
|
186
|
+
elif item_kind == "reasoning":
|
|
187
|
+
item_id = stable_item_id(
|
|
188
|
+
"langgraph", state.scope_id, "reasoning", state.llm_run_id, state.message_id
|
|
189
|
+
)
|
|
190
|
+
phase = "commentary"
|
|
191
|
+
elif item_kind == "tool_call":
|
|
192
|
+
item_id = stable_item_id(
|
|
193
|
+
"langgraph", state.scope_id, "tool_call", state.llm_run_id, native_item_id
|
|
194
|
+
)
|
|
195
|
+
phase = "commentary"
|
|
196
|
+
else:
|
|
197
|
+
# Provider-executed results on the messages channel are semantically
|
|
198
|
+
# distinct from locally executed results on the tools channel.
|
|
199
|
+
item_id = stable_item_id(
|
|
200
|
+
"langgraph",
|
|
201
|
+
state.scope_id,
|
|
202
|
+
"provider_tool_result",
|
|
203
|
+
state.llm_run_id,
|
|
204
|
+
state.message_id,
|
|
205
|
+
native_item_id,
|
|
206
|
+
)
|
|
207
|
+
phase = "commentary"
|
|
208
|
+
return _ItemLane(
|
|
209
|
+
item_id=item_id,
|
|
210
|
+
item_kind=item_kind,
|
|
211
|
+
phase=phase,
|
|
212
|
+
native_item_id=native_item_id,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _lane_for_content(
|
|
217
|
+
state: _MessageState,
|
|
218
|
+
index: int,
|
|
219
|
+
content: Mapping[str, Any],
|
|
220
|
+
) -> tuple[_ItemLane, bool]:
|
|
221
|
+
if index in state.block_lanes:
|
|
222
|
+
_fail(
|
|
223
|
+
"content_block_already_started",
|
|
224
|
+
"content-block-start.index",
|
|
225
|
+
f"LangGraph content block {index} started twice",
|
|
226
|
+
)
|
|
227
|
+
block_type = _required_string(content.get("type"), "content block type")
|
|
228
|
+
if block_type in _TOOL_CALL_BLOCKS:
|
|
229
|
+
call_id = _required_string(content.get("id"), "tool_call.id")
|
|
230
|
+
lane_key, item_kind, native_item_id = f"tool_call:{call_id}", "tool_call", call_id
|
|
231
|
+
elif block_type == "server_tool_result":
|
|
232
|
+
call_id = _required_string(content.get("tool_call_id"), "server_tool_result.tool_call_id")
|
|
233
|
+
lane_key, item_kind, native_item_id = (
|
|
234
|
+
f"provider_tool_result:{call_id}",
|
|
235
|
+
"tool_result",
|
|
236
|
+
call_id,
|
|
237
|
+
)
|
|
238
|
+
elif block_type == "text":
|
|
239
|
+
lane_key, item_kind, native_item_id = "message", "message", state.message_id
|
|
240
|
+
elif block_type == "reasoning":
|
|
241
|
+
lane_key, item_kind, native_item_id = "reasoning", "reasoning", state.message_id
|
|
242
|
+
else:
|
|
243
|
+
_fail(
|
|
244
|
+
"unsupported_content_block",
|
|
245
|
+
"content.type",
|
|
246
|
+
f"Unsupported LangGraph content block type: {block_type}",
|
|
247
|
+
)
|
|
248
|
+
lane = state.lanes.get(lane_key)
|
|
249
|
+
created = lane is None
|
|
250
|
+
if lane is None:
|
|
251
|
+
lane = _new_lane(state, item_kind, native_item_id)
|
|
252
|
+
state.lanes[lane_key] = lane
|
|
253
|
+
state.block_lanes[index] = lane_key
|
|
254
|
+
return lane, created
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _lane_for_index(state: _MessageState, index: int) -> _ItemLane:
|
|
258
|
+
lane_key = state.block_lanes.get(index)
|
|
259
|
+
if lane_key is None:
|
|
260
|
+
_fail(
|
|
261
|
+
"content_block_not_started",
|
|
262
|
+
"content block index",
|
|
263
|
+
f"LangGraph content block {index} mutated before start",
|
|
264
|
+
)
|
|
265
|
+
return state.lanes[lane_key]
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _lane_source(source: SourceRef, lane: _ItemLane) -> SourceRef:
|
|
269
|
+
update: dict[str, Any] = {"native_item_id": lane.native_item_id}
|
|
270
|
+
if lane.item_kind == "tool_result":
|
|
271
|
+
update["metadata"] = {**source.metadata, "tool_semantic": "provider_result"}
|
|
272
|
+
return source.model_copy(update=update)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _lane_started(
|
|
276
|
+
lane_env: Callable[..., dict[str, Any]],
|
|
277
|
+
lane: _ItemLane,
|
|
278
|
+
) -> ItemStarted:
|
|
279
|
+
return ItemStarted(
|
|
280
|
+
**lane_env(lane, "item.started", lane.item_kind),
|
|
281
|
+
item_id=lane.item_id,
|
|
282
|
+
item_kind=lane.item_kind,
|
|
283
|
+
phase=lane.phase,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _lane_updated(
|
|
288
|
+
lane_env: Callable[..., dict[str, Any]],
|
|
289
|
+
lane: _ItemLane,
|
|
290
|
+
update: ContentValue,
|
|
291
|
+
op: Literal["append", "replace"],
|
|
292
|
+
ordinal: int,
|
|
293
|
+
) -> ItemUpdated:
|
|
294
|
+
return ItemUpdated(
|
|
295
|
+
**lane_env(lane, "item.updated", update.part_id, ordinal),
|
|
296
|
+
item_id=lane.item_id,
|
|
297
|
+
item_kind=lane.item_kind,
|
|
298
|
+
op=op,
|
|
299
|
+
update=update,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _lane_completed(
|
|
304
|
+
lane_env: Callable[..., dict[str, Any]],
|
|
305
|
+
lane: _ItemLane,
|
|
306
|
+
) -> ItemCompleted:
|
|
307
|
+
return ItemCompleted(
|
|
308
|
+
**lane_env(lane, "item.completed", "snapshot"),
|
|
309
|
+
item_id=lane.item_id,
|
|
310
|
+
item_kind=lane.item_kind,
|
|
311
|
+
snapshot=ContentSnapshot(parts=tuple(lane.parts[index] for index in sorted(lane.parts))),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _map_whole_message(
|
|
316
|
+
*,
|
|
317
|
+
payload: AIMessage,
|
|
318
|
+
metadata: Mapping[str, Any],
|
|
319
|
+
context: LangGraphAdapterContext,
|
|
320
|
+
frame: _Frame,
|
|
321
|
+
node: str,
|
|
322
|
+
) -> tuple[RuntimeEvent, ...]:
|
|
323
|
+
message_id = _required_string(payload.id, "whole message.id")
|
|
324
|
+
llm_run_id = _optional_string(metadata.get("run_id")) or context.graph_run_id
|
|
325
|
+
state = _MessageState(
|
|
326
|
+
scope_id=frame.scope_id,
|
|
327
|
+
parent_scope_id=frame.parent_scope_id,
|
|
328
|
+
llm_run_id=llm_run_id,
|
|
329
|
+
message_id=message_id,
|
|
330
|
+
node=node,
|
|
331
|
+
)
|
|
332
|
+
source = _source_ref(
|
|
333
|
+
channel="messages",
|
|
334
|
+
native_run_id=state.llm_run_id,
|
|
335
|
+
native_item_id=state.message_id,
|
|
336
|
+
source_seq=frame.source_seq,
|
|
337
|
+
native_event_id=frame.native_event_id,
|
|
338
|
+
extra={
|
|
339
|
+
"graph_run_id": context.graph_run_id,
|
|
340
|
+
"namespace": list(frame.namespace),
|
|
341
|
+
"node": state.node,
|
|
342
|
+
},
|
|
343
|
+
)
|
|
344
|
+
env = _envelope(context, frame.occurrence_key, frame.timestamp)
|
|
345
|
+
|
|
346
|
+
content = payload.content
|
|
347
|
+
blocks: Sequence[Any]
|
|
348
|
+
if isinstance(content, str):
|
|
349
|
+
# An empty whole-message string carries no text block. Tool-only
|
|
350
|
+
# messages therefore avoid a phantom final-answer lane; if there are
|
|
351
|
+
# no tool calls either, the fallback below preserves one empty message.
|
|
352
|
+
blocks = () if content == "" else ({"type": "text", "text": content},)
|
|
353
|
+
elif isinstance(content, Sequence) and not isinstance(content, (str, bytes)):
|
|
354
|
+
blocks = content
|
|
355
|
+
else:
|
|
356
|
+
_fail(
|
|
357
|
+
"unsupported_whole_message",
|
|
358
|
+
"whole message.content",
|
|
359
|
+
"LangGraph whole message content must be text or typed blocks",
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
for index, value in enumerate(blocks):
|
|
363
|
+
block = _mapping(value, f"whole message.content[{index}]")
|
|
364
|
+
lane, _ = _lane_for_content(state, index, block)
|
|
365
|
+
if lane.item_kind == "tool_call":
|
|
366
|
+
lane.parts[index] = _tool_call_snapshot(lane.item_id, index, block)
|
|
367
|
+
elif lane.item_kind == "tool_result":
|
|
368
|
+
lane.parts[index] = _server_tool_result_snapshot(lane.item_id, index, block)
|
|
369
|
+
else:
|
|
370
|
+
lane.parts[index] = _text_block_snapshot(lane.item_id, index, block)
|
|
371
|
+
|
|
372
|
+
tool_calls = getattr(payload, "tool_calls", ())
|
|
373
|
+
if isinstance(tool_calls, Sequence) and not isinstance(tool_calls, (str, bytes)):
|
|
374
|
+
for offset, value in enumerate(tool_calls, start=len(blocks)):
|
|
375
|
+
call = _mapping(value, f"whole message.tool_calls[{offset - len(blocks)}]")
|
|
376
|
+
normalized_call = {
|
|
377
|
+
"type": "tool_call",
|
|
378
|
+
"id": call.get("id"),
|
|
379
|
+
"name": call.get("name"),
|
|
380
|
+
"args": call.get("args"),
|
|
381
|
+
}
|
|
382
|
+
call_id = _required_string(normalized_call["id"], "tool_call.id")
|
|
383
|
+
if f"tool_call:{call_id}" in state.lanes:
|
|
384
|
+
continue
|
|
385
|
+
lane, _ = _lane_for_content(state, offset, normalized_call)
|
|
386
|
+
lane.parts[offset] = _tool_call_snapshot(lane.item_id, offset, normalized_call)
|
|
387
|
+
|
|
388
|
+
if not state.lanes:
|
|
389
|
+
state.lanes["message"] = _new_lane(state, "message", state.message_id)
|
|
390
|
+
|
|
391
|
+
emitted: list[RuntimeEvent] = []
|
|
392
|
+
for lane in state.lanes.values():
|
|
393
|
+
emitted.append(
|
|
394
|
+
ItemStarted(
|
|
395
|
+
**env(
|
|
396
|
+
state.scope_id,
|
|
397
|
+
state.parent_scope_id,
|
|
398
|
+
lane.item_id,
|
|
399
|
+
"item.started",
|
|
400
|
+
lane.item_kind,
|
|
401
|
+
_lane_source(source, lane),
|
|
402
|
+
),
|
|
403
|
+
item_id=lane.item_id,
|
|
404
|
+
item_kind=lane.item_kind,
|
|
405
|
+
phase=lane.phase,
|
|
406
|
+
)
|
|
407
|
+
)
|
|
408
|
+
lane.completed = True
|
|
409
|
+
emitted.append(
|
|
410
|
+
ItemCompleted(
|
|
411
|
+
**env(
|
|
412
|
+
state.scope_id,
|
|
413
|
+
state.parent_scope_id,
|
|
414
|
+
lane.item_id,
|
|
415
|
+
"item.completed",
|
|
416
|
+
"snapshot",
|
|
417
|
+
_lane_source(source, lane),
|
|
418
|
+
),
|
|
419
|
+
item_id=lane.item_id,
|
|
420
|
+
item_kind=lane.item_kind,
|
|
421
|
+
snapshot=ContentSnapshot(
|
|
422
|
+
parts=tuple(lane.parts[index] for index in sorted(lane.parts))
|
|
423
|
+
),
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
return tuple(emitted)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def _envelope(
|
|
430
|
+
context: LangGraphAdapterContext,
|
|
431
|
+
occurrence_key: str,
|
|
432
|
+
timestamp: float,
|
|
433
|
+
) -> Callable[..., dict[str, Any]]:
|
|
434
|
+
def env(
|
|
435
|
+
scope_id: str,
|
|
436
|
+
parent_scope_id: str | None,
|
|
437
|
+
item_id: str,
|
|
438
|
+
event_type: str,
|
|
439
|
+
part_id: str,
|
|
440
|
+
source: SourceRef,
|
|
441
|
+
ordinal: int = 0,
|
|
442
|
+
) -> dict[str, Any]:
|
|
443
|
+
return {
|
|
444
|
+
"schema_version": 2,
|
|
445
|
+
"event_id": stable_event_id(
|
|
446
|
+
"langgraph",
|
|
447
|
+
scope_id,
|
|
448
|
+
item_id,
|
|
449
|
+
event_type,
|
|
450
|
+
part_id,
|
|
451
|
+
occurrence_key,
|
|
452
|
+
ordinal,
|
|
453
|
+
),
|
|
454
|
+
"seq": context.allocate_placeholder_seq(),
|
|
455
|
+
"timestamp": timestamp,
|
|
456
|
+
"run_id": context.run_id,
|
|
457
|
+
"scope_id": scope_id,
|
|
458
|
+
"parent_scope_id": parent_scope_id,
|
|
459
|
+
"source": source,
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return env
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def _source_ref(
|
|
466
|
+
*,
|
|
467
|
+
channel: str,
|
|
468
|
+
native_run_id: str | None,
|
|
469
|
+
native_item_id: str | None,
|
|
470
|
+
source_seq: int,
|
|
471
|
+
native_event_id: str | None,
|
|
472
|
+
extra: Mapping[str, JsonValue] | None = None,
|
|
473
|
+
) -> SourceRef:
|
|
474
|
+
metadata: dict[str, JsonValue] = {
|
|
475
|
+
"stream_version": "v3",
|
|
476
|
+
"channel": channel,
|
|
477
|
+
"seq_semantics": "source_cursor",
|
|
478
|
+
}
|
|
479
|
+
if extra:
|
|
480
|
+
metadata.update(extra)
|
|
481
|
+
return SourceRef(
|
|
482
|
+
framework="langgraph",
|
|
483
|
+
native_event_id=native_event_id,
|
|
484
|
+
native_cursor=str(source_seq),
|
|
485
|
+
native_run_id=native_run_id,
|
|
486
|
+
native_item_id=native_item_id,
|
|
487
|
+
metadata=metadata,
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _message_data(value: Any) -> tuple[Any, Mapping[str, Any]]:
|
|
492
|
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes)) or len(value) != 2:
|
|
493
|
+
_fail(
|
|
494
|
+
"invalid_messages_data",
|
|
495
|
+
"params.data",
|
|
496
|
+
"LangGraph messages data must be (MessagesData, metadata)",
|
|
497
|
+
)
|
|
498
|
+
return (
|
|
499
|
+
value[0],
|
|
500
|
+
_mapping(value[1], "params.data[1]"),
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def _text_block_snapshot(
|
|
505
|
+
item_id: str,
|
|
506
|
+
index: int,
|
|
507
|
+
content: Mapping[str, Any],
|
|
508
|
+
) -> TextContent:
|
|
509
|
+
block_type = _required_string(content.get("type"), "content block type")
|
|
510
|
+
part_id = _part_id(item_id, "content-block", block_type, index)
|
|
511
|
+
if block_type == "text":
|
|
512
|
+
field_name = "text"
|
|
513
|
+
elif block_type == "reasoning":
|
|
514
|
+
field_name = "reasoning"
|
|
515
|
+
else:
|
|
516
|
+
_fail(
|
|
517
|
+
"unsupported_content_block",
|
|
518
|
+
"content.type",
|
|
519
|
+
f"Unsupported LangGraph text-like block type: {block_type}",
|
|
520
|
+
)
|
|
521
|
+
# langchain-protocol 0.0.18 makes the reasoning body optional on both
|
|
522
|
+
# ReasoningContentBlock shapes. Empty is therefore an authoritative native
|
|
523
|
+
# snapshot; later deltas may append and finish may replace it again.
|
|
524
|
+
text = content.get(field_name, "") if block_type == "reasoning" else content.get(field_name)
|
|
525
|
+
if not isinstance(text, str):
|
|
526
|
+
_fail(
|
|
527
|
+
"invalid_content_block",
|
|
528
|
+
f"content.{field_name}",
|
|
529
|
+
f"LangGraph {block_type} block requires string {field_name}",
|
|
530
|
+
)
|
|
531
|
+
return TextContent(part_id=part_id, text=text)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _text_block_delta(
|
|
535
|
+
item_id: str,
|
|
536
|
+
index: int,
|
|
537
|
+
delta: Mapping[str, Any],
|
|
538
|
+
item_kind: Literal["message", "reasoning", "tool_call", "tool_result"],
|
|
539
|
+
) -> TextContent:
|
|
540
|
+
delta_type = _required_string(delta.get("type"), "content delta type")
|
|
541
|
+
if item_kind == "message" and delta_type == "text-delta":
|
|
542
|
+
block_type, field_name = "text", "text"
|
|
543
|
+
elif item_kind == "reasoning" and delta_type == "reasoning-delta":
|
|
544
|
+
block_type, field_name = "reasoning", "reasoning"
|
|
545
|
+
else:
|
|
546
|
+
_fail(
|
|
547
|
+
"unsupported_content_delta",
|
|
548
|
+
"delta.type",
|
|
549
|
+
f"Unsupported LangGraph content delta type: {delta_type}",
|
|
550
|
+
)
|
|
551
|
+
part_id = _part_id(item_id, "content-block", block_type, index)
|
|
552
|
+
text = delta.get(field_name)
|
|
553
|
+
if not isinstance(text, str):
|
|
554
|
+
_fail(
|
|
555
|
+
"invalid_content_delta",
|
|
556
|
+
f"delta.{field_name}",
|
|
557
|
+
f"LangGraph {delta_type} requires string {field_name}",
|
|
558
|
+
)
|
|
559
|
+
return TextContent(part_id=part_id, text=text)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def _validate_tool_delta(delta: Mapping[str, Any]) -> None:
|
|
563
|
+
delta_type = _required_string(delta.get("type"), "content delta type")
|
|
564
|
+
if delta_type == "block-delta":
|
|
565
|
+
fields = _mapping(delta.get("fields"), "block-delta.fields")
|
|
566
|
+
if _required_string(fields.get("type"), "block-delta.fields.type") in _TOOL_CALL_BLOCKS:
|
|
567
|
+
return
|
|
568
|
+
if delta_type in _TOOL_DELTA_TYPES:
|
|
569
|
+
return
|
|
570
|
+
_fail(
|
|
571
|
+
"unsupported_content_delta",
|
|
572
|
+
"delta.type",
|
|
573
|
+
f"Unsupported LangGraph tool call delta type: {delta_type}",
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def _tool_call_snapshot(
|
|
578
|
+
item_id: str,
|
|
579
|
+
index: int,
|
|
580
|
+
content: Mapping[str, Any],
|
|
581
|
+
) -> ToolCallContent:
|
|
582
|
+
block_type = _required_string(content.get("type"), "content block type")
|
|
583
|
+
if block_type not in _TOOL_CALL_BLOCKS:
|
|
584
|
+
_fail(
|
|
585
|
+
"unsupported_content_block",
|
|
586
|
+
"content.type",
|
|
587
|
+
f"Expected LangGraph tool call block, got: {block_type}",
|
|
588
|
+
)
|
|
589
|
+
call_id = _required_string(content.get("id"), "tool_call.id")
|
|
590
|
+
name = _required_string(content.get("name"), "tool_call.name")
|
|
591
|
+
return ToolCallContent(
|
|
592
|
+
part_id=_part_id(item_id, "tool-call", call_id, index),
|
|
593
|
+
call_id=call_id,
|
|
594
|
+
name=name,
|
|
595
|
+
arguments=_json_value(content.get("args")),
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
def _server_tool_result_snapshot(
|
|
600
|
+
item_id: str,
|
|
601
|
+
index: int,
|
|
602
|
+
content: Mapping[str, Any],
|
|
603
|
+
) -> ToolResultContent:
|
|
604
|
+
block_type = _required_string(content.get("type"), "content block type")
|
|
605
|
+
if block_type != "server_tool_result":
|
|
606
|
+
_fail(
|
|
607
|
+
"unsupported_content_block",
|
|
608
|
+
"content.type",
|
|
609
|
+
f"Expected LangGraph server tool result block, got: {block_type}",
|
|
610
|
+
)
|
|
611
|
+
call_id = _required_string(content.get("tool_call_id"), "server_tool_result.tool_call_id")
|
|
612
|
+
status = _required_string(content.get("status"), "server_tool_result.status")
|
|
613
|
+
if status not in {"success", "error"}:
|
|
614
|
+
_fail(
|
|
615
|
+
"invalid_content_block",
|
|
616
|
+
"server_tool_result.status",
|
|
617
|
+
f"Unsupported LangGraph server tool result status: {status}",
|
|
618
|
+
)
|
|
619
|
+
return ToolResultContent(
|
|
620
|
+
part_id=_part_id(item_id, "provider-tool-result", call_id, index),
|
|
621
|
+
call_id=call_id,
|
|
622
|
+
result=_json_value(content.get("output")),
|
|
623
|
+
is_error=status == "error",
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def _json_value(value: Any) -> JsonValue:
|
|
628
|
+
if value is None or isinstance(value, (bool, int, str)):
|
|
629
|
+
return cast(JsonValue, value)
|
|
630
|
+
if isinstance(value, float):
|
|
631
|
+
if not math.isfinite(value):
|
|
632
|
+
_fail(
|
|
633
|
+
"non_json_protocol_data",
|
|
634
|
+
"ProtocolEvent.params.data",
|
|
635
|
+
"LangGraph protocol data contains a non-finite float",
|
|
636
|
+
)
|
|
637
|
+
return cast(JsonValue, value)
|
|
638
|
+
if isinstance(value, Mapping):
|
|
639
|
+
if any(not isinstance(key, str) for key in value):
|
|
640
|
+
_fail(
|
|
641
|
+
"non_json_protocol_data",
|
|
642
|
+
"ProtocolEvent.params.data",
|
|
643
|
+
"LangGraph protocol data object keys must be strings",
|
|
644
|
+
)
|
|
645
|
+
return cast(
|
|
646
|
+
JsonValue,
|
|
647
|
+
{key: _json_value(item) for key, item in value.items()},
|
|
648
|
+
)
|
|
649
|
+
if isinstance(value, Sequence) and not isinstance(value, (str, bytes)):
|
|
650
|
+
return cast(JsonValue, [_json_value(item) for item in value])
|
|
651
|
+
model_dump = getattr(value, "model_dump", None)
|
|
652
|
+
if callable(model_dump):
|
|
653
|
+
try:
|
|
654
|
+
dumped = model_dump(mode="json")
|
|
655
|
+
except Exception as exc:
|
|
656
|
+
raise LangGraphMappingError(
|
|
657
|
+
"non_json_protocol_data",
|
|
658
|
+
"ProtocolEvent.params.data",
|
|
659
|
+
"LangGraph protocol model could not be serialized to JSON",
|
|
660
|
+
) from exc
|
|
661
|
+
if dumped is value:
|
|
662
|
+
_fail(
|
|
663
|
+
"non_json_protocol_data",
|
|
664
|
+
"ProtocolEvent.params.data",
|
|
665
|
+
"LangGraph protocol model returned itself from model_dump",
|
|
666
|
+
)
|
|
667
|
+
return _json_value(dumped)
|
|
668
|
+
_fail(
|
|
669
|
+
"non_json_protocol_data",
|
|
670
|
+
"ProtocolEvent.params.data",
|
|
671
|
+
f"LangGraph protocol data is not stably JSON serializable: {type(value).__name__}",
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
def _scope_id(graph_run_id: str, namespace: tuple[str, ...]) -> str:
|
|
676
|
+
return stable_scope_id("langgraph", graph_run_id, _namespace_identity(namespace))
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def _parent_scope_id(graph_run_id: str, namespace: tuple[str, ...]) -> str | None:
|
|
680
|
+
if not namespace:
|
|
681
|
+
return None
|
|
682
|
+
return _scope_id(graph_run_id, namespace[:-1])
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
def _namespace(value: Any) -> tuple[str, ...]:
|
|
686
|
+
if not isinstance(value, Sequence) or isinstance(value, (str, bytes)):
|
|
687
|
+
_fail(
|
|
688
|
+
"invalid_namespace",
|
|
689
|
+
"namespace",
|
|
690
|
+
"LangGraph namespace must be an ordered string sequence",
|
|
691
|
+
)
|
|
692
|
+
return tuple(_required_string(component, "namespace component") for component in value)
|
|
693
|
+
|
|
694
|
+
|
|
695
|
+
def _namespace_identity(namespace: tuple[str, ...]) -> str:
|
|
696
|
+
return json.dumps(
|
|
697
|
+
{
|
|
698
|
+
"length": len(namespace),
|
|
699
|
+
"components": [{"type": "string", "value": component} for component in namespace],
|
|
700
|
+
},
|
|
701
|
+
ensure_ascii=False,
|
|
702
|
+
separators=(",", ":"),
|
|
703
|
+
sort_keys=True,
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
def _part_id(item_id: str, *components: str | int) -> str:
|
|
708
|
+
return stable_part_id("langgraph", item_id, *components)
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
def _mapping(value: Any, field_name: str) -> Mapping[str, Any]:
|
|
712
|
+
if not isinstance(value, Mapping):
|
|
713
|
+
_fail(
|
|
714
|
+
"invalid_event_shape",
|
|
715
|
+
field_name,
|
|
716
|
+
f"LangGraph {field_name} must be an object",
|
|
717
|
+
)
|
|
718
|
+
return value
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
def _required_string(value: Any, field_name: str) -> str:
|
|
722
|
+
if not isinstance(value, str) or not value.strip():
|
|
723
|
+
_fail(
|
|
724
|
+
"missing_native_identity",
|
|
725
|
+
field_name,
|
|
726
|
+
f"LangGraph {field_name} must be a non-empty string",
|
|
727
|
+
)
|
|
728
|
+
return value
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
def _optional_string(value: Any) -> str | None:
|
|
732
|
+
return value if isinstance(value, str) and value.strip() else None
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def _block_index(value: Any) -> int:
|
|
736
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
737
|
+
_fail(
|
|
738
|
+
"invalid_block_index",
|
|
739
|
+
"index",
|
|
740
|
+
"LangGraph content block index must be a non-negative integer",
|
|
741
|
+
)
|
|
742
|
+
return int(value)
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
def _source_seq(value: Any) -> int:
|
|
746
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
747
|
+
_fail(
|
|
748
|
+
"missing_source_cursor",
|
|
749
|
+
"seq",
|
|
750
|
+
"LangGraph ProtocolEvent requires its non-negative root mux seq",
|
|
751
|
+
)
|
|
752
|
+
return int(value)
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
def _protocol_timestamp(value: Any) -> float:
|
|
756
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
757
|
+
_fail(
|
|
758
|
+
"invalid_timestamp",
|
|
759
|
+
"params.timestamp",
|
|
760
|
+
"LangGraph ProtocolEvent timestamp must be epoch milliseconds",
|
|
761
|
+
)
|
|
762
|
+
return float(value) / 1000.0
|
|
763
|
+
|
|
764
|
+
|
|
765
|
+
def _interrupt_reason(interrupts: Any) -> str | None:
|
|
766
|
+
if not isinstance(interrupts, Sequence) or isinstance(interrupts, (str, bytes)):
|
|
767
|
+
_fail(
|
|
768
|
+
"invalid_interrupts",
|
|
769
|
+
"params.interrupts",
|
|
770
|
+
"LangGraph interrupts must be a sequence",
|
|
771
|
+
)
|
|
772
|
+
if not interrupts:
|
|
773
|
+
return None
|
|
774
|
+
first = interrupts[0]
|
|
775
|
+
if isinstance(first, Mapping):
|
|
776
|
+
value = first.get("value")
|
|
777
|
+
else:
|
|
778
|
+
value = getattr(first, "value", None)
|
|
779
|
+
return value if isinstance(value, str) and value else str(first)
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
__all__ = [
|
|
783
|
+
"LangGraphAdapterContext",
|
|
784
|
+
"LangGraphMappingError",
|
|
785
|
+
]
|