agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +13 -9
- agentengine_sdk_python-0.8.5.dist-info/RECORD +1296 -0
- ksadk/_build_provenance.json +1 -1
- ksadk/_process.py +83 -0
- ksadk/_str_enum.py +17 -0
- ksadk/a2ui/core.py +3 -3
- ksadk/api/client.py +111 -91
- ksadk/builders/code_builder.py +74 -21
- ksadk/builders/framework_requirements.py +22 -3
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +1 -0
- ksadk/cli/__init__.py +68 -3
- ksadk/cli/cmd_config.py +4 -4
- ksadk/cli/cmd_create.py +12 -12
- ksadk/cli/cmd_hermes.py +24 -2
- ksadk/cli/cmd_invoke.py +28 -5
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_openclaw.py +26 -1
- ksadk/cli/cmd_plugin.py +76 -13
- ksadk/cli/cmd_studio.py +64 -16
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/openclaw_env.py +1 -1
- ksadk/cli/resource_common.py +26 -0
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +425 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +56 -298
- ksadk/common/auth.py +16 -10
- ksadk/configs/__init__.py +1 -1
- ksadk/configs/env_registry.py +153 -31
- ksadk/configs/env_registry_studio.py +86 -0
- ksadk/configs/global_config.py +1 -1
- ksadk/configs/settings.py +3 -3
- ksadk/connector/__init__.py +17 -0
- ksadk/connector/channel.py +477 -0
- ksadk/context_engine/capabilities.py +52 -4
- ksadk/conversations/attachment_storage.py +10 -3
- ksadk/conversations/attachments.py +16 -5
- ksadk/conversations/message_projection.py +133 -21
- ksadk/conversations/normalize.py +28 -10
- ksadk/conversations/projector.py +4 -6
- ksadk/conversations/runtime_baseline.py +37 -0
- ksadk/conversations/runtime_invocation.py +22 -4
- ksadk/conversations/runtime_observability.py +39 -10
- ksadk/conversations/runtime_payloads.py +9 -0
- ksadk/conversations/runtime_persistence.py +105 -9
- ksadk/conversations/runtime_preparation.py +42 -33
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +34 -35
- ksadk/conversations/runtime_streaming.py +33 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/adapters/_codex_items.py +16 -8
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/_langgraph_support.py +34 -0
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/events/session_event.py +2 -2
- ksadk/harness/__init__.py +14 -0
- ksadk/harness/app.py +11 -0
- ksadk/harness/artifact_store.py +213 -0
- ksadk/harness/capabilities.py +115 -0
- ksadk/harness/capability_runtime.py +237 -0
- ksadk/harness/closure_contract.py +92 -0
- ksadk/harness/compaction_record.py +122 -0
- ksadk/harness/compiler.py +284 -0
- ksadk/harness/config.py +2 -2
- ksadk/harness/conformance/__init__.py +33 -0
- ksadk/harness/conformance/contract.py +506 -0
- ksadk/harness/conformance/fixtures.py +102 -0
- ksadk/harness/context_engine.py +403 -0
- ksadk/harness/context_maintenance.py +259 -0
- ksadk/harness/context_manifest.py +188 -0
- ksadk/harness/context_tuning.py +168 -0
- ksadk/harness/draft_runtime.py +322 -0
- ksadk/harness/engine/__init__.py +40 -0
- ksadk/harness/engine/base.py +122 -0
- ksadk/harness/engine/budgets.py +108 -0
- ksadk/harness/engine/capability_declarations.py +59 -0
- ksadk/harness/engine/completion_guard.py +42 -0
- ksadk/harness/engine/context_pipeline.py +579 -0
- ksadk/harness/engine/graph_builder.py +859 -0
- ksadk/harness/engine/langgraph.py +931 -0
- ksadk/harness/engine/mcp_disclosure.py +750 -0
- ksadk/harness/engine/policy_runtime.py +70 -0
- ksadk/harness/engine/postgres_checkpointer.py +63 -0
- ksadk/harness/engine/run_control_bridge.py +80 -0
- ksadk/harness/engine/run_types.py +88 -0
- ksadk/harness/engine/skill_disclosure.py +189 -0
- ksadk/harness/engine/spans.py +41 -0
- ksadk/harness/engine/subagents.py +343 -0
- ksadk/harness/engine/thread_ids.py +112 -0
- ksadk/harness/engine/tool_dispatch.py +144 -0
- ksadk/harness/event_tree.py +212 -0
- ksadk/harness/events.py +461 -0
- ksadk/harness/execution_policy.py +94 -0
- ksadk/harness/insights.py +210 -0
- ksadk/harness/lifecycle.py +578 -0
- ksadk/harness/lifecycle_conformance.py +233 -0
- ksadk/harness/lifecycle_local_plane.py +104 -0
- ksadk/harness/loop/__init__.py +44 -0
- ksadk/harness/loop/reason.py +454 -0
- ksadk/harness/loop/tools.py +762 -0
- ksadk/harness/managed_runtime.py +884 -0
- ksadk/harness/mcp_matrix.py +474 -0
- ksadk/harness/mcp_runtime.py +471 -0
- ksadk/harness/memory_consolidation.py +157 -0
- ksadk/harness/memory_loop.py +156 -0
- ksadk/harness/memory_runtime.py +541 -0
- ksadk/harness/metrics.py +90 -0
- ksadk/harness/model_capability.py +253 -0
- ksadk/harness/model_provider.py +220 -0
- ksadk/harness/observability/__init__.py +29 -0
- ksadk/harness/observability/inspection.py +528 -0
- ksadk/harness/observability/metrics.py +167 -0
- ksadk/harness/observability/otel_exporter.py +218 -0
- ksadk/harness/prompt_cache.py +70 -0
- ksadk/harness/public_activity.py +154 -0
- ksadk/harness/readiness.py +249 -0
- ksadk/harness/reasoner.py +466 -13
- ksadk/harness/release_readiness.py +140 -0
- ksadk/harness/resource_ref.py +69 -0
- ksadk/harness/run_control.py +668 -0
- ksadk/harness/runtime.py +171 -136
- ksadk/harness/runtime_capabilities.py +158 -0
- ksadk/harness/runtime_server.py +514 -0
- ksadk/harness/sandbox_adapters.py +739 -0
- ksadk/harness/sandbox_backend.py +530 -0
- ksadk/harness/sandbox_conformance.py +288 -0
- ksadk/harness/sandbox_lease.py +77 -0
- ksadk/harness/sandbox_lease_conformance.py +259 -0
- ksadk/harness/sandbox_matrix.py +170 -0
- ksadk/harness/sandbox_reconciliation.py +140 -0
- ksadk/harness/sandbox_recovery.py +586 -0
- ksadk/harness/sandbox_recovery_conformance.py +246 -0
- ksadk/harness/session_store.py +243 -0
- ksadk/harness/skill_composition.py +212 -0
- ksadk/harness/skill_feedback.py +123 -0
- ksadk/harness/skill_matrix.py +233 -0
- ksadk/harness/skill_runtime.py +259 -0
- ksadk/harness/spec.py +332 -0
- ksadk/harness/state.py +153 -0
- ksadk/harness/strategies.py +149 -0
- ksadk/harness/subagent.py +253 -0
- ksadk/harness/tool_policy.py +131 -0
- ksadk/harness/tool_receipts.py +96 -0
- ksadk/harness/tool_reliability.py +81 -0
- ksadk/harness/tools.py +38 -13
- ksadk/harness/user_errors.py +69 -0
- ksadk/harness/working_context.py +81 -0
- ksadk/harness/working_context_patch.py +99 -0
- ksadk/identity/resolver.py +18 -0
- ksadk/interaction/__init__.py +1 -1
- ksadk/interaction/ledger.py +1 -1
- ksadk/interaction/provider.py +2 -1
- ksadk/interaction/providers/__init__.py +3 -1
- ksadk/interaction/providers/adk.py +1 -1
- ksadk/interaction/providers/codex.py +1 -1
- ksadk/interaction/providers/harness.py +50 -0
- ksadk/interaction/providers/langgraph.py +2 -1
- ksadk/kernel/__init__.py +10 -0
- ksadk/kernel/approval_presentation.py +91 -0
- ksadk/kernel/authorization.py +1 -1
- ksadk/kernel/bootstrap.py +114 -106
- ksadk/kernel/contract_fingerprints.py +1 -1
- ksadk/kernel/contracts.py +5 -0
- ksadk/kernel/control.py +32 -1
- ksadk/kernel/execution_grants.py +221 -0
- ksadk/kernel/execution_grants_memory.py +133 -0
- ksadk/kernel/execution_grants_postgres.py +217 -0
- ksadk/kernel/execution_grants_sqlite.py +209 -0
- ksadk/kernel/ingress.py +42 -29
- ksadk/kernel/mapping.py +1 -1
- ksadk/kernel/memory_store.py +24 -11
- ksadk/kernel/postgres_store.py +63 -33
- ksadk/kernel/recovery.py +78 -14
- ksadk/kernel/sql/001_agent_kernel.sql +23 -0
- ksadk/kernel/sqlite_store.py +331 -25
- ksadk/kernel/state.py +2 -3
- ksadk/kernel/store.py +72 -2
- ksadk/kernel/worker.py +144 -51
- ksadk/kernel/worker_history.py +72 -0
- ksadk/kernel/worker_identity.py +47 -0
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/coordinator.py +22 -6
- ksadk/memory/extraction.py +40 -1
- ksadk/memory/models.py +84 -5
- ksadk/memory/provider_resolver.py +8 -0
- ksadk/memory/providers/local_postgres.py +200 -0
- ksadk/memory/providers/local_sqlite.py +42 -3
- ksadk/memory/retrieval.py +189 -0
- ksadk/memory/store_adapter.py +150 -0
- ksadk/model_policy.py +2 -2
- ksadk/model_proxy/detect.py +254 -0
- ksadk/model_proxy/server.py +14 -7
- ksadk/model_proxy/transform.py +40 -2
- ksadk/plugins/__init__.py +5 -1
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +4 -2
- ksadk/plugins/bridges/codex.py +120 -13
- ksadk/plugins/bridges/dsh.py +351 -156
- ksadk/plugins/builtins.py +72 -35
- ksadk/plugins/bundle_security.py +28 -4
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/companion_artifacts.py +83 -0
- ksadk/plugins/companions.py +368 -0
- ksadk/plugins/composition.py +8 -0
- ksadk/plugins/contracts.py +119 -1
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_channels.py +156 -0
- ksadk/plugins/dsh_home.py +140 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_teams.py +105 -0
- ksadk/plugins/dsh_toolchain.py +203 -32
- ksadk/plugins/ecosystem_probe.py +6 -6
- ksadk/plugins/execution_host.py +99 -0
- ksadk/plugins/host.py +102 -39
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +23 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/client.js +19 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/index.mjs +7 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/client.js +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/index.mjs +11 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/package.json +35 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/index.mjs +13 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/index.mjs +12 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/package.json +26 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/index.mjs +25 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/tools.json +235 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +1 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +920 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/client.mjs +133 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/index.mjs +14 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +115 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
- ksadk/plugins/providers/codex.py +344 -70
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh_capabilities.py +1450 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +294 -141
- ksadk/plugins/providers/harness_delegation.py +593 -0
- ksadk/plugins/providers/harness_managed.py +456 -0
- ksadk/plugins/providers/harness_tools.py +326 -0
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/providers/shipped_dsh.py +4 -1
- ksadk/plugins/resolver.py +8 -1
- ksadk/plugins/subagent_providers/codex.py +28 -6
- ksadk/plugins/teams/__init__.py +5 -0
- ksadk/plugins/teams/api.py +405 -0
- ksadk/plugins/teams/application.py +680 -0
- ksadk/plugins/teams/artifacts.py +60 -0
- ksadk/plugins/teams/context.py +96 -0
- ksadk/plugins/teams/contracts.py +136 -0
- ksadk/plugins/teams/domain.py +1427 -0
- ksadk/plugins/teams/domain_values.py +24 -0
- ksadk/plugins/teams/errors.py +13 -0
- ksadk/plugins/teams/migration.py +311 -0
- ksadk/plugins/teams/migration_cli.py +322 -0
- ksadk/plugins/teams/postgres_store.py +138 -0
- ksadk/plugins/teams/runtime.py +777 -0
- ksadk/plugins/teams/source_projection.py +84 -0
- ksadk/plugins/teams/store.py +311 -0
- ksadk/plugins/teams/task_decisions.py +423 -0
- ksadk/plugins/teams/transport.py +91 -0
- ksadk/plugins/teams/workspaces.py +255 -0
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +182 -38
- ksadk/runners/_langgraph_state_reader.py +106 -0
- ksadk/runners/_session_identity.py +285 -0
- ksadk/runners/adk_runner.py +166 -63
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +542 -195
- ksadk/runners/patch_langchain.py +47 -0
- ksadk/runners/usage_accumulator.py +11 -3
- ksadk/runtime/_runner_adapter/stream_mapping.py +194 -20
- ksadk/runtime/adapter.py +2 -0
- ksadk/runtime/conversation_execution.py +117 -17
- ksadk/runtime/executor.py +87 -3
- ksadk/runtime/factory.py +65 -274
- ksadk/runtime/framework_adapters.py +23 -0
- ksadk/runtime/preprocessing.py +21 -5
- ksadk/runtime/runner_adapter.py +106 -18
- ksadk/runtime/skill_eval_result.py +36 -0
- ksadk/runtime/timing.py +46 -0
- ksadk/runtime/usage.py +49 -18
- ksadk/runtime_context.py +142 -2
- ksadk/sandbox/backends/e2b.py +288 -25
- ksadk/sandbox/backends/local_process.py +72 -39
- ksadk/sandbox/base.py +64 -1
- ksadk/sandbox/diagnostics.py +82 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/sandbox/local_controls.py +746 -0
- ksadk/sandbox/local_launcher.py +90 -0
- ksadk/scheduler/dispatcher.py +1 -1
- ksadk/scheduler/sqlite_store.py +18 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/invocation_identity.py +118 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/common.py +32 -3
- ksadk/server/routes/control.py +271 -52
- ksadk/server/routes/dependencies.py +16 -0
- ksadk/server/routes/kernel_ingress.py +9 -1
- ksadk/server/routes/misc.py +233 -25
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/openai_compat.py +76 -13
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/run.py +106 -35
- ksadk/server/routes/sessions.py +491 -138
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/routes/workspace.py +130 -21
- ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-DHuAWfr5.js} +10 -7
- ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
- ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-DeBkbJvI.js} +9 -9
- ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
- ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-C35w-pn1.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-BCtGGkhN.js} +1 -1
- ksadk/server/static/assets/channel-_KDifNys.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-Bx1jS-X-.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
- ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-B7nCawed.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
- ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
- ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-1nXCdsej.js} +1 -1
- ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-2vL2sAdF.js} +1 -1
- ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-B3bA05-e.js} +1 -1
- ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-BLpRy_Yx.js} +1 -1
- ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-BO_UwatH.js} +1 -1
- ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-BdNFAney.js} +1 -1
- ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-C0J5_3qM.js} +1 -1
- ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-CGt_UGeO.js} +1 -1
- ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CIRMvUM4.js} +1 -1
- ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-CIpWk_5f.js} +1 -1
- ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-CPyieXEf.js} +1 -1
- ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-D-92S-Fd.js} +1 -1
- ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-DNKuMzWc.js} +1 -1
- ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-DWfdmz9s.js} +2 -2
- ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DppE_r-D.js} +1 -1
- ksadk/server/static/assets/{dist-C71CsujO.js → dist-DyG6Ya-z.js} +1 -1
- ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-M-SrdhhZ.js} +1 -1
- ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-mqD5TZup.js} +1 -1
- ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-n3n6t_FO.js} +1 -1
- ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-qe8xjesy.js} +1 -1
- ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-t6MzE0jU.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-Dpz9_0zn.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-DcxzRwYC.js} +1 -1
- ksadk/server/static/assets/index-BMd2mucF.css +2 -0
- ksadk/server/static/assets/index-D5qyyhTH.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
- ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-mtjOi4KM.js} +1 -1
- ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-BETqsxE_.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-DPWrvs90.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-CJG2mfBP.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-4d78KiEY.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-CMD3x_U_.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +34 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/invocation_identity.py +235 -0
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/__init__.py +26 -0
- ksadk/skills/events.py +464 -0
- ksadk/skills/manifest_cache.py +263 -0
- ksadk/skills/mcp_server/__init__.py +0 -0
- ksadk/skills/mcp_server/_registry.py +33 -0
- ksadk/skills/mcp_server/_routing.py +26 -0
- ksadk/skills/mcp_server/_workspace_files.py +160 -0
- ksadk/skills/mcp_server/register.py +415 -0
- ksadk/skills/mcp_server/server.py +218 -0
- ksadk/skills/models.py +37 -4
- ksadk/skills/observability.py +132 -0
- ksadk/skills/package_store.py +261 -40
- ksadk/skills/runtime/agent.py +67 -9
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/artifacts.py +87 -0
- ksadk/skills/runtime/backends/e2b.py +460 -27
- ksadk/skills/runtime/backends/local.py +629 -62
- ksadk/skills/runtime/base.py +81 -7
- ksadk/skills/runtime/executor.py +268 -1
- ksadk/skills/runtime/loader.py +118 -5
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +49 -0
- ksadk/skills/service_client.py +167 -28
- ksadk/skills/tool_defs.py +108 -3
- ksadk/studio/api.py +810 -93
- ksadk/studio/api_catalog_routes.py +18 -0
- ksadk/studio/api_contracts.py +8 -2
- ksadk/studio/api_plugin_routes.py +562 -104
- ksadk/studio/api_resource_connections.py +221 -0
- ksadk/studio/authoring.py +12 -6
- ksadk/studio/authoring_coordinator.py +23 -16
- ksadk/studio/builder.py +88 -0
- ksadk/studio/capabilities.py +23 -6
- ksadk/studio/channel_connections.py +333 -0
- ksadk/studio/cloud.py +370 -112
- ksadk/studio/cloud_shared_web.py +638 -0
- ksadk/studio/codex_agent_service.py +130 -28
- ksadk/studio/codex_builder.py +242 -3
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +31 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +190 -26
- ksadk/studio/compatibility_report.py +12 -1
- ksadk/studio/compiler.py +88 -14
- ksadk/studio/configuration.py +182 -0
- ksadk/studio/contracts.py +165 -11
- ksadk/studio/dsh_application.py +247 -0
- ksadk/studio/dsh_capability_service.py +1374 -0
- ksadk/studio/dsh_lifecycle.py +58 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +367 -21
- ksadk/studio/entry.py +53 -0
- ksadk/studio/event_store.py +36 -5
- ksadk/studio/execution_host.py +525 -0
- ksadk/studio/framework_run.py +32 -10
- ksadk/studio/hosted_kernel.py +89 -14
- ksadk/studio/kernel_registry.py +418 -0
- ksadk/studio/kernel_sqlite_migration.py +181 -0
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +1180 -66
- ksadk/studio/model_profile_service.py +26 -11
- ksadk/studio/native_documents.py +172 -0
- ksadk/studio/plugin_composition.py +202 -24
- ksadk/studio/plugin_kernel_adapter.py +21 -106
- ksadk/studio/plugin_lifecycle.py +80 -0
- ksadk/studio/plugin_runtime.py +448 -56
- ksadk/studio/provider_recovery.py +59 -0
- ksadk/studio/recovery_page.py +70 -0
- ksadk/studio/resource_authority.py +664 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +149 -2
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_activity.py +895 -0
- ksadk/studio/run_documents.py +127 -0
- ksadk/studio/run_service.py +789 -83
- ksadk/studio/runtime_catalog.py +53 -10
- ksadk/studio/runtime_source.py +16 -8
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +32 -280
- ksadk/studio/scheduler_service.py +3 -0
- ksadk/studio/service.py +861 -120
- ksadk/studio/shared_web.py +579 -82
- ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +8 -0
- ksadk/studio/static/assets/CodeBlock-DMIf4h33-UIqo-BPW.js +44 -0
- ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-OhNwH4K9.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
- ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-g0I-I4dD.js +59 -0
- ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
- ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
- ksadk/studio/static/assets/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CLB4L11u.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BOma_Z_F.js +38 -0
- ksadk/studio/static/assets/channel-r8itPEik.js +1 -0
- ksadk/studio/static/assets/chunk-2E4U76K2-BFf_huql.js +2 -0
- ksadk/studio/static/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- ksadk/studio/static/assets/chunk-2ZTRR5NV-C2qZJila.js +2 -0
- ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
- ksadk/studio/static/assets/chunk-4HAMMTFA-DVtDP4rm.js +62 -0
- ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- ksadk/studio/static/assets/chunk-6AZGARVD-BB6FqMl-.js +1 -0
- ksadk/studio/static/assets/chunk-6EIED4P4-DdUJkP0f.js +1 -0
- ksadk/studio/static/assets/chunk-6K3QC6MW-CqVsVn-y.js +1 -0
- ksadk/studio/static/assets/chunk-6TQVIW2G-DKlLbNIP.js +1 -0
- ksadk/studio/static/assets/chunk-747NJXEK-BFkZPlab.js +2 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-BZNhM4vB.js +2 -0
- ksadk/studio/static/assets/chunk-CLGD4ZFX-D-GTtyKs.js +1 -0
- ksadk/studio/static/assets/chunk-DU6HZSFF-CpEZCUgg.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DE_8H717.js +72 -0
- ksadk/studio/static/assets/chunk-GVQU2GXP-BfEB0lNv.js +1 -0
- ksadk/studio/static/assets/chunk-I5DQTOEV-Hm2LfiYI.js +1 -0
- ksadk/studio/static/assets/chunk-ICYGCRZG-749o-pGJ.js +1 -0
- ksadk/studio/static/assets/chunk-IH6LHLGP-CC6I9F3i.js +1 -0
- ksadk/studio/static/assets/chunk-IMKFNOWR-D38axYOR.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- ksadk/studio/static/assets/chunk-KI3K4JFJ-Rma-0k_M.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Dq5xn7aL.js +1 -0
- ksadk/studio/static/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
- ksadk/studio/static/assets/chunk-OSK3NFVY-DiCQjx9b.js +10 -0
- ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-VdhKmfYq.js +1 -0
- ksadk/studio/static/assets/chunk-POPQ4Y6H-C1_rzO5M.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-B45HvflI.js +1 -0
- ksadk/studio/static/assets/chunk-SHT3W25Y-DsCFnRVE.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DljApgRX.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-DWqRtyqa.js +206 -0
- ksadk/studio/static/assets/chunk-TLUHSLCS-DUeGgnD5.js +2 -0
- ksadk/studio/static/assets/chunk-UY3FDG6J-CnmaAkG5.js +1 -0
- ksadk/studio/static/assets/chunk-XHIXRSVI-BFQ6B8BE.js +1 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
- ksadk/studio/static/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/clsx-DB0hHKMi.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-om8AY0Mc.js +1 -0
- ksadk/studio/static/assets/createLucideIcon-DR0LGTP5.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-6BrmK52S.js +62 -0
- ksadk/studio/static/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-C6aH78c4.js +30 -0
- ksadk/studio/static/assets/diagram-UQ7AKVKN-DY_tQ6C_.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-DX9p5cQT.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-DB2WSH8X.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-Ce1BJwHE.js +24 -0
- ksadk/studio/static/assets/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-CGthTMmJ.js +99 -0
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-CZ1tEenp.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BfoAZW9X.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-S985OIJF.js +106 -0
- ksadk/studio/static/assets/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
- ksadk/studio/static/assets/index-CfEnms6Y.css +2 -0
- ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
- ksadk/studio/static/assets/index.dom-BQenBtFm.js +1 -0
- ksadk/studio/static/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-CO3W8tFn.js +2 -0
- ksadk/studio/static/assets/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-BUGEl8cO.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-Ch2ZYxvr.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-Da-Fp4vC.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
- ksadk/studio/static/assets/line-BDaeq300.js +1 -0
- ksadk/studio/static/assets/linear-DmucvK78.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-Cj5mYdBi.js +4 -0
- ksadk/studio/static/assets/mindmap-definition-YA3MSWOX-CvlsVQ38.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-BuHuNgT5.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
- ksadk/studio/static/assets/pieDiagram-E7YTZNPT-DlrWiSOv.js +39 -0
- ksadk/studio/static/assets/preload-helper-CO68xz6u.js +1 -0
- ksadk/studio/static/assets/presentation-yYw7xK60-BmcZriri.js +1 -0
- ksadk/studio/static/assets/quadrantDiagram-AXDQQJYC-BA3hpUZM.js +7 -0
- ksadk/studio/static/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-BxpAazym.js +1 -0
- ksadk/studio/static/assets/requirementDiagram-BXWQKSXE-E-Ge0FcV.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-CcElXGg4.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- ksadk/studio/static/assets/src-B6xuSHsQ.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DdXZOFqY.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-CJbOM-QK.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-NtgEEHLY.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-D-AVlW8B.js +8 -0
- ksadk/studio/static/assets/timeline-definition-24CTP7MA-CIuYhNy3.js +120 -0
- ksadk/studio/static/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-7HbApbrv.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
- ksadk/studio/static/assets/wardleyDiagram-VM6X3IG4-CMJiaedy.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-BdgtMvW2.js +7 -0
- ksadk/studio/static/index.html +8 -2
- ksadk/studio/teams_catalog.py +133 -0
- ksadk/studio/teams_installation.py +214 -0
- ksadk/studio/teams_node.py +545 -0
- ksadk/studio/teams_node_runner.py +69 -0
- ksadk/studio/teams_remote.py +274 -0
- ksadk/studio/templates.py +40 -19
- ksadk/studio/validator.py +13 -0
- ksadk/studio/workspace.py +19 -4
- ksadk/studio/workspace_plugins.py +136 -0
- ksadk/studio/workspace_registry.py +286 -0
- ksadk/toolsets/__init__.py +11 -0
- ksadk/toolsets/skills.py +446 -378
- ksadk/toolsets/workspace.py +3 -3
- ksadk/toolsets/workspace_identity.py +15 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/memory_backend/providers/lancedb.py +56 -2
- ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -148
- ksadk_runtime_common/workspace_files/router.py +26 -13
- agentengine_sdk_python-0.8.3.dist-info/RECORD +0 -833
- ksadk/server/static/assets/MathMessageMarkdown-D9uB55Oh.js +0 -8
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
- ksadk/server/static/assets/dist-DdRBIceA.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
- ksadk/server/static/assets/index-B2k_urY8.js +0 -241
- ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
- ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
|
@@ -4,12 +4,11 @@ LangGraphRunner - LangGraph 框架运行时
|
|
|
4
4
|
直接透传 LangGraph 原生能力,最小化封装
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
7
|
import asyncio
|
|
10
8
|
import base64
|
|
11
9
|
import os
|
|
12
10
|
import re
|
|
11
|
+
import sqlite3
|
|
13
12
|
import uuid
|
|
14
13
|
from typing import Any, AsyncIterator, Dict, Mapping
|
|
15
14
|
|
|
@@ -17,28 +16,40 @@ from langgraph.types import Command
|
|
|
17
16
|
|
|
18
17
|
from ksadk.conversations.attachments import classify_attachment_kind, read_attachment_uri_bytes
|
|
19
18
|
from ksadk.runners._langgraph_runner_streams import _LangGraphStreamMixin
|
|
19
|
+
from ksadk.runners._langgraph_state_reader import (
|
|
20
|
+
interrupt_info_from_state,
|
|
21
|
+
known_subgraph_namespaces,
|
|
22
|
+
read_graph_state,
|
|
23
|
+
)
|
|
24
|
+
from ksadk.runners._session_identity import LangGraphSessionIdentityMixin
|
|
20
25
|
from ksadk.runners.base_runner import BaseRunner
|
|
21
26
|
from ksadk.runners.utils import load_agent_module
|
|
27
|
+
from ksadk.runtime.skill_eval_result import skill_eval_response_fields
|
|
28
|
+
from ksadk.runtime.timing import extract_timing
|
|
29
|
+
from ksadk.sessions import resolve_persistence_topology
|
|
22
30
|
from ksadk.sessions.continuity import LangGraphSessionAdapter
|
|
23
31
|
|
|
24
32
|
|
|
25
|
-
class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
33
|
+
class LangGraphRunner(LangGraphSessionIdentityMixin, _LangGraphStreamMixin, BaseRunner):
|
|
26
34
|
"""LangGraph 框架运行时
|
|
27
35
|
|
|
28
36
|
透传原生 LangGraph 功能,支持任意 State 格式
|
|
29
37
|
"""
|
|
30
38
|
|
|
31
|
-
# ToolGateway approvals can
|
|
32
|
-
#
|
|
39
|
+
# ToolGateway approvals can occur after a terminal-looking tool call, so
|
|
40
|
+
# the semantic stream must remain resumable for a follow-up decision.
|
|
33
41
|
supports_gateway_approval_semantic_resume = True
|
|
34
42
|
|
|
35
43
|
def __init__(self, detection_result: Any, project_dir: str):
|
|
36
44
|
super().__init__(detection_result, project_dir)
|
|
45
|
+
self._module: Any = None
|
|
37
46
|
self._managed_checkpoint_lock = asyncio.Lock()
|
|
38
47
|
self._managed_checkpoint_prepared = False
|
|
48
|
+
self._managed_checkpoint_state = "uninitialized"
|
|
39
49
|
self._managed_checkpoint_error: tuple[str, str] | None = None
|
|
40
50
|
self._managed_checkpoint_pool: Any = None
|
|
41
|
-
self.
|
|
51
|
+
self._identity_thread_bindings: dict[str, str] = {}
|
|
52
|
+
self._identity_thread_lock = asyncio.Lock()
|
|
42
53
|
|
|
43
54
|
def load_agent(self) -> None:
|
|
44
55
|
self._load_agent(force_reload=False)
|
|
@@ -62,86 +73,241 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
62
73
|
normalized = self.sync_process_model_env(model)
|
|
63
74
|
if normalized is None or self._agent is None:
|
|
64
75
|
return
|
|
65
|
-
|
|
66
|
-
# each model turn. Reloading it here would discard the managed
|
|
67
|
-
# PostgreSQL checkpointer that was installed asynchronously below.
|
|
68
|
-
if (
|
|
69
|
-
normalized == getattr(self, "_loaded_model_name", None)
|
|
70
|
-
or self._managed_checkpoint_pool is not None
|
|
71
|
-
):
|
|
76
|
+
if normalized == getattr(self, "_loaded_model_name", None):
|
|
72
77
|
return
|
|
73
78
|
self._load_agent(force_reload=True)
|
|
74
79
|
|
|
75
80
|
def get_session_adapter(self):
|
|
76
81
|
return LangGraphSessionAdapter()
|
|
77
82
|
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
def describe_lazy_checkpoint_capability(self) -> dict[str, Any] | None:
|
|
84
|
+
"""Describe a checkpointer created lazily by a custom runner.
|
|
85
|
+
|
|
86
|
+
Standard LangGraph runners expose the compiled graph through ``_agent``.
|
|
87
|
+
Custom runners that construct a graph per invocation can override this
|
|
88
|
+
hook so bootstrap capability discovery does not depend on a resident
|
|
89
|
+
graph object.
|
|
90
|
+
"""
|
|
91
|
+
return None
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def _checkpoint_backend_from_saver(checkpointer: Any) -> str:
|
|
95
|
+
for saver_type in type(checkpointer).__mro__:
|
|
96
|
+
qualified_name = f"{saver_type.__module__}.{saver_type.__name__}".lower()
|
|
97
|
+
if "checkpoint.postgres" in qualified_name or "postgressaver" in qualified_name:
|
|
98
|
+
return "postgres"
|
|
99
|
+
if "checkpoint.sqlite" in qualified_name or "sqlitesaver" in qualified_name:
|
|
100
|
+
return "sqlite"
|
|
101
|
+
if "checkpoint.memory" in qualified_name or saver_type.__name__.lower() in {
|
|
102
|
+
"memorysaver",
|
|
103
|
+
"inmemorysaver",
|
|
104
|
+
}:
|
|
105
|
+
return "memory"
|
|
106
|
+
return "unknown"
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def _sqlite_target_storage(database: Any) -> str:
|
|
110
|
+
target = os.fspath(database).strip() if isinstance(database, (str, os.PathLike)) else ""
|
|
111
|
+
if not target:
|
|
112
|
+
return "memory"
|
|
113
|
+
lowered = target.lower()
|
|
114
|
+
if lowered == ":memory:":
|
|
115
|
+
return "memory"
|
|
116
|
+
if lowered.startswith("file:"):
|
|
117
|
+
path, _, query = lowered.partition("?")
|
|
118
|
+
if path in {"file:", "file::memory:"} or "mode=memory" in query.split("&"):
|
|
119
|
+
return "memory"
|
|
120
|
+
return "file"
|
|
121
|
+
|
|
122
|
+
@classmethod
|
|
123
|
+
def _sqlite_checkpoint_storage(cls, checkpointer: Any) -> str:
|
|
124
|
+
connection = getattr(checkpointer, "conn", None)
|
|
125
|
+
if isinstance(connection, sqlite3.Connection):
|
|
126
|
+
try:
|
|
127
|
+
rows = connection.execute("PRAGMA database_list").fetchall()
|
|
128
|
+
except Exception:
|
|
129
|
+
return "unknown"
|
|
130
|
+
for row in rows:
|
|
131
|
+
if len(row) >= 3 and row[1] == "main":
|
|
132
|
+
return "file" if str(row[2] or "").strip() else "memory"
|
|
133
|
+
return "unknown"
|
|
134
|
+
|
|
135
|
+
# AsyncSqliteSaver keeps the original aiosqlite connector closure. Its
|
|
136
|
+
# public PRAGMA API is async, while capability discovery is synchronous,
|
|
137
|
+
# so inspect the connection target and fail closed if it is unavailable.
|
|
138
|
+
connector = getattr(connection, "_connector", None)
|
|
139
|
+
code = getattr(connector, "__code__", None)
|
|
140
|
+
closure = getattr(connector, "__closure__", None)
|
|
141
|
+
if code is None or closure is None:
|
|
142
|
+
return "unknown"
|
|
143
|
+
try:
|
|
144
|
+
closed_values = {
|
|
145
|
+
name: cell.cell_contents for name, cell in zip(code.co_freevars, closure)
|
|
146
|
+
}
|
|
147
|
+
except (AttributeError, ValueError):
|
|
148
|
+
return "unknown"
|
|
149
|
+
if "database" not in closed_values:
|
|
150
|
+
return "unknown"
|
|
151
|
+
return cls._sqlite_target_storage(closed_values["database"])
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def _checkpoint_capability_for_backend(
|
|
155
|
+
cls,
|
|
156
|
+
backend: str,
|
|
157
|
+
*,
|
|
158
|
+
checkpointer: Any = None,
|
|
159
|
+
) -> dict[str, Any]:
|
|
160
|
+
if backend == "postgres":
|
|
161
|
+
return {
|
|
162
|
+
"Supported": True,
|
|
163
|
+
"Backend": "postgres",
|
|
164
|
+
"Scope": "shared",
|
|
165
|
+
"Durable": True,
|
|
166
|
+
"SharedAcrossPods": True,
|
|
167
|
+
"ResumeMode": "time_travel",
|
|
168
|
+
"Reason": "",
|
|
169
|
+
}
|
|
170
|
+
if backend == "sqlite":
|
|
171
|
+
if checkpointer is not None:
|
|
172
|
+
storage = cls._sqlite_checkpoint_storage(checkpointer)
|
|
173
|
+
if storage != "file":
|
|
174
|
+
return {
|
|
175
|
+
"Supported": False,
|
|
176
|
+
"Backend": "sqlite",
|
|
177
|
+
"Scope": "process_local" if storage == "memory" else "unknown",
|
|
178
|
+
"Durable": False,
|
|
179
|
+
"SharedAcrossPods": False,
|
|
180
|
+
"ResumeMode": "none",
|
|
181
|
+
"ReasonCode": "CHECKPOINTER_NOT_DURABLE",
|
|
182
|
+
"Reason": (
|
|
183
|
+
"In-memory SQLite checkpoint cannot be recovered after process restart"
|
|
184
|
+
if storage == "memory"
|
|
185
|
+
else "SQLite checkpoint file target cannot be verified as durable"
|
|
186
|
+
),
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
"Supported": True,
|
|
190
|
+
"Backend": "sqlite",
|
|
191
|
+
"Scope": "pod_local",
|
|
192
|
+
"Durable": True,
|
|
193
|
+
"SharedAcrossPods": False,
|
|
194
|
+
"ResumeMode": "time_travel",
|
|
195
|
+
"Reason": (
|
|
196
|
+
"SQLite checkpoint is durable for local web debugging "
|
|
197
|
+
"but is not shared across pods"
|
|
198
|
+
),
|
|
199
|
+
}
|
|
200
|
+
if backend == "memory":
|
|
85
201
|
return {
|
|
86
202
|
"Supported": False,
|
|
87
|
-
"Backend": "
|
|
88
|
-
"Scope": "
|
|
203
|
+
"Backend": "memory",
|
|
204
|
+
"Scope": "process_local",
|
|
89
205
|
"Durable": False,
|
|
90
206
|
"SharedAcrossPods": False,
|
|
91
207
|
"ResumeMode": "none",
|
|
92
|
-
|
|
93
|
-
"Reason":
|
|
208
|
+
"ReasonCode": "CHECKPOINTER_NOT_DURABLE",
|
|
209
|
+
"Reason": (
|
|
210
|
+
"In-memory checkpoint cannot be recovered after process restart or across pods"
|
|
211
|
+
),
|
|
94
212
|
}
|
|
213
|
+
return {
|
|
214
|
+
"Supported": False,
|
|
215
|
+
"Backend": "unknown",
|
|
216
|
+
"Scope": "unknown",
|
|
217
|
+
"Durable": False,
|
|
218
|
+
"SharedAcrossPods": False,
|
|
219
|
+
"ResumeMode": "none",
|
|
220
|
+
"ReasonCode": "CHECKPOINTER_NOT_DURABLE",
|
|
221
|
+
"Reason": "LangGraph checkpointer backend is not recognized as durable",
|
|
222
|
+
}
|
|
95
223
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
224
|
+
@staticmethod
|
|
225
|
+
def _invalid_lazy_checkpoint_capability(
|
|
226
|
+
capability: Mapping[str, Any] | None = None,
|
|
227
|
+
) -> dict[str, Any]:
|
|
228
|
+
source = capability or {}
|
|
229
|
+
return {
|
|
230
|
+
"Supported": False,
|
|
231
|
+
"Backend": str(source.get("Backend") or "unknown").strip().lower(),
|
|
232
|
+
"Scope": str(source.get("Scope") or "unknown").strip().lower(),
|
|
233
|
+
"Durable": bool(source.get("Durable")),
|
|
234
|
+
"SharedAcrossPods": bool(source.get("SharedAcrossPods")),
|
|
235
|
+
"ResumeMode": "none",
|
|
236
|
+
"ReasonCode": "CHECKPOINTER_NOT_DURABLE",
|
|
237
|
+
"Reason": "Lazy LangGraph checkpoint capability is invalid or not durably resumable",
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@classmethod
|
|
241
|
+
def _normalize_lazy_checkpoint_capability(cls, capability: Any) -> dict[str, Any]:
|
|
242
|
+
if not isinstance(capability, Mapping):
|
|
243
|
+
return cls._invalid_lazy_checkpoint_capability()
|
|
244
|
+
|
|
245
|
+
backend = str(capability.get("Backend") or "unknown").strip().lower()
|
|
246
|
+
scope = str(capability.get("Scope") or "unknown").strip().lower()
|
|
247
|
+
durable = capability.get("Durable") is True
|
|
248
|
+
shared = capability.get("SharedAcrossPods") is True
|
|
249
|
+
resume_mode = str(capability.get("ResumeMode") or "none").strip().lower()
|
|
250
|
+
supported = capability.get("Supported") is True
|
|
251
|
+
|
|
252
|
+
if supported:
|
|
253
|
+
valid = (
|
|
254
|
+
durable
|
|
255
|
+
and resume_mode == "time_travel"
|
|
256
|
+
and (
|
|
257
|
+
(backend == "postgres" and scope == "shared" and shared)
|
|
258
|
+
or (backend == "sqlite" and scope == "pod_local" and not shared)
|
|
259
|
+
)
|
|
120
260
|
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
scope = "process_local"
|
|
124
|
-
durable = False
|
|
125
|
-
shared = False
|
|
126
|
-
reason = "In-memory checkpoint cannot be recovered after process restart or across pods"
|
|
261
|
+
if not valid:
|
|
262
|
+
return cls._invalid_lazy_checkpoint_capability(capability)
|
|
127
263
|
|
|
128
264
|
return {
|
|
129
|
-
|
|
130
|
-
# is not a native durable-resume capability in a hosted runtime.
|
|
131
|
-
"Supported": backend not in {"memory", "inmemory", "unknown", ""},
|
|
265
|
+
"Supported": supported,
|
|
132
266
|
"Backend": backend,
|
|
133
267
|
"Scope": scope,
|
|
134
268
|
"Durable": durable,
|
|
135
269
|
"SharedAcrossPods": shared,
|
|
136
|
-
"ResumeMode":
|
|
137
|
-
|
|
138
|
-
{"ReasonCode": "CHECKPOINTER_NOT_DURABLE"}
|
|
139
|
-
if backend in {"memory", "inmemory", "unknown", ""}
|
|
140
|
-
else {}
|
|
141
|
-
),
|
|
142
|
-
"Reason": reason,
|
|
270
|
+
"ResumeMode": resume_mode if supported else "none",
|
|
271
|
+
"Reason": str(capability.get("Reason") or "").strip(),
|
|
143
272
|
}
|
|
144
273
|
|
|
274
|
+
def describe_checkpoint_capability(self) -> dict[str, Any]:
|
|
275
|
+
agent = getattr(self, "_agent", None)
|
|
276
|
+
checkpointer = getattr(agent, "checkpointer", None)
|
|
277
|
+
if checkpointer is None:
|
|
278
|
+
checkpointer = getattr(agent, "_checkpointer", None)
|
|
279
|
+
if checkpointer is None:
|
|
280
|
+
lazy_capability = self.describe_lazy_checkpoint_capability()
|
|
281
|
+
if lazy_capability is not None:
|
|
282
|
+
return self._normalize_lazy_checkpoint_capability(lazy_capability)
|
|
283
|
+
if self._managed_checkpoint_error is not None:
|
|
284
|
+
reason_code, reason = self._managed_checkpoint_error
|
|
285
|
+
return {
|
|
286
|
+
"Supported": False,
|
|
287
|
+
"Backend": "postgres",
|
|
288
|
+
"Scope": "unknown",
|
|
289
|
+
"Durable": False,
|
|
290
|
+
"SharedAcrossPods": False,
|
|
291
|
+
"ResumeMode": "none",
|
|
292
|
+
"ReasonCode": reason_code,
|
|
293
|
+
"Reason": reason,
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
"Supported": False,
|
|
297
|
+
"Backend": "none",
|
|
298
|
+
"Scope": "unknown",
|
|
299
|
+
"Durable": False,
|
|
300
|
+
"SharedAcrossPods": False,
|
|
301
|
+
"ReasonCode": "CHECKPOINTER_NOT_DURABLE",
|
|
302
|
+
"Reason": "LangGraph graph has no configured checkpointer",
|
|
303
|
+
}
|
|
304
|
+
backend = self._checkpoint_backend_from_saver(checkpointer)
|
|
305
|
+
if backend == "unknown":
|
|
306
|
+
configured_backend = str(os.getenv("KSADK_CHECKPOINT_BACKEND") or "").strip().lower()
|
|
307
|
+
if configured_backend in {"postgres", "sqlite", "memory"}:
|
|
308
|
+
backend = configured_backend
|
|
309
|
+
return self._checkpoint_capability_for_backend(backend, checkpointer=checkpointer)
|
|
310
|
+
|
|
145
311
|
def get_runtime_capabilities(self) -> dict[str, Any]:
|
|
146
312
|
capabilities = super().get_runtime_capabilities()
|
|
147
313
|
capabilities["model_call_boundaries"] = True
|
|
@@ -158,36 +324,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
158
324
|
}
|
|
159
325
|
return capabilities
|
|
160
326
|
|
|
161
|
-
@staticmethod
|
|
162
|
-
def _checkpoint_backend_from_saver(checkpointer: Any) -> str:
|
|
163
|
-
if checkpointer is None:
|
|
164
|
-
return "unknown"
|
|
165
|
-
for saver_type in type(checkpointer).__mro__:
|
|
166
|
-
qualified_name = f"{saver_type.__module__}.{saver_type.__name__}".lower()
|
|
167
|
-
if "checkpoint.postgres" in qualified_name or "postgressaver" in qualified_name:
|
|
168
|
-
return "postgres"
|
|
169
|
-
if "checkpoint.sqlite" in qualified_name or "sqlitesaver" in qualified_name:
|
|
170
|
-
return "sqlite"
|
|
171
|
-
if "checkpoint.memory" in qualified_name or saver_type.__name__.lower() in {
|
|
172
|
-
"memorysaver",
|
|
173
|
-
"inmemorysaver",
|
|
174
|
-
}:
|
|
175
|
-
return "memory"
|
|
176
|
-
return "unknown"
|
|
177
|
-
|
|
178
327
|
@staticmethod
|
|
179
328
|
def _env_flag(name: str) -> bool:
|
|
180
|
-
return str(os.getenv(name) or "").strip().lower() in {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return session_namespace
|
|
187
|
-
agent_id = str(
|
|
188
|
-
os.getenv("AGENTENGINE_AGENT_ID") or os.getenv("KSADK_AGENT_ID") or "default"
|
|
189
|
-
).strip()
|
|
190
|
-
return f"agent:{agent_id}"
|
|
329
|
+
return str(os.getenv(name) or "").strip().lower() in {
|
|
330
|
+
"1",
|
|
331
|
+
"true",
|
|
332
|
+
"yes",
|
|
333
|
+
"on",
|
|
334
|
+
}
|
|
191
335
|
|
|
192
336
|
async def _create_managed_postgres_saver(self, dsn: str) -> tuple[Any, Any]:
|
|
193
337
|
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
|
|
@@ -217,36 +361,160 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
217
361
|
raise
|
|
218
362
|
|
|
219
363
|
async def prepare_runtime_capabilities(self) -> None:
|
|
220
|
-
|
|
364
|
+
await self._prepare_managed_checkpoint(allow_transient_retry=False)
|
|
365
|
+
|
|
366
|
+
async def refresh_runtime_capabilities(self) -> None:
|
|
367
|
+
await self._prepare_managed_checkpoint(allow_transient_retry=True)
|
|
368
|
+
|
|
369
|
+
async def attach_runtime_handle(self, handle: Any) -> bool:
|
|
370
|
+
"""Validate a persisted LangGraph checkpoint handle for Runtime v2.
|
|
221
371
|
|
|
222
|
-
The graph
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
and capability discovery honestly reports why native resume is absent.
|
|
372
|
+
The concrete graph resolves the checkpoint during its native resume
|
|
373
|
+
call. Attachment verifies the durable backend and the complete native
|
|
374
|
+
address without fabricating process-local ownership.
|
|
226
375
|
"""
|
|
227
|
-
|
|
376
|
+
|
|
377
|
+
if str(getattr(handle, "runtime_type", "") or "").strip().lower() != "langgraph":
|
|
378
|
+
return False
|
|
379
|
+
native_ref = getattr(handle, "native_ref", None)
|
|
380
|
+
if not isinstance(native_ref, Mapping):
|
|
381
|
+
return False
|
|
382
|
+
framework_ref = native_ref.get("framework_ref")
|
|
383
|
+
langgraph_ref = (
|
|
384
|
+
framework_ref.get("langgraph") if isinstance(framework_ref, Mapping) else None
|
|
385
|
+
)
|
|
386
|
+
checkpoint_id = str(
|
|
387
|
+
native_ref.get("checkpoint_id")
|
|
388
|
+
or (langgraph_ref.get("checkpoint_id") if isinstance(langgraph_ref, Mapping) else "")
|
|
389
|
+
or ""
|
|
390
|
+
).strip()
|
|
391
|
+
thread_id = str(
|
|
392
|
+
native_ref.get("thread_id")
|
|
393
|
+
or (langgraph_ref.get("thread_id") if isinstance(langgraph_ref, Mapping) else "")
|
|
394
|
+
or ""
|
|
395
|
+
).strip()
|
|
396
|
+
if not checkpoint_id or not thread_id:
|
|
397
|
+
return False
|
|
398
|
+
|
|
399
|
+
await self.prepare_runtime_capabilities()
|
|
400
|
+
capability = self.describe_checkpoint_capability()
|
|
401
|
+
if not bool(
|
|
402
|
+
capability.get("Supported")
|
|
403
|
+
and capability.get("Durable")
|
|
404
|
+
and capability.get("SharedAcrossPods")
|
|
405
|
+
):
|
|
406
|
+
return False
|
|
407
|
+
|
|
408
|
+
configurable = {
|
|
409
|
+
"thread_id": thread_id,
|
|
410
|
+
"checkpoint_id": checkpoint_id,
|
|
411
|
+
}
|
|
412
|
+
checkpoint_ns = str(
|
|
413
|
+
native_ref.get("checkpoint_ns")
|
|
414
|
+
or (langgraph_ref.get("checkpoint_ns") if isinstance(langgraph_ref, Mapping) else "")
|
|
415
|
+
or ""
|
|
416
|
+
).strip()
|
|
417
|
+
if checkpoint_ns:
|
|
418
|
+
configurable["checkpoint_ns"] = checkpoint_ns
|
|
419
|
+
config = {"configurable": configurable}
|
|
420
|
+
|
|
421
|
+
if callable(
|
|
422
|
+
getattr(self._agent, "aget_state", None) or getattr(self._agent, "get_state", None)
|
|
423
|
+
):
|
|
424
|
+
return await self._checkpoint_state_resolves(
|
|
425
|
+
config,
|
|
426
|
+
thread_id=thread_id,
|
|
427
|
+
checkpoint_id=checkpoint_id,
|
|
428
|
+
checkpoint_ns=checkpoint_ns,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
with_graph = getattr(self, "_with_graph", None)
|
|
432
|
+
if not callable(with_graph):
|
|
433
|
+
return False
|
|
434
|
+
|
|
435
|
+
async def validate_lazy_graph() -> bool:
|
|
436
|
+
return await self._checkpoint_state_resolves(
|
|
437
|
+
config,
|
|
438
|
+
thread_id=thread_id,
|
|
439
|
+
checkpoint_id=checkpoint_id,
|
|
440
|
+
checkpoint_ns=checkpoint_ns,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
return bool(await with_graph(validate_lazy_graph))
|
|
444
|
+
|
|
445
|
+
async def _checkpoint_state_resolves(
|
|
446
|
+
self,
|
|
447
|
+
config: Mapping[str, Any],
|
|
448
|
+
*,
|
|
449
|
+
thread_id: str,
|
|
450
|
+
checkpoint_id: str,
|
|
451
|
+
checkpoint_ns: str,
|
|
452
|
+
) -> bool:
|
|
453
|
+
"""Confirm one exact persisted checkpoint through the active graph."""
|
|
454
|
+
|
|
455
|
+
state, _error = await self._read_graph_state(config)
|
|
456
|
+
if state is None:
|
|
457
|
+
return False
|
|
458
|
+
state_created_at = (
|
|
459
|
+
state.get("created_at")
|
|
460
|
+
if isinstance(state, Mapping)
|
|
461
|
+
else getattr(state, "created_at", None)
|
|
462
|
+
)
|
|
463
|
+
state_metadata = (
|
|
464
|
+
state.get("metadata")
|
|
465
|
+
if isinstance(state, Mapping)
|
|
466
|
+
else getattr(state, "metadata", None)
|
|
467
|
+
)
|
|
468
|
+
if state_created_at is None and state_metadata is None:
|
|
469
|
+
return False
|
|
470
|
+
resolved_ref = self._checkpoint_ref_from_state(state).get("langgraph", {})
|
|
471
|
+
if not isinstance(resolved_ref, Mapping):
|
|
472
|
+
return False
|
|
473
|
+
if str(resolved_ref.get("thread_id") or "").strip() != thread_id:
|
|
474
|
+
return False
|
|
475
|
+
if str(resolved_ref.get("checkpoint_id") or "").strip() != checkpoint_id:
|
|
476
|
+
return False
|
|
477
|
+
if checkpoint_ns and str(resolved_ref.get("checkpoint_ns") or "").strip() != checkpoint_ns:
|
|
478
|
+
return False
|
|
479
|
+
return True
|
|
480
|
+
|
|
481
|
+
async def _prepare_managed_checkpoint(self, *, allow_transient_retry: bool) -> None:
|
|
482
|
+
if self._managed_checkpoint_state in {"ready", "terminal_failure"}:
|
|
483
|
+
return
|
|
484
|
+
if self._managed_checkpoint_state == "transient_failure" and not allow_transient_retry:
|
|
228
485
|
return
|
|
229
486
|
async with self._managed_checkpoint_lock:
|
|
230
|
-
if self.
|
|
487
|
+
if self._managed_checkpoint_state in {"ready", "terminal_failure"}:
|
|
488
|
+
return
|
|
489
|
+
if self._managed_checkpoint_state == "transient_failure" and not allow_transient_retry:
|
|
231
490
|
return
|
|
232
491
|
|
|
233
492
|
checkpointer = getattr(self._agent, "checkpointer", None)
|
|
234
493
|
if checkpointer is None:
|
|
235
494
|
checkpointer = getattr(self._agent, "_checkpointer", None)
|
|
236
495
|
if self._checkpoint_backend_from_saver(checkpointer) == "postgres":
|
|
237
|
-
self._managed_checkpoint_namespace = self._resolve_checkpoint_namespace()
|
|
238
496
|
self._managed_checkpoint_prepared = True
|
|
497
|
+
self._managed_checkpoint_state = "ready"
|
|
239
498
|
return
|
|
240
499
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
500
|
+
auto_enabled = self._env_flag("KSADK_LANGGRAPH_AUTO_CHECKPOINT")
|
|
501
|
+
checkpoint_target = resolve_persistence_topology(framework="langgraph").checkpoint
|
|
502
|
+
if (
|
|
503
|
+
not auto_enabled
|
|
504
|
+
or checkpoint_target.backend != "postgres"
|
|
505
|
+
or not checkpoint_target.dsn
|
|
506
|
+
):
|
|
247
507
|
self._managed_checkpoint_prepared = True
|
|
508
|
+
self._managed_checkpoint_state = "terminal_failure"
|
|
248
509
|
return
|
|
249
510
|
|
|
511
|
+
# 探测路径可能先于首个 chat 请求 probe(本地调试与手动部署形态的
|
|
512
|
+
# capability adapter 均未 preflight)。此时驻留图还没加载,先完成
|
|
513
|
+
# 模块加载:既避免把"未加载"误判为"无 durable checkpointer",
|
|
514
|
+
# 也避免对未初始化的 _module 抛 AttributeError 被静默吞掉。
|
|
515
|
+
if self._agent is None:
|
|
516
|
+
self.load_agent()
|
|
517
|
+
|
|
250
518
|
factory = getattr(self._module, "ksadk_graph_factory", None)
|
|
251
519
|
if not callable(factory):
|
|
252
520
|
self._managed_checkpoint_error = (
|
|
@@ -255,37 +523,78 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
255
523
|
"ksadk_graph_factory(*, checkpointer) for managed PostgreSQL checkpoints",
|
|
256
524
|
)
|
|
257
525
|
self._managed_checkpoint_prepared = True
|
|
526
|
+
self._managed_checkpoint_state = "terminal_failure"
|
|
527
|
+
return
|
|
528
|
+
|
|
529
|
+
# 托管 checkpointer 从 checkpoint 恢复 messages(append-only reducer)。
|
|
530
|
+
# 若接入方未导出 ksadk_prepare_state,runner 走 _to_state 把 history 再注入
|
|
531
|
+
# 一遍,与 checkpointer 恢复的 messages 双重叠加。托管 checkpoint 必须同时
|
|
532
|
+
# 提供 hook,否则 fail-closed,避免生产 auto checkpoint 下静默双重注入。
|
|
533
|
+
prepare_state_hook = getattr(self._module, "ksadk_prepare_state", None)
|
|
534
|
+
if not callable(prepare_state_hook):
|
|
535
|
+
self._managed_checkpoint_error = (
|
|
536
|
+
"PREPARE_STATE_HOOK_REQUIRED",
|
|
537
|
+
"Managed PostgreSQL checkpoint requires ksadk_prepare_state hook to "
|
|
538
|
+
"avoid double history injection (checkpointer messages restore + "
|
|
539
|
+
"_to_state history). Export ksadk_prepare_state(payload, "
|
|
540
|
+
"session_context) in the agent module.",
|
|
541
|
+
)
|
|
542
|
+
self._managed_checkpoint_prepared = True
|
|
543
|
+
self._managed_checkpoint_state = "terminal_failure"
|
|
258
544
|
return
|
|
259
545
|
|
|
260
546
|
pool = None
|
|
261
547
|
try:
|
|
262
|
-
saver, pool = await self._create_managed_postgres_saver(dsn)
|
|
548
|
+
saver, pool = await self._create_managed_postgres_saver(checkpoint_target.dsn)
|
|
263
549
|
managed_graph = factory(checkpointer=saver)
|
|
264
550
|
if not callable(getattr(managed_graph, "invoke", None)):
|
|
265
551
|
raise TypeError("ksadk_graph_factory must return a compiled LangGraph graph")
|
|
266
552
|
self._agent = managed_graph
|
|
267
553
|
self._managed_checkpoint_pool = pool
|
|
268
|
-
self._managed_checkpoint_namespace = self._resolve_checkpoint_namespace()
|
|
269
554
|
self._managed_checkpoint_error = None
|
|
555
|
+
self._managed_checkpoint_state = "ready"
|
|
270
556
|
except (ModuleNotFoundError, ImportError):
|
|
271
557
|
self._managed_checkpoint_error = (
|
|
272
558
|
"DEPENDENCY_MISSING",
|
|
273
559
|
"langgraph-checkpoint-postgres and psycopg are required "
|
|
274
560
|
"for managed checkpoints",
|
|
275
561
|
)
|
|
276
|
-
|
|
562
|
+
self._managed_checkpoint_state = "terminal_failure"
|
|
563
|
+
except Exception as exc:
|
|
277
564
|
error_name = type(exc).__name__.lower()
|
|
565
|
+
authentication_failure = any(
|
|
566
|
+
marker in error_name
|
|
567
|
+
for marker in ("password", "authentication", "authorization")
|
|
568
|
+
)
|
|
569
|
+
permission_failure = any(
|
|
570
|
+
marker in error_name for marker in ("privilege", "permission")
|
|
571
|
+
)
|
|
572
|
+
terminal = (
|
|
573
|
+
authentication_failure
|
|
574
|
+
or permission_failure
|
|
575
|
+
or isinstance(exc, (TypeError, ValueError))
|
|
576
|
+
)
|
|
577
|
+
reason_code = (
|
|
578
|
+
"AUTH_FAILED"
|
|
579
|
+
if authentication_failure
|
|
580
|
+
else "SCHEMA_PERMISSION_DENIED"
|
|
581
|
+
if permission_failure
|
|
582
|
+
else "CHECKPOINTER_NOT_DURABLE"
|
|
583
|
+
if terminal
|
|
584
|
+
else "CHECKPOINT_STORE_UNREACHABLE"
|
|
585
|
+
)
|
|
278
586
|
self._managed_checkpoint_error = (
|
|
279
|
-
|
|
280
|
-
if "privilege" in error_name or "permission" in error_name
|
|
281
|
-
else "DB_UNREACHABLE",
|
|
587
|
+
reason_code,
|
|
282
588
|
"Managed LangGraph PostgreSQL checkpointer initialization failed",
|
|
283
589
|
)
|
|
590
|
+
self._managed_checkpoint_state = (
|
|
591
|
+
"terminal_failure" if terminal else "transient_failure"
|
|
592
|
+
)
|
|
284
593
|
finally:
|
|
285
594
|
if pool is not None and self._managed_checkpoint_pool is None:
|
|
286
595
|
try:
|
|
287
596
|
await pool.close()
|
|
288
|
-
except Exception:
|
|
597
|
+
except Exception:
|
|
289
598
|
pass
|
|
290
599
|
self._managed_checkpoint_prepared = True
|
|
291
600
|
|
|
@@ -297,11 +606,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
297
606
|
await super().close()
|
|
298
607
|
|
|
299
608
|
def _get_config(self, session_id: str) -> dict:
|
|
300
|
-
"""获取运行配置
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
609
|
+
"""获取运行配置
|
|
610
|
+
|
|
611
|
+
只写 thread_id:checkpoint_ns 是 LangGraph 的子图寻址字段,不是租户
|
|
612
|
+
隔离字段。把租户/agent scope 塞进 configurable.checkpoint_ns 会让
|
|
613
|
+
Pregel 的 aget_state 走子图重定向并抛 "Subgraph <scope> not found",
|
|
614
|
+
静默打掉流式路径的待审批探测。租户隔离由 thread_id 承担。
|
|
615
|
+
"""
|
|
616
|
+
return {"configurable": {"thread_id": session_id}}
|
|
305
617
|
|
|
306
618
|
@staticmethod
|
|
307
619
|
def _extract_langgraph_checkpoint_ref(payload: Dict[str, Any]) -> dict[str, Any]:
|
|
@@ -313,19 +625,28 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
313
625
|
return {}
|
|
314
626
|
return dict(langgraph_ref)
|
|
315
627
|
|
|
316
|
-
|
|
628
|
+
def _known_subgraph_namespaces(self) -> set[str]:
|
|
629
|
+
"""当前图里真实存在的子图 namespace 集合(无法探测时返回空集)。"""
|
|
630
|
+
return known_subgraph_namespaces(self._agent)
|
|
631
|
+
|
|
317
632
|
def _apply_checkpoint_resume_config(
|
|
318
|
-
|
|
633
|
+
self,
|
|
319
634
|
config: dict[str, Any],
|
|
320
635
|
*,
|
|
321
636
|
session_id: str,
|
|
322
637
|
checkpoint_ref: dict[str, Any],
|
|
638
|
+
enforce_bound_thread: bool = False,
|
|
323
639
|
) -> dict[str, Any]:
|
|
324
640
|
checkpoint_id = str(checkpoint_ref.get("checkpoint_id") or "").strip()
|
|
325
641
|
if not checkpoint_id:
|
|
326
642
|
raise ValueError("checkpoint_resume requires framework_ref.langgraph.checkpoint_id")
|
|
327
643
|
|
|
328
|
-
|
|
644
|
+
configured = dict(config.get("configurable") or {})
|
|
645
|
+
bound_thread_id = str(configured.get("thread_id") or session_id or "").strip()
|
|
646
|
+
requested_thread_id = str(checkpoint_ref.get("thread_id") or "").strip()
|
|
647
|
+
if enforce_bound_thread and requested_thread_id and requested_thread_id != bound_thread_id:
|
|
648
|
+
raise ValueError("checkpoint_resume thread does not belong to this session")
|
|
649
|
+
thread_id = requested_thread_id or bound_thread_id
|
|
329
650
|
if not thread_id:
|
|
330
651
|
raise ValueError(
|
|
331
652
|
"checkpoint_resume requires session_id or framework_ref.langgraph.thread_id"
|
|
@@ -334,11 +655,57 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
334
655
|
next_config = dict(config)
|
|
335
656
|
configurable = dict(next_config.get("configurable") or {})
|
|
336
657
|
configurable["thread_id"] = thread_id
|
|
337
|
-
|
|
658
|
+
# checkpoint_ns 只承载 LangGraph 子图寻址语义。真实运行时 namespace 的
|
|
659
|
+
# 格式是 "<子图名>:<task_path>"(如 inner:<task-id>),get_subgraphs()
|
|
660
|
+
# 返回的是裸子图名——所以校验必须只比对首段,合法时保留原始完整
|
|
661
|
+
# namespace(带任务路径;否则 aget_state 定位不到对应 checkpoint)。
|
|
662
|
+
# 不匹配的地址(含历史租户/agent scope 残留)显性报错,绝不静默改写
|
|
663
|
+
# 成根地址——静默改写曾让恢复悄悄指向不存在的 checkpoint。
|
|
664
|
+
requested_namespace = str(checkpoint_ref.get("checkpoint_ns") or "").strip()
|
|
665
|
+
if requested_namespace:
|
|
666
|
+
known = self._known_subgraph_namespaces()
|
|
667
|
+
leading = requested_namespace.split(":", 1)[0]
|
|
668
|
+
if leading not in known:
|
|
669
|
+
raise ValueError(
|
|
670
|
+
"checkpoint_resume checkpoint_ns does not address any subgraph "
|
|
671
|
+
f"of this graph: {requested_namespace!r} "
|
|
672
|
+
f"(known subgraphs: {sorted(known) or 'none'})"
|
|
673
|
+
)
|
|
674
|
+
configurable["checkpoint_ns"] = requested_namespace
|
|
338
675
|
configurable["checkpoint_id"] = checkpoint_id
|
|
339
676
|
next_config["configurable"] = configurable
|
|
340
677
|
return next_config
|
|
341
678
|
|
|
679
|
+
@staticmethod
|
|
680
|
+
def _unwrap_resume_value(resume_value: Any) -> Any:
|
|
681
|
+
"""从 ksadk_resume 包装中提取实际 resume value。
|
|
682
|
+
|
|
683
|
+
KsADK 的 ksadk_resume 协议把用户决策包在 ``{"type":"ksadk_resume",
|
|
684
|
+
"interrupt_id":..., "value":{...}}`` 里,但 ``Command(resume=...)``
|
|
685
|
+
期望直接收到框架能识别的值(如 HumanInTheLoopMiddleware 的
|
|
686
|
+
``{"decisions":[...]}``)。这里拆掉外层包装,把 ``value`` 内容
|
|
687
|
+
作为 resume value 返回。有 interrupt_id 时保留原生 {id: value} 定向
|
|
688
|
+
恢复语义,避免并行 interrupt 丢失目标;无 ID 时保留单 interrupt 值路径。
|
|
689
|
+
|
|
690
|
+
非 ksadk_resume 类型(mcp_approval_response 等)原样返回,保持
|
|
691
|
+
既有内置工具审批路径不变;ToolGateway 走 semantic resume 分支,
|
|
692
|
+
不经过此处。
|
|
693
|
+
"""
|
|
694
|
+
if isinstance(resume_value, Mapping):
|
|
695
|
+
item_type = str(resume_value.get("type") or "").strip()
|
|
696
|
+
if item_type in {"ksadk_resume", "ksadk.approval_response"}:
|
|
697
|
+
inner = resume_value.get("value")
|
|
698
|
+
if inner is not None:
|
|
699
|
+
interrupt_id = str(
|
|
700
|
+
resume_value.get("interrupt_id")
|
|
701
|
+
or resume_value.get("approval_request_id")
|
|
702
|
+
or resume_value.get("id")
|
|
703
|
+
or ""
|
|
704
|
+
).strip()
|
|
705
|
+
# Parallel graph tasks must receive only their own decision.
|
|
706
|
+
return {interrupt_id: inner} if interrupt_id else inner
|
|
707
|
+
return resume_value
|
|
708
|
+
|
|
342
709
|
@staticmethod
|
|
343
710
|
def _checkpoint_resume_input(
|
|
344
711
|
value: Any,
|
|
@@ -353,14 +720,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
353
720
|
|
|
354
721
|
@staticmethod
|
|
355
722
|
def _is_gateway_approval_semantic_resume(value: Any) -> bool:
|
|
356
|
-
"""
|
|
357
|
-
|
|
358
|
-
Native LangGraph ``interrupt()`` values must keep using
|
|
359
|
-
``Command(resume=...)``. In contrast, a ToolGateway can return an
|
|
360
|
-
``approval_required`` result from an otherwise normal tool call; the
|
|
361
|
-
graph then reaches its terminal node before KsADK shows the approval
|
|
362
|
-
card. Its approved tool result needs a new semantic graph turn.
|
|
363
|
-
"""
|
|
723
|
+
"""Return whether a completed ToolGateway approval needs a fresh turn."""
|
|
364
724
|
|
|
365
725
|
return bool(
|
|
366
726
|
isinstance(value, Mapping)
|
|
@@ -370,13 +730,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
370
730
|
|
|
371
731
|
@staticmethod
|
|
372
732
|
def _gateway_approval_follow_up_input() -> str:
|
|
373
|
-
"""
|
|
374
|
-
|
|
375
|
-
The actual approval response and durable tool result are already in
|
|
376
|
-
the session history. Do not repeat their contents here: project hooks
|
|
377
|
-
commonly route by input keywords, and copying a workspace path back
|
|
378
|
-
into a synthetic user message can accidentally trigger another tool.
|
|
379
|
-
"""
|
|
733
|
+
"""Build the neutral prompt used after an approved terminal tool call."""
|
|
380
734
|
|
|
381
735
|
return (
|
|
382
736
|
"系统已完成此前获批的操作。请基于会话记录中的真实结果,直接向用户说明完成情况;"
|
|
@@ -422,13 +776,8 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
422
776
|
}
|
|
423
777
|
|
|
424
778
|
async def _latest_checkpoint_metadata(self, config: dict[str, Any]) -> dict[str, Any]:
|
|
425
|
-
state =
|
|
426
|
-
|
|
427
|
-
if callable(getattr(self._agent, "aget_state", None)):
|
|
428
|
-
state = await self._agent.aget_state(config)
|
|
429
|
-
elif callable(getattr(self._agent, "get_state", None)):
|
|
430
|
-
state = self._agent.get_state(config)
|
|
431
|
-
except Exception:
|
|
779
|
+
state, _error = await self._read_graph_state(config)
|
|
780
|
+
if state is None:
|
|
432
781
|
return {}
|
|
433
782
|
framework_ref = self._checkpoint_ref_from_state(state)
|
|
434
783
|
if not framework_ref:
|
|
@@ -464,13 +813,8 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
464
813
|
}
|
|
465
814
|
|
|
466
815
|
async def _latest_state_usage(self, config: dict[str, Any]) -> dict[str, Any]:
|
|
467
|
-
state =
|
|
468
|
-
|
|
469
|
-
if callable(getattr(self._agent, "aget_state", None)):
|
|
470
|
-
state = await self._agent.aget_state(config)
|
|
471
|
-
elif callable(getattr(self._agent, "get_state", None)):
|
|
472
|
-
state = self._agent.get_state(config)
|
|
473
|
-
except Exception:
|
|
816
|
+
state, _error = await self._read_graph_state(config)
|
|
817
|
+
if state is None:
|
|
474
818
|
return {}
|
|
475
819
|
values = getattr(state, "values", None)
|
|
476
820
|
if values is not None:
|
|
@@ -759,10 +1103,15 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
759
1103
|
final_metadata = final_chunk.get("metadata")
|
|
760
1104
|
if isinstance(final_metadata, Mapping):
|
|
761
1105
|
metadata = {**dict(final_metadata), **metadata}
|
|
762
|
-
result: dict[str, Any] = {
|
|
1106
|
+
result: dict[str, Any] = {
|
|
1107
|
+
"output": output_text, "raw": {"chunks": chunks},
|
|
1108
|
+
**skill_eval_response_fields(final_chunk),
|
|
1109
|
+
}
|
|
763
1110
|
usage = final_chunk.get("usage")
|
|
764
1111
|
if isinstance(usage, Mapping) and usage:
|
|
765
1112
|
result["usage"] = dict(usage)
|
|
1113
|
+
if timing := extract_timing(final_chunk):
|
|
1114
|
+
result["timing"] = timing
|
|
766
1115
|
if metadata:
|
|
767
1116
|
result["metadata"] = metadata
|
|
768
1117
|
return result
|
|
@@ -788,43 +1137,32 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
788
1137
|
resume_payload_provided = bool(payload.pop("resume_payload_provided", False))
|
|
789
1138
|
resume_interrupt_id = str(payload.pop("resume_interrupt_id", "") or "")
|
|
790
1139
|
resume_value = payload.get("input")
|
|
791
|
-
is_gateway_approval_resume = bool(
|
|
792
|
-
is_resume and self._is_gateway_approval_semantic_resume(resume_value)
|
|
793
|
-
)
|
|
794
|
-
if is_gateway_approval_resume:
|
|
795
|
-
# ``Command(resume=...)`` only works for a graph that actually
|
|
796
|
-
# yielded LangGraph's native interrupt. ToolGateway approvals are
|
|
797
|
-
# intercepted after a normal tool result, when the graph already
|
|
798
|
-
# ended, so restart a normal turn from the persisted transcript.
|
|
799
|
-
payload["input"] = self._gateway_approval_follow_up_input()
|
|
800
|
-
resume_value = payload["input"]
|
|
801
1140
|
checkpoint_ref = self._extract_langgraph_checkpoint_ref(payload)
|
|
802
1141
|
history = payload.pop("history", [])
|
|
803
|
-
native_context = self.build_native_context(
|
|
804
|
-
|
|
1142
|
+
native_context = self.build_native_context(
|
|
1143
|
+
payload.get("platform_context"),
|
|
1144
|
+
context_schema=getattr(self._agent, "context_schema", None),
|
|
1145
|
+
)
|
|
1146
|
+
config = await self._get_session_config(session_id)
|
|
805
1147
|
if is_checkpoint_resume:
|
|
806
1148
|
config = self._apply_checkpoint_resume_config(
|
|
807
1149
|
config,
|
|
808
1150
|
session_id=session_id,
|
|
809
1151
|
checkpoint_ref=checkpoint_ref,
|
|
1152
|
+
enforce_bound_thread=bool(self._invocation_identity_scope_ref()),
|
|
810
1153
|
)
|
|
811
1154
|
|
|
812
1155
|
# 判断输入格式 / resume
|
|
813
1156
|
if is_checkpoint_resume:
|
|
814
1157
|
state = resume_value
|
|
815
|
-
elif is_resume
|
|
1158
|
+
elif is_resume:
|
|
816
1159
|
# ``Command(resume=...)`` is delivered to the graph's suspended
|
|
817
1160
|
# interrupt. A custom prepare-state hook is for new user input;
|
|
818
1161
|
# applying it here can rewrite an approval decision into ordinary
|
|
819
1162
|
# graph state and turn an approved HITL action into a rejection.
|
|
820
|
-
state = resume_value
|
|
1163
|
+
state = self._unwrap_resume_value(resume_value)
|
|
821
1164
|
elif self._has_prepare_state_hook():
|
|
822
|
-
state = self._prepare_state_with_hook(
|
|
823
|
-
payload,
|
|
824
|
-
session_id,
|
|
825
|
-
history,
|
|
826
|
-
is_resume=is_gateway_approval_resume,
|
|
827
|
-
)
|
|
1165
|
+
state = self._prepare_state_with_hook(payload, session_id, history)
|
|
828
1166
|
else:
|
|
829
1167
|
state = self._to_state(payload, history)
|
|
830
1168
|
|
|
@@ -839,7 +1177,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
839
1177
|
config=config,
|
|
840
1178
|
context=native_context,
|
|
841
1179
|
)
|
|
842
|
-
elif is_resume
|
|
1180
|
+
elif is_resume:
|
|
843
1181
|
result = await self._invoke_graph(
|
|
844
1182
|
Command(resume=state),
|
|
845
1183
|
config=config,
|
|
@@ -852,7 +1190,12 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
852
1190
|
context=native_context,
|
|
853
1191
|
)
|
|
854
1192
|
|
|
855
|
-
output = {
|
|
1193
|
+
output = {
|
|
1194
|
+
"output": self._extract_output(result), "raw": result,
|
|
1195
|
+
**skill_eval_response_fields(result),
|
|
1196
|
+
}
|
|
1197
|
+
if timing := extract_timing(result):
|
|
1198
|
+
output["timing"] = timing
|
|
856
1199
|
usage = self._extract_usage(result)
|
|
857
1200
|
if usage:
|
|
858
1201
|
output["usage"] = usage
|
|
@@ -866,7 +1209,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
866
1209
|
|
|
867
1210
|
except Exception as e:
|
|
868
1211
|
if "Interrupt" in type(e).__name__:
|
|
869
|
-
|
|
1212
|
+
state, error = await self._read_graph_state(config, include_subgraphs=True)
|
|
1213
|
+
if state is None:
|
|
1214
|
+
# 图已经抛出 interrupt,但状态读不回来:这里必须显性失败,
|
|
1215
|
+
# 不能返回空 interrupt_info,更不能伪装成正常完成。
|
|
1216
|
+
raise RuntimeError(
|
|
1217
|
+
"graph interrupted but its checkpoint state could not be read"
|
|
1218
|
+
) from error
|
|
1219
|
+
interrupt_info = self._get_interrupt_info(state)
|
|
870
1220
|
return {
|
|
871
1221
|
"type": "interrupt",
|
|
872
1222
|
"interrupt_info": interrupt_info,
|
|
@@ -901,20 +1251,20 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
901
1251
|
return str(content)
|
|
902
1252
|
return str(result) if result else ""
|
|
903
1253
|
|
|
1254
|
+
async def _read_graph_state(
|
|
1255
|
+
self,
|
|
1256
|
+
config: Mapping[str, Any],
|
|
1257
|
+
*,
|
|
1258
|
+
include_subgraphs: bool = False,
|
|
1259
|
+
) -> tuple[Any | None, Exception | None]:
|
|
1260
|
+
"""统一的图状态读取入口(实现在 `_langgraph_state_reader`,全仓唯一)。"""
|
|
1261
|
+
return await read_graph_state(
|
|
1262
|
+
self._agent, config, include_subgraphs=include_subgraphs
|
|
1263
|
+
)
|
|
1264
|
+
|
|
904
1265
|
def _get_interrupt_info(self, state) -> dict:
|
|
905
|
-
"""从 state 中获取 interrupt
|
|
906
|
-
|
|
907
|
-
for task in state.tasks:
|
|
908
|
-
if hasattr(task, "interrupts") and task.interrupts:
|
|
909
|
-
for intr in task.interrupts:
|
|
910
|
-
if hasattr(intr, "value"):
|
|
911
|
-
value = intr.value
|
|
912
|
-
info = dict(value) if isinstance(value, Mapping) else {"value": value}
|
|
913
|
-
interrupt_id = str(getattr(intr, "id", "") or "")
|
|
914
|
-
if interrupt_id:
|
|
915
|
-
info.setdefault("approval_request_id", interrupt_id)
|
|
916
|
-
return info
|
|
917
|
-
return {}
|
|
1266
|
+
"""从 state 中获取 interrupt 信息(含子图嵌套任务)。"""
|
|
1267
|
+
return interrupt_info_from_state(state)
|
|
918
1268
|
|
|
919
1269
|
async def _stream_checkpoint_resume_updates(
|
|
920
1270
|
self,
|
|
@@ -958,6 +1308,7 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
958
1308
|
latest_config = self._latest_checkpoint_config(config)
|
|
959
1309
|
state_usage = await self._latest_state_usage(latest_config)
|
|
960
1310
|
state_output = ""
|
|
1311
|
+
result_fields: dict[str, Any] = {}
|
|
961
1312
|
try:
|
|
962
1313
|
state = None
|
|
963
1314
|
if callable(getattr(self._agent, "aget_state", None)):
|
|
@@ -967,12 +1318,14 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
967
1318
|
values = getattr(state, "values", None)
|
|
968
1319
|
if values is not None:
|
|
969
1320
|
state_output = self._extract_output(values)
|
|
1321
|
+
result_fields = skill_eval_response_fields(values)
|
|
970
1322
|
except Exception:
|
|
971
1323
|
state_output = ""
|
|
972
1324
|
final_output = state_output or self._extract_output(latest_output)
|
|
973
1325
|
yield {
|
|
974
1326
|
"type": "final",
|
|
975
1327
|
"output": final_output,
|
|
1328
|
+
**result_fields,
|
|
976
1329
|
**({"usage": state_usage} if state_usage else {}),
|
|
977
1330
|
**({"resume_noop": True} if not emitted_update else {}),
|
|
978
1331
|
}
|
|
@@ -1052,15 +1405,9 @@ class LangGraphRunner(_LangGraphStreamMixin, BaseRunner):
|
|
|
1052
1405
|
return events
|
|
1053
1406
|
|
|
1054
1407
|
def _filter_tool_tags(self, content: str) -> str:
|
|
1055
|
-
"""
|
|
1408
|
+
"""过滤 <tool_call> 标签"""
|
|
1056
1409
|
if not isinstance(content, str):
|
|
1057
1410
|
return content
|
|
1058
1411
|
content = re.sub(r"<tool_call>.*?</tool_call>", "", content, flags=re.DOTALL)
|
|
1059
1412
|
content = re.sub(r"</?(?:tool_call|arg_key|arg_value)>", "", content)
|
|
1060
1413
|
return content
|
|
1061
|
-
|
|
1062
|
-
async def stream(self, input_data: Dict[str, Any]) -> AsyncIterator[Dict[str, Any]]:
|
|
1063
|
-
"""Prepare the managed checkpoint before yielding the first event."""
|
|
1064
|
-
await self.prepare_runtime_capabilities()
|
|
1065
|
-
async for event in super().stream(input_data):
|
|
1066
|
-
yield event
|