agentengine-sdk-python 0.8.4__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.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +6 -3
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/RECORD +591 -365
- 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 +6 -0
- ksadk/builders/code_builder.py +38 -12
- ksadk/builders/framework_requirements.py +20 -2
- ksadk/cli/__init__.py +36 -0
- 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_openclaw.py +26 -1
- ksadk/cli/cmd_plugin.py +70 -12
- ksadk/cli/cmd_studio.py +64 -16
- ksadk/cli/openclaw_env.py +1 -1
- ksadk/cli/resource_common.py +26 -0
- ksadk/codex/client.py +3 -2
- ksadk/configs/__init__.py +1 -1
- ksadk/configs/env_registry.py +125 -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 +23 -32
- ksadk/conversations/normalize.py +28 -10
- ksadk/conversations/runtime_baseline.py +37 -0
- ksadk/conversations/runtime_invocation.py +17 -4
- ksadk/conversations/runtime_observability.py +39 -10
- ksadk/conversations/runtime_payloads.py +8 -0
- ksadk/conversations/runtime_persistence.py +105 -9
- ksadk/conversations/runtime_preparation.py +13 -7
- ksadk/conversations/runtime_stream_events.py +29 -35
- ksadk/conversations/runtime_streaming.py +8 -0
- ksadk/events/adapters/_codex_items.py +16 -8
- ksadk/events/adapters/_langgraph_support.py +34 -0
- 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/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 +146 -111
- 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/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 +1 -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 +1 -1
- ksadk/kernel/__init__.py +10 -0
- ksadk/kernel/approval_presentation.py +91 -0
- ksadk/kernel/authorization.py +1 -1
- ksadk/kernel/bootstrap.py +86 -102
- 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 +27 -27
- 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 +304 -25
- ksadk/kernel/state.py +2 -3
- ksadk/kernel/store.py +69 -2
- ksadk/kernel/worker.py +79 -41
- ksadk/kernel/worker_history.py +72 -0
- ksadk/kernel/worker_identity.py +47 -0
- ksadk/memory/coordinator.py +22 -6
- ksadk/memory/extraction.py +40 -1
- ksadk/memory/models.py +77 -1
- ksadk/memory/provider_resolver.py +5 -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 +4 -2
- ksadk/model_proxy/transform.py +40 -2
- ksadk/plugins/__init__.py +1 -1
- ksadk/plugins/bridges/dsh.py +11 -0
- ksadk/plugins/builtins.py +40 -2
- ksadk/plugins/companion_artifacts.py +83 -0
- ksadk/plugins/companions.py +368 -0
- ksadk/plugins/contracts.py +1 -1
- ksadk/plugins/dsh_channels.py +156 -0
- ksadk/plugins/dsh_home.py +140 -0
- ksadk/plugins/dsh_teams.py +105 -0
- ksadk/plugins/dsh_toolchain.py +101 -19
- ksadk/plugins/execution_host.py +99 -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/package.json +1 -1
- ksadk/plugins/providers/bundles/dsh-memory/package.json +1 -1
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +1 -1
- 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/index.mjs +51 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +2 -2
- 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 +27 -4
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +9 -5
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
- ksadk/plugins/providers/codex.py +10 -2
- ksadk/plugins/providers/dsh_capabilities.py +61 -0
- ksadk/plugins/providers/harness.py +181 -33
- 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/shipped_dsh.py +4 -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/runners/_langgraph_runner_streams.py +121 -45
- ksadk/runners/_langgraph_state_reader.py +106 -0
- ksadk/runners/_session_identity.py +285 -0
- ksadk/runners/adk_runner.py +25 -60
- ksadk/runners/langgraph_runner.py +128 -111
- ksadk/runners/patch_langchain.py +47 -0
- ksadk/runners/usage_accumulator.py +11 -3
- ksadk/runtime/_runner_adapter/stream_mapping.py +52 -2
- ksadk/runtime/conversation_execution.py +25 -1
- ksadk/runtime/executor.py +9 -1
- ksadk/runtime/factory.py +36 -1
- ksadk/runtime/preprocessing.py +11 -3
- ksadk/runtime/runner_adapter.py +38 -9
- ksadk/runtime/skill_eval_result.py +36 -0
- ksadk/runtime/timing.py +46 -0
- ksadk/runtime/usage.py +49 -18
- ksadk/runtime_context.py +103 -1
- ksadk/sandbox/backends/e2b.py +245 -23
- ksadk/sandbox/backends/local_process.py +63 -39
- ksadk/sandbox/base.py +62 -1
- ksadk/sandbox/diagnostics.py +82 -0
- ksadk/sandbox/local_controls.py +746 -0
- ksadk/sandbox/local_launcher.py +90 -0
- ksadk/scheduler/dispatcher.py +1 -1
- ksadk/server/invocation_identity.py +118 -0
- ksadk/server/routes/common.py +32 -3
- ksadk/server/routes/control.py +64 -9
- ksadk/server/routes/dependencies.py +2 -1
- ksadk/server/routes/kernel_ingress.py +9 -1
- ksadk/server/routes/misc.py +233 -25
- ksadk/server/routes/models.py +3 -3
- ksadk/server/routes/openai_compat.py +76 -13
- ksadk/server/routes/run.py +106 -35
- ksadk/server/routes/sessions.py +244 -68
- ksadk/server/routes/workspace.py +130 -21
- ksadk/server/static/assets/{ArtifactsPanel-CGbWlMNh.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-b4C7upmO.js → CodeBlock-DHuAWfr5.js} +10 -7
- ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
- ksadk/server/static/assets/{MermaidBlock-BEBN4Ksz.js → MermaidBlock-DeBkbJvI.js} +9 -9
- ksadk/server/static/assets/{NativeTerminalPanel-zvL-WpAn.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-BYafW7Za.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
- ksadk/server/static/assets/{arc-bTohInsS.js → arc-C35w-pn1.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-Ch5Lbzsi.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-kqF4MDOG.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-8uSRIODv.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-DkhehZDr.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-BdXhtPe9.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-DPTpvpwi.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-Pqoh38el.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-DeU00qC-.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CzxScFkr.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-DpqMx-ux.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-C6t0SypQ.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-DVaeafZk.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-Bf9D3tzJ.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-B9cY3iTz.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-CSwlx3CB.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
- ksadk/server/static/assets/{dagre-UBpgon5q.js → dagre-B7nCawed.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-C9akhN9a.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-CgedhTPI.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-Cjucz5BY.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-Dd4Vleyn.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-CZ2jGtYW.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
- ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
- ksadk/server/static/assets/{dist-DiixqL0J.js → dist-1nXCdsej.js} +1 -1
- ksadk/server/static/assets/{dist-BIr4DSRq.js → dist-2vL2sAdF.js} +1 -1
- ksadk/server/static/assets/{dist-D_ctSS2i.js → dist-B3bA05-e.js} +1 -1
- ksadk/server/static/assets/{dist-ClYUxfeK.js → dist-BLpRy_Yx.js} +1 -1
- ksadk/server/static/assets/{dist-QfkEHOlb.js → dist-BO_UwatH.js} +1 -1
- ksadk/server/static/assets/{dist-B3FR1SKK.js → dist-BdNFAney.js} +1 -1
- ksadk/server/static/assets/{dist-BnaTiyzN.js → dist-C0J5_3qM.js} +1 -1
- ksadk/server/static/assets/{dist-Bj730Ib4.js → dist-CGt_UGeO.js} +1 -1
- ksadk/server/static/assets/{dist-CFzsn6BG.js → dist-CIRMvUM4.js} +1 -1
- ksadk/server/static/assets/{dist-BgV_owcB.js → dist-CIpWk_5f.js} +1 -1
- ksadk/server/static/assets/{dist-C5_ZAZsG.js → dist-CPyieXEf.js} +1 -1
- ksadk/server/static/assets/{dist-btbmmX5O.js → dist-D-92S-Fd.js} +1 -1
- ksadk/server/static/assets/{dist-fBO2v5Kt.js → dist-DNKuMzWc.js} +1 -1
- ksadk/server/static/assets/{dist-ufY3F5p6.js → dist-DWfdmz9s.js} +2 -2
- ksadk/server/static/assets/{dist-DVCOWtha.js → dist-DppE_r-D.js} +1 -1
- ksadk/server/static/assets/{dist-C1NMAY5a.js → dist-DyG6Ya-z.js} +1 -1
- ksadk/server/static/assets/{dist-CB9iJrvg.js → dist-M-SrdhhZ.js} +1 -1
- ksadk/server/static/assets/{dist-DvFK7p5S.js → dist-mqD5TZup.js} +1 -1
- ksadk/server/static/assets/{dist-Cf125P_m.js → dist-n3n6t_FO.js} +1 -1
- ksadk/server/static/assets/{dist-DFD6Qa6T.js → dist-qe8xjesy.js} +1 -1
- ksadk/server/static/assets/{dist-DoVSwoDb.js → dist-t6MzE0jU.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Ci8NqqZu.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CCIOhLZG.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-Cp_r9Hb6.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-Dlhc8Wr8.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-CO0rRTRA.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CHiaedSS.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-CHcCIB09.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CJ_ebBZf.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
- ksadk/server/static/assets/{katex-B4weu383.js → katex-mtjOi4KM.js} +1 -1
- ksadk/server/static/assets/{linear-V-MgYHW1.js → linear-BETqsxE_.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-CBijEX_c.js → mermaid-parser.core-DPWrvs90.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-Bc-pQvpp.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-D7genGLl.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-Bxj32zwD.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BURv2mGh.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-CCsh3avW.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-_FRRBKEd.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-C-gr2o9M.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-D97NmfKg.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DjrPC5FX.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DzMNg1hh.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-Cssf_CsU.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-BWTHzyS1.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-BSKgJsmR.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-eflHNoaZ.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-eYqrQ-v4.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +34 -2
- ksadk/sessions/invocation_identity.py +235 -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 +11 -0
- ksadk/skills/observability.py +132 -0
- ksadk/skills/package_store.py +75 -2
- ksadk/skills/runtime/agent.py +38 -5
- ksadk/skills/runtime/artifacts.py +87 -0
- ksadk/skills/runtime/backends/e2b.py +393 -52
- ksadk/skills/runtime/backends/local.py +621 -119
- ksadk/skills/runtime/base.py +78 -7
- ksadk/skills/runtime/executor.py +266 -1
- ksadk/skills/runtime/loader.py +108 -3
- ksadk/skills/runtime/request.py +18 -0
- ksadk/skills/tool_defs.py +108 -3
- ksadk/studio/api.py +592 -57
- ksadk/studio/api_contracts.py +8 -2
- ksadk/studio/api_plugin_routes.py +39 -12
- ksadk/studio/api_resource_connections.py +79 -41
- ksadk/studio/authoring.py +12 -6
- ksadk/studio/authoring_coordinator.py +4 -2
- ksadk/studio/builder.py +12 -0
- ksadk/studio/capabilities.py +23 -6
- ksadk/studio/channel_connections.py +333 -0
- ksadk/studio/cloud.py +30 -10
- ksadk/studio/cloud_shared_web.py +75 -2
- ksadk/studio/codex_agent_service.py +2 -2
- ksadk/studio/codex_builder.py +1 -1
- ksadk/studio/codex_run.py +6 -1
- ksadk/studio/compiler.py +10 -0
- ksadk/studio/configuration.py +182 -0
- ksadk/studio/contracts.py +33 -5
- ksadk/studio/dsh_application.py +135 -25
- ksadk/studio/dsh_capability_service.py +287 -20
- ksadk/studio/dsh_lifecycle.py +58 -0
- ksadk/studio/dsh_provider_registration.py +55 -16
- 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 +1 -1
- ksadk/studio/kernel_registry.py +418 -0
- ksadk/studio/kernel_sqlite_migration.py +181 -0
- ksadk/studio/model_client.py +1178 -64
- ksadk/studio/model_profile_service.py +26 -11
- ksadk/studio/native_documents.py +172 -0
- ksadk/studio/plugin_composition.py +13 -2
- ksadk/studio/plugin_kernel_adapter.py +15 -0
- ksadk/studio/plugin_lifecycle.py +80 -0
- ksadk/studio/plugin_runtime.py +230 -17
- ksadk/studio/provider_recovery.py +59 -0
- ksadk/studio/recovery_page.py +70 -0
- ksadk/studio/resource_authority.py +59 -32
- ksadk/studio/resource_catalog.py +6 -0
- ksadk/studio/run_activity.py +895 -0
- ksadk/studio/run_documents.py +127 -0
- ksadk/studio/run_service.py +329 -33
- ksadk/studio/runtime_catalog.py +53 -10
- ksadk/studio/runtime_source.py +1 -1
- ksadk/studio/scheduler_runtime.py +32 -289
- ksadk/studio/service.py +398 -103
- ksadk/studio/shared_web.py +149 -36
- 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/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/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
- ksadk/studio/static/assets/{blockDiagram-I7D4REHJ-CFmPl1de.js → blockDiagram-I7D4REHJ-CLB4L11u.js} +6 -6
- ksadk/studio/static/assets/{c4Diagram-7LVT6UL2-BRrGu8qt.js → c4Diagram-7LVT6UL2-BOma_Z_F.js} +7 -7
- 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-2ZTRR5NV-C2qZJila.js +2 -0
- ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
- ksadk/studio/static/assets/{chunk-4HAMMTFA-D220vUtq.js → chunk-4HAMMTFA-DVtDP4rm.js} +7 -7
- ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -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-C4DtVpCu.js → chunk-DU6HZSFF-CpEZCUgg.js} +1 -1
- ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
- ksadk/studio/static/assets/{chunk-GMAD6QVW-DiQA-u2N.js → chunk-GMAD6QVW-DE_8H717.js} +6 -6
- 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-BSlbjT_b.js → chunk-IMKFNOWR-D38axYOR.js} +5 -5
- 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-M2m6G3j4.js → chunk-OSK3NFVY-DiCQjx9b.js} +5 -5
- ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
- ksadk/studio/static/assets/{chunk-P2QGCYS3-DezaQxiK.js → chunk-P2QGCYS3-VdhKmfYq.js} +1 -1
- 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-DAyIVp5H.js → chunk-SHT3W25Y-DsCFnRVE.js} +9 -9
- ksadk/studio/static/assets/{chunk-SVP7TREG-DulomOrS.js → chunk-SVP7TREG-DljApgRX.js} +1 -1
- ksadk/studio/static/assets/{chunk-TICWLB2K-bHJYoflj.js → chunk-TICWLB2K-DWqRtyqa.js} +6 -6
- 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/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/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
- ksadk/studio/static/assets/{diagram-S7CK7UJ4-0BZ98mya.js → diagram-S7CK7UJ4-C6aH78c4.js} +3 -3
- 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/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
- ksadk/studio/static/assets/{erDiagram-RLTQ6QDP-DLGry2Ap.js → erDiagram-RLTQ6QDP-CGthTMmJ.js} +6 -6
- 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/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/{ishikawaDiagram-5VMMS53U-CljI2wyf.js → ishikawaDiagram-5VMMS53U-BUGEl8cO.js} +2 -2
- ksadk/studio/static/assets/{journeyDiagram-3NMN7TZE-D50Fo2sL.js → journeyDiagram-3NMN7TZE-Ch2ZYxvr.js} +6 -6
- ksadk/studio/static/assets/{kanban-definition-UXKFOSKX-DimfOTam.js → kanban-definition-UXKFOSKX-Da-Fp4vC.js} +3 -3
- ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
- ksadk/studio/static/assets/{line-CX5BOOUP.js → line-BDaeq300.js} +1 -1
- 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-Bizzqy5R.js → mindmap-definition-YA3MSWOX-CvlsVQ38.js} +1 -1
- ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.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-B9mrFSDF.js → pieDiagram-E7YTZNPT-DlrWiSOv.js} +1 -1
- 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-NzUfCbMR.js → quadrantDiagram-AXDQQJYC-BA3hpUZM.js} +6 -6
- 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-BF3d103U.js → requirementDiagram-BXWQKSXE-E-Ge0FcV.js} +1 -1
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
- ksadk/studio/static/assets/{sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js → sequenceDiagram-WJ2MYXX4-CcElXGg4.js} +9 -9
- 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-DxmSSjRB.js → timeline-definition-24CTP7MA-CIuYhNy3.js} +7 -7
- 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-Ba1AOWoe.js → wardleyDiagram-VM6X3IG4-CMJiaedy.js} +1 -1
- ksadk/studio/static/assets/{xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js → xychartDiagram-S5SC5T6Z-BdgtMvW2.js} +6 -6
- 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
- ksadk/server/static/assets/MathMessageMarkdown-DbdW5A4_.js +0 -8
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +0 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +0 -1
- ksadk/server/static/assets/dist-B2_CVgKv.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +0 -1
- ksadk/server/static/assets/index-DcTML1Up.css +0 -2
- ksadk/server/static/assets/index-Dh2XHqPK.js +0 -244
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +0 -1
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +0 -41
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +0 -8
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +0 -44
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +0 -3
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +0 -1
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +0 -1
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +0 -36
- ksadk/studio/static/assets/channel-BqO-gtEw.js +0 -1
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +0 -2
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +0 -1
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +0 -1
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +0 -1
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +0 -1
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +0 -1
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +0 -1
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +0 -1
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +0 -1
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +0 -1
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +0 -1
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +0 -62
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +0 -4
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +0 -41
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +0 -3
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +0 -24
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +0 -24
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +0 -1
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +0 -1
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +0 -1
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +0 -292
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +0 -1
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +0 -106
- ksadk/studio/static/assets/index-CeHL9ARV.css +0 -2
- ksadk/studio/static/assets/index-D9QEcVpL.js +0 -320
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +0 -1
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +0 -2
- ksadk/studio/static/assets/linear-BCxN9JLv.js +0 -1
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +0 -7
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +0 -1
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +0 -1
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +0 -1
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +0 -1
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +0 -1
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +0 -1
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +0 -1
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +0 -1
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +0 -1
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +0 -40
- ksadk/studio/static/assets/src-SFn9St9H.js +0 -1
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +0 -1
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +0 -1
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +0 -1
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +0 -8
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +0 -1
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +0 -1
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +0 -34
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +0 -1
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
- /ksadk/studio/static/assets/{MathMessageMarkdown-CBcDrAw--BEOyPC3w.css → MathMessageMarkdown-BesSeCYl-BEOyPC3w.css} +0 -0
|
@@ -0,0 +1,859 @@
|
|
|
1
|
+
"""ManagedLangGraphEngine 的图构建模块(从 langgraph.py 拆出)。
|
|
2
|
+
|
|
3
|
+
按 ExecutionPlan 组装 LangGraph 图(节点实现 + 边 + 条件路由),
|
|
4
|
+
并随引擎注入 Checkpointer。langgraph 类型不越出 engine 包
|
|
5
|
+
(tests/architecture/test_harness_contract.py 守卫)。
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
from typing import Any
|
|
13
|
+
|
|
14
|
+
from langgraph.graph import END, START, StateGraph
|
|
15
|
+
from langgraph.types import interrupt
|
|
16
|
+
|
|
17
|
+
from ksadk.harness.engine import budgets
|
|
18
|
+
from ksadk.harness.engine.base import ExecutionEngineError
|
|
19
|
+
from ksadk.harness.engine.langgraph import _GraphState
|
|
20
|
+
from ksadk.harness.engine.mcp_disclosure import MCP_CALL_TOOL_TOOL, McpDisclosureCursors
|
|
21
|
+
from ksadk.harness.engine.policy_runtime import revalidate_policy
|
|
22
|
+
from ksadk.harness.engine.spans import wrap_node_span
|
|
23
|
+
from ksadk.harness.engine.subagents import ChildApprovalPending
|
|
24
|
+
from ksadk.harness.events import EventType
|
|
25
|
+
from ksadk.harness.loop import (
|
|
26
|
+
ModelFailoverExhausted,
|
|
27
|
+
ReasonInput,
|
|
28
|
+
ToolCallInput,
|
|
29
|
+
execute_tool_calls,
|
|
30
|
+
reason_turn_async,
|
|
31
|
+
)
|
|
32
|
+
from ksadk.harness.loop.reason import ReasoningLimitError
|
|
33
|
+
from ksadk.harness.reasoner import HarnessReasoningTurn
|
|
34
|
+
from ksadk.harness.run_control import ControlAction, RunControlStop
|
|
35
|
+
|
|
36
|
+
_DELEGATION_PREFACE = re.compile(
|
|
37
|
+
r"(?:\blet\s+me\s+(?:delegate|dispatch)|"
|
|
38
|
+
r"\bi\s+(?:will|'ll|am\s+going\s+to)\s+(?:delegate|dispatch)|"
|
|
39
|
+
r"(?:让我|我会|我将|接下来|准备|正在)(?:先)?(?:并行)?(?:派发|分派|调度|处理).{0,80}(?:子任务|子智能体|subtasks?))",
|
|
40
|
+
re.IGNORECASE,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def build_graph(engine, run):
|
|
45
|
+
spec = run.compiled.spec
|
|
46
|
+
|
|
47
|
+
def _restore_controller(state: _GraphState) -> None:
|
|
48
|
+
if run.controller is not None and state.get("run_control"):
|
|
49
|
+
run.controller.restore(state["run_control"])
|
|
50
|
+
budgets.restore(run, state.get("budget") or {})
|
|
51
|
+
|
|
52
|
+
def _capture_control_event(event) -> ControlAction:
|
|
53
|
+
if event.event_id in run.observed_event_ids:
|
|
54
|
+
return ControlAction.CONTINUE
|
|
55
|
+
run.observed_event_ids.add(event.event_id)
|
|
56
|
+
if event.event_type == EventType.USAGE_REPORTED:
|
|
57
|
+
input_tokens = int(event.payload.get("input_tokens") or 0)
|
|
58
|
+
output_tokens = int(event.payload.get("output_tokens") or 0)
|
|
59
|
+
budgets.spend(run, "tokens", int(event.payload.get("total_tokens") or
|
|
60
|
+
input_tokens + output_tokens))
|
|
61
|
+
budgets.spend(run, "input_tokens", input_tokens)
|
|
62
|
+
budgets.spend(run, "output_tokens", output_tokens)
|
|
63
|
+
if event.event_type == EventType.ARTIFACT_CREATED:
|
|
64
|
+
uri = str(event.payload.get("uri") or "")
|
|
65
|
+
if uri and uri not in run.artifact_refs:
|
|
66
|
+
run.artifact_refs.append(uri)
|
|
67
|
+
if run.controller is None:
|
|
68
|
+
return ControlAction.CONTINUE
|
|
69
|
+
if not any(item.event_id == event.event_id for item in run.control_events):
|
|
70
|
+
run.control_events.append(event)
|
|
71
|
+
decision = run.controller.observe(event)
|
|
72
|
+
return decision.action
|
|
73
|
+
|
|
74
|
+
def _before_model(state: _GraphState) -> None:
|
|
75
|
+
_restore_controller(state)
|
|
76
|
+
if run.controller is None:
|
|
77
|
+
budgets.check(run, "tokens", 0)
|
|
78
|
+
budgets.check(run, "models")
|
|
79
|
+
budgets.spend(run, "models")
|
|
80
|
+
return
|
|
81
|
+
decision = run.controller.before_model()
|
|
82
|
+
if decision.action == ControlAction.STOP:
|
|
83
|
+
state["run_control"] = run.controller.snapshot()
|
|
84
|
+
raise RunControlStop(decision.reason)
|
|
85
|
+
budgets.check(run, "tokens", 0)
|
|
86
|
+
budgets.check(run, "models")
|
|
87
|
+
budgets.spend(run, "models")
|
|
88
|
+
guidance = run.controller.take_execution_instruction()
|
|
89
|
+
if guidance:
|
|
90
|
+
state["messages"].append({"role": "system", "content": guidance})
|
|
91
|
+
run.events.append(
|
|
92
|
+
engine._event(
|
|
93
|
+
run,
|
|
94
|
+
EventType.RUN_PROGRESS,
|
|
95
|
+
{
|
|
96
|
+
"kind": "run_control",
|
|
97
|
+
"status": "in_progress",
|
|
98
|
+
"action": "guidance",
|
|
99
|
+
"plan_revision": run.controller.guidance_revision,
|
|
100
|
+
},
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
if decision.action == ControlAction.CLOSE:
|
|
104
|
+
instruction = run.controller.take_closing_instruction(decision.reason)
|
|
105
|
+
if instruction:
|
|
106
|
+
state["messages"].append({"role": "system", "content": instruction})
|
|
107
|
+
run.events.append(
|
|
108
|
+
engine._event(
|
|
109
|
+
run,
|
|
110
|
+
EventType.RUN_PROGRESS,
|
|
111
|
+
{
|
|
112
|
+
"kind": "run_control",
|
|
113
|
+
"status": "in_progress",
|
|
114
|
+
"action": "close",
|
|
115
|
+
"reason": decision.reason,
|
|
116
|
+
},
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
state["run_control"] = run.controller.snapshot()
|
|
120
|
+
|
|
121
|
+
async def reason(state: _GraphState) -> _GraphState:
|
|
122
|
+
await revalidate_policy(engine, run)
|
|
123
|
+
_before_model(state)
|
|
124
|
+
state["turn_count"] += 1
|
|
125
|
+
# 收口 5:Turn 区间事件(模型/工具/usage 事件按 seq 落在区间内)。
|
|
126
|
+
turn_id = f"{run.handle.run_id}:t{state['turn_count']}"
|
|
127
|
+
run.events.append(
|
|
128
|
+
engine._event(
|
|
129
|
+
run,
|
|
130
|
+
EventType.TURN_STARTED,
|
|
131
|
+
{"turn_id": turn_id, "turn_number": state["turn_count"]},
|
|
132
|
+
)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def _reason_input() -> ReasonInput:
|
|
136
|
+
max_total_tokens = budgets.limit(run, "tokens")
|
|
137
|
+
if (
|
|
138
|
+
run.controller is not None
|
|
139
|
+
and run.controller.spec.limits.max_total_tokens is not None
|
|
140
|
+
):
|
|
141
|
+
controlled_limit = run.controller.spec.limits.max_total_tokens
|
|
142
|
+
max_total_tokens = (
|
|
143
|
+
min(int(max_total_tokens), controlled_limit)
|
|
144
|
+
if max_total_tokens is not None
|
|
145
|
+
else controlled_limit
|
|
146
|
+
)
|
|
147
|
+
# Model Profile 的输出上限是每次调用的硬限制;Run 总预算则是
|
|
148
|
+
# 随执行消耗递减的剩余额度。两者同时存在时必须取更小值。
|
|
149
|
+
max_output_tokens = spec.model.max_output_tokens
|
|
150
|
+
if max_total_tokens is not None:
|
|
151
|
+
from ksadk.harness.engine.context_pipeline import count_tokens
|
|
152
|
+
from ksadk.harness.subagent import SubAgentExecutionError
|
|
153
|
+
|
|
154
|
+
used = max(
|
|
155
|
+
int(state.get("usage_tokens") or 0),
|
|
156
|
+
run.budget_usage.get("tokens", 0),
|
|
157
|
+
run.controller.total_tokens if run.controller is not None else 0,
|
|
158
|
+
)
|
|
159
|
+
estimated_input = sum(
|
|
160
|
+
count_tokens(str(message.get("content") or "")) for message in state["messages"]
|
|
161
|
+
) + count_tokens(spec.prompt.instructions or "")
|
|
162
|
+
remaining = int(max_total_tokens) - used - estimated_input
|
|
163
|
+
if remaining < 1:
|
|
164
|
+
if run.controller is not None:
|
|
165
|
+
run.controller.stop_reason = "total_tokens_hard_limit"
|
|
166
|
+
run.controller.budget_exhausted = True
|
|
167
|
+
state["run_control"] = run.controller.snapshot()
|
|
168
|
+
raise RunControlStop("total_tokens_hard_limit")
|
|
169
|
+
raise SubAgentExecutionError(
|
|
170
|
+
"budget_exhausted",
|
|
171
|
+
"sub-agent token budget exhausted before model invocation "
|
|
172
|
+
f"(limit={max_total_tokens}, used={used}, "
|
|
173
|
+
f"estimated_input={estimated_input})",
|
|
174
|
+
)
|
|
175
|
+
max_output_tokens = (
|
|
176
|
+
min(max_output_tokens, remaining)
|
|
177
|
+
if max_output_tokens is not None
|
|
178
|
+
else remaining
|
|
179
|
+
)
|
|
180
|
+
streaming = getattr(engine._reasoner, "_streaming", None) is True or os.getenv(
|
|
181
|
+
"KSADK_MODEL_STREAMING", ""
|
|
182
|
+
).strip().lower() in {"1", "true", "yes", "on"}
|
|
183
|
+
|
|
184
|
+
def _live_event_sink(event):
|
|
185
|
+
run.events.append(event)
|
|
186
|
+
run.seq = max(run.seq, event.seq_id)
|
|
187
|
+
_capture_control_event(event)
|
|
188
|
+
|
|
189
|
+
delegation_synthesis = bool(state.get("delegation_synthesis_pending"))
|
|
190
|
+
closing_turn = state["turn_count"] >= engine._max_reasoning_turns and any(
|
|
191
|
+
message.get("role") == "tool" for message in state["messages"]
|
|
192
|
+
)
|
|
193
|
+
instructions = spec.prompt.instructions or ""
|
|
194
|
+
if delegation_synthesis:
|
|
195
|
+
instructions += (
|
|
196
|
+
"\n\n已调度的子任务均已结束。现在必须直接综合已有子任务结果回答"
|
|
197
|
+
"用户;不得再次派发、描述将要执行的计划或把处理中话术当成答案。"
|
|
198
|
+
"若部分子任务失败,应明确指出失败项,并基于其余结果给出当前最佳结论。"
|
|
199
|
+
)
|
|
200
|
+
if closing_turn:
|
|
201
|
+
instructions += (
|
|
202
|
+
"\n\n这是本次执行的最后一轮。禁止再调用或模拟调用工具,禁止描述"
|
|
203
|
+
"后续计划或说将继续查找。必须现在基于已有证据输出完整、可交付的"
|
|
204
|
+
"当前最佳答案;证据不足的部分直接标为未验证。"
|
|
205
|
+
)
|
|
206
|
+
reason_messages = list(state["messages"])
|
|
207
|
+
if closing_turn:
|
|
208
|
+
# Several OpenAI-compatible models follow the newest user
|
|
209
|
+
# message more reliably than a system-prompt suffix. Without
|
|
210
|
+
# this explicit hand-off GLM can keep emitting a textual call
|
|
211
|
+
# to a tool used in the previous turn even though the closing
|
|
212
|
+
# turn deliberately has no tool schema. The provider then
|
|
213
|
+
# (correctly) rejects that call as undeclared and turns an
|
|
214
|
+
# otherwise useful research run into a failure. Keep the
|
|
215
|
+
# safety boundary -- no tools are disclosed -- but make the
|
|
216
|
+
# required transition from evidence collection to synthesis
|
|
217
|
+
# unambiguous in the conversational context as well.
|
|
218
|
+
reason_messages.append(
|
|
219
|
+
{
|
|
220
|
+
"role": "user",
|
|
221
|
+
"content": (
|
|
222
|
+
"资料收集阶段已经结束。不要再搜索、查看网页或调用任何工具;"
|
|
223
|
+
"请只使用上文已有证据,现在直接给出最终结论。若证据不足,"
|
|
224
|
+
"明确标为未验证。"
|
|
225
|
+
),
|
|
226
|
+
}
|
|
227
|
+
)
|
|
228
|
+
synthesis_tools = (
|
|
229
|
+
list(run.tools.values())
|
|
230
|
+
+ engine._skill_disclosure.tools(run.skill_catalog)
|
|
231
|
+
+ engine._mcp_disclosure.tools(run.mcp_catalog)
|
|
232
|
+
)
|
|
233
|
+
available_tools = (
|
|
234
|
+
synthesis_tools
|
|
235
|
+
+ list(run.sub_agents.values())
|
|
236
|
+
+ (
|
|
237
|
+
[engine._delegation_runtime]
|
|
238
|
+
if engine._delegation_runtime is not None
|
|
239
|
+
else []
|
|
240
|
+
)
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return ReasonInput(
|
|
244
|
+
model_ref=spec.model.profile_ref,
|
|
245
|
+
fallback_model_refs=spec.model.fallback_profile_refs,
|
|
246
|
+
provider_policy=spec.model.provider_policy,
|
|
247
|
+
instructions=instructions,
|
|
248
|
+
messages=reason_messages,
|
|
249
|
+
# A synthesis turn must not spawn more children, but it still
|
|
250
|
+
# needs ordinary tools to produce the deliverable the user
|
|
251
|
+
# requested (for example, save a Markdown report). Removing
|
|
252
|
+
# every tool here made GLM emit a textual write call against an
|
|
253
|
+
# empty schema, which could only fail after all children had
|
|
254
|
+
# already completed.
|
|
255
|
+
tools=(
|
|
256
|
+
[]
|
|
257
|
+
if closing_turn
|
|
258
|
+
else synthesis_tools if delegation_synthesis else available_tools
|
|
259
|
+
),
|
|
260
|
+
reasoner=engine._reasoner,
|
|
261
|
+
agent_id=run.state.agent_id,
|
|
262
|
+
user_id=run.state.user_id,
|
|
263
|
+
session_id=run.state.session_id,
|
|
264
|
+
run_id=run.handle.run_id,
|
|
265
|
+
seq_start=run.seq,
|
|
266
|
+
max_turns=engine._max_reasoning_turns,
|
|
267
|
+
max_output_tokens=max_output_tokens,
|
|
268
|
+
streaming=streaming,
|
|
269
|
+
live_event_sink=_live_event_sink if streaming else None,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
out = await reason_turn_async(state["turn_count"], _reason_input())
|
|
274
|
+
except ModelFailoverExhausted as exc:
|
|
275
|
+
# reason_turn 在最后一次失败时仍必须把每次 started/failed
|
|
276
|
+
# 审计事件交还引擎,不能因异常路径丢失配对事实。
|
|
277
|
+
for event in exc.events:
|
|
278
|
+
if event.seq_id <= run.seq:
|
|
279
|
+
continue
|
|
280
|
+
run.events.append(event)
|
|
281
|
+
run.seq = max(run.seq, event.seq_id)
|
|
282
|
+
if exc.stop_reason.value == "recover_context" and engine._context_engine is not None:
|
|
283
|
+
state["messages"] = await engine._context_pipeline.recover_model_overflow(
|
|
284
|
+
run,
|
|
285
|
+
state["messages"],
|
|
286
|
+
spec.prompt.instructions or "",
|
|
287
|
+
)
|
|
288
|
+
# 恢复调用仍属于同一个 Turn,但使用压缩后输入及新的 seq 起点。
|
|
289
|
+
try:
|
|
290
|
+
out = await reason_turn_async(state["turn_count"], _reason_input())
|
|
291
|
+
except ModelFailoverExhausted as retry_exc:
|
|
292
|
+
for event in retry_exc.events:
|
|
293
|
+
if event.seq_id <= run.seq:
|
|
294
|
+
continue
|
|
295
|
+
run.events.append(event)
|
|
296
|
+
run.seq = max(run.seq, event.seq_id)
|
|
297
|
+
raise RuntimeError(str(retry_exc)) from retry_exc
|
|
298
|
+
else:
|
|
299
|
+
raise RuntimeError(str(exc)) from exc
|
|
300
|
+
except ReasoningLimitError as exc:
|
|
301
|
+
raise RuntimeError(str(exc)) from exc
|
|
302
|
+
# 部分 Provider 在最后一个披露工具返回后会给出空 assistant 消息,
|
|
303
|
+
# 随即把 Run 当成正常结束。只在本 Run 已执行过工具且尚未重试时,
|
|
304
|
+
# 增加一次无工具收口轮;避免 Skill/MCP 已拿到 L3 证据却没有最终答案。
|
|
305
|
+
assistant_text = "\n".join(
|
|
306
|
+
str(message.get("content") or "").strip()
|
|
307
|
+
for message in out.new_messages
|
|
308
|
+
if message.get("role") == "assistant"
|
|
309
|
+
).strip()
|
|
310
|
+
unfinished_delegation_answer = bool(
|
|
311
|
+
state.get("delegation_synthesis_pending")
|
|
312
|
+
and _DELEGATION_PREFACE.search(assistant_text)
|
|
313
|
+
)
|
|
314
|
+
if (
|
|
315
|
+
out.route == "final"
|
|
316
|
+
and (not assistant_text or unfinished_delegation_answer)
|
|
317
|
+
and any(message.get("role") == "tool" for message in state["messages"])
|
|
318
|
+
and int(state.get("finalization_retries") or 0) < 1
|
|
319
|
+
and ("reason", "tool_calls") in set(run.compiled.plan.edges or ())
|
|
320
|
+
):
|
|
321
|
+
state["finalization_retries"] = int(state.get("finalization_retries") or 0) + 1
|
|
322
|
+
out.events = [
|
|
323
|
+
event
|
|
324
|
+
for event in out.events
|
|
325
|
+
if not (
|
|
326
|
+
event.event_type == EventType.TEXT_COMPLETED and event.phase == "final_answer"
|
|
327
|
+
)
|
|
328
|
+
]
|
|
329
|
+
out.new_messages = []
|
|
330
|
+
out.pending_tool_calls = []
|
|
331
|
+
out.route = "tool_calls"
|
|
332
|
+
state["messages"].append(
|
|
333
|
+
{
|
|
334
|
+
"role": "user",
|
|
335
|
+
"content": (
|
|
336
|
+
"上一轮没有形成可交付答案。所有已派发任务都已经结束,"
|
|
337
|
+
"请立即基于现有工具和子任务结果给出完整答案;不得描述"
|
|
338
|
+
"将要派发、继续处理或稍后完成。"
|
|
339
|
+
),
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
if out.route == "final" and state.get("delegation_synthesis_pending"):
|
|
343
|
+
state["delegation_synthesis_pending"] = False
|
|
344
|
+
for ev in out.events:
|
|
345
|
+
if ev.seq_id <= run.seq:
|
|
346
|
+
continue
|
|
347
|
+
# 长任务方案 §6.3:Actual Token 回填到最近一次 ContextManifest
|
|
348
|
+
# (actual_usage_ref 指向 usage.reported 事件)。同时在 usage
|
|
349
|
+
# 事件 payload 落 manifest_id —— 事件流层面可直接查询
|
|
350
|
+
# 「某次模型调用实际对应哪个 Manifest」(§6.2 闭环)。
|
|
351
|
+
if ev.event_type == EventType.USAGE_REPORTED and run.context_manifest:
|
|
352
|
+
ev.payload["manifest_id"] = run.context_manifest.manifest_id
|
|
353
|
+
run.context_manifest = run.context_manifest.with_actual(
|
|
354
|
+
input_tokens=int(ev.payload.get("input_tokens") or 0),
|
|
355
|
+
output_tokens=int(ev.payload.get("output_tokens") or 0),
|
|
356
|
+
usage_ref=ev.event_id,
|
|
357
|
+
)
|
|
358
|
+
run.events.append(ev)
|
|
359
|
+
run.seq = max(run.seq, ev.seq_id)
|
|
360
|
+
_capture_control_event(ev)
|
|
361
|
+
if ev.event_type == EventType.USAGE_REPORTED:
|
|
362
|
+
state["usage_tokens"] = (
|
|
363
|
+
int(state.get("usage_tokens") or 0)
|
|
364
|
+
+ int(ev.payload.get("input_tokens") or 0)
|
|
365
|
+
+ int(ev.payload.get("output_tokens") or 0)
|
|
366
|
+
)
|
|
367
|
+
state["messages"].extend(out.new_messages)
|
|
368
|
+
state["pending_tool_calls"] = out.pending_tool_calls
|
|
369
|
+
state["tool_batch_succeeded"] = []
|
|
370
|
+
state["tool_batch_failed"] = False
|
|
371
|
+
state["route"] = out.route
|
|
372
|
+
run.events.append(
|
|
373
|
+
engine._event(
|
|
374
|
+
run,
|
|
375
|
+
EventType.TURN_COMPLETED,
|
|
376
|
+
{"turn_id": turn_id, "turn_number": state["turn_count"]},
|
|
377
|
+
)
|
|
378
|
+
)
|
|
379
|
+
if run.controller is not None:
|
|
380
|
+
state["run_control"] = run.controller.snapshot()
|
|
381
|
+
if run.controller.stop_reason:
|
|
382
|
+
raise RunControlStop(run.controller.stop_reason)
|
|
383
|
+
return state
|
|
384
|
+
|
|
385
|
+
async def tool_calls(state: _GraphState) -> _GraphState:
|
|
386
|
+
await revalidate_policy(engine, run)
|
|
387
|
+
_restore_controller(state)
|
|
388
|
+
run.child_approval_decision = state.get("child_approval_decision")
|
|
389
|
+
state["child_approval_decision"] = {}
|
|
390
|
+
class _GraphApprovalResolver:
|
|
391
|
+
# LangGraph interrupt 同步语义:首次抛 GraphInterrupt,resume 后返回审批决定。
|
|
392
|
+
def request(self, *, call_id, name, arguments): # type: ignore[no-untyped-def]
|
|
393
|
+
return interrupt(
|
|
394
|
+
{"call_id": call_id, "name": name, "args": arguments, "risk": "high"}
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# 披露游标活在图状态(随 Checkpoint 持久化);节点结束写回。
|
|
398
|
+
cursors = McpDisclosureCursors(
|
|
399
|
+
# Checkpoint 反序列化会把 tuple 变 list(不可哈希),统一还原。
|
|
400
|
+
listed={tuple(item) for item in (state.get("mcp_listed") or ())},
|
|
401
|
+
schema_read={tuple(item) for item in (state.get("mcp_schema_read") or ())},
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
def _mcp_approval_decider(name: str, arguments: dict[str, Any]) -> bool:
|
|
405
|
+
# P0.1:按实际目标 Server 动态决策——只有 mcp_call_tool 指向
|
|
406
|
+
# high/critical 风险 Server 时才要求审批(高低风险混用不误伤)。
|
|
407
|
+
return name == MCP_CALL_TOOL_TOOL and engine._mcp_disclosure.approval_decider(arguments)
|
|
408
|
+
|
|
409
|
+
class _EngineToolExecutor:
|
|
410
|
+
@staticmethod
|
|
411
|
+
def validate_arguments(name, arguments): # type: ignore[no-untyped-def]
|
|
412
|
+
tool = run.tools.get(name)
|
|
413
|
+
if tool is None:
|
|
414
|
+
return None
|
|
415
|
+
raw_schema = getattr(tool, "parameters", None)
|
|
416
|
+
# Host tests and backward-compatible integrations may still
|
|
417
|
+
# register a plain callable. With no published schema there
|
|
418
|
+
# is nothing to validate here; execution retains its previous
|
|
419
|
+
# behaviour.
|
|
420
|
+
if not isinstance(raw_schema, dict):
|
|
421
|
+
return None
|
|
422
|
+
schema = raw_schema
|
|
423
|
+
required = schema.get("required") or ()
|
|
424
|
+
missing = [
|
|
425
|
+
str(field)
|
|
426
|
+
for field in required
|
|
427
|
+
if str(field) not in arguments
|
|
428
|
+
or arguments.get(str(field)) is None
|
|
429
|
+
]
|
|
430
|
+
if missing:
|
|
431
|
+
return "missing required fields: " + ", ".join(missing)
|
|
432
|
+
try:
|
|
433
|
+
from jsonschema.validators import validator_for
|
|
434
|
+
|
|
435
|
+
validator = validator_for(schema)(schema)
|
|
436
|
+
error = next(validator.iter_errors(arguments), None)
|
|
437
|
+
except Exception as exc: # malformed host schema is not a model error
|
|
438
|
+
return f"tool schema validation failed: {exc}"
|
|
439
|
+
return f"schema mismatch: {error.message}" if error is not None else None
|
|
440
|
+
|
|
441
|
+
async def execute(self, name, arguments): # type: ignore[no-untyped-def]
|
|
442
|
+
return await engine._invoke_tool(name, arguments, run=run, mcp_cursors=cursors)
|
|
443
|
+
|
|
444
|
+
async def execute_with_context( # type: ignore[no-untyped-def]
|
|
445
|
+
self, name, arguments, context
|
|
446
|
+
):
|
|
447
|
+
return await engine._invoke_tool(
|
|
448
|
+
name,
|
|
449
|
+
arguments,
|
|
450
|
+
run=run,
|
|
451
|
+
mcp_cursors=cursors,
|
|
452
|
+
call_id=context.call_id,
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
def reliability(self, name, arguments, *, receipt_enabled): # type: ignore[no-untyped-def]
|
|
456
|
+
if engine._mcp_disclosure.is_tool(name):
|
|
457
|
+
return engine._mcp_disclosure.reliability(
|
|
458
|
+
name,
|
|
459
|
+
arguments,
|
|
460
|
+
receipt_enabled=receipt_enabled,
|
|
461
|
+
)
|
|
462
|
+
if engine._capability_runtime is not None:
|
|
463
|
+
return engine._capability_runtime.reliability(name)
|
|
464
|
+
from ksadk.harness.tool_reliability import classify_tool_reliability
|
|
465
|
+
|
|
466
|
+
return classify_tool_reliability(side_effect="unknown")
|
|
467
|
+
|
|
468
|
+
from ksadk.harness.subagent import order_subagent_tool_calls
|
|
469
|
+
|
|
470
|
+
pending_tool_calls = order_subagent_tool_calls(
|
|
471
|
+
list(state["pending_tool_calls"]), run.sub_agents
|
|
472
|
+
)
|
|
473
|
+
def _parallel_safe(name, arguments):
|
|
474
|
+
sub = run.sub_agents.get(name)
|
|
475
|
+
if sub is not None:
|
|
476
|
+
return not (sub.tools or (sub.inherit_skills and run.skill_catalog)
|
|
477
|
+
or (sub.inherit_mcp and run.mcp_catalog))
|
|
478
|
+
return bool(
|
|
479
|
+
engine._delegation_runtime is not None
|
|
480
|
+
and engine._delegation_runtime.is_tool(name)
|
|
481
|
+
and engine._capability_runtime is None
|
|
482
|
+
and engine._delegation_runtime.parallel_safe(
|
|
483
|
+
arguments,
|
|
484
|
+
parent_run=run,
|
|
485
|
+
)
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
# Commit sequential siblings at separate checkpoint boundaries. Only
|
|
489
|
+
# children proven unable to request approval may share a parallel node.
|
|
490
|
+
parallel = len(pending_tool_calls) > 1 and engine._capability_runtime is None and all(
|
|
491
|
+
_parallel_safe(p["name"], p["arguments"])
|
|
492
|
+
and p["name"] not in run.approval_required
|
|
493
|
+
and not (run.sub_agents.get(p["name"]) and run.sub_agents[p["name"]].depends_on)
|
|
494
|
+
for p in pending_tool_calls
|
|
495
|
+
) and spec.execution_strategy.config.get("subagent_failure_mode", "partial") != "fail_fast"
|
|
496
|
+
remaining_calls = [] if parallel else pending_tool_calls[1:]
|
|
497
|
+
pending_tool_calls = pending_tool_calls if parallel else pending_tool_calls[:1]
|
|
498
|
+
# Chat only needs an aggregate lifecycle signal. Provider selection,
|
|
499
|
+
# child labels and task bodies remain available in the execution trace
|
|
500
|
+
# and tool receipts, but are deliberately not expanded into one visible
|
|
501
|
+
# progress card per child.
|
|
502
|
+
delegation_calls = (
|
|
503
|
+
[
|
|
504
|
+
pending
|
|
505
|
+
for pending in pending_tool_calls
|
|
506
|
+
if engine._delegation_runtime is not None
|
|
507
|
+
and engine._delegation_runtime.is_tool(str(pending.get("name") or ""))
|
|
508
|
+
]
|
|
509
|
+
if engine._delegation_runtime is not None
|
|
510
|
+
else []
|
|
511
|
+
)
|
|
512
|
+
delegation_labels: list[str] = []
|
|
513
|
+
ordinary_calls = [
|
|
514
|
+
pending for pending in pending_tool_calls if pending not in delegation_calls
|
|
515
|
+
]
|
|
516
|
+
|
|
517
|
+
def _emit_tool_progress(status: str) -> None:
|
|
518
|
+
if not ordinary_calls:
|
|
519
|
+
return
|
|
520
|
+
tools = [str(pending.get("name") or "tool") for pending in ordinary_calls]
|
|
521
|
+
lowered = " ".join(tools).lower()
|
|
522
|
+
activity_kind = (
|
|
523
|
+
"write"
|
|
524
|
+
if any(token in lowered for token in ("write", "edit", "save"))
|
|
525
|
+
else "search"
|
|
526
|
+
if "search" in lowered
|
|
527
|
+
else "fetch"
|
|
528
|
+
if "fetch" in lowered
|
|
529
|
+
else "read"
|
|
530
|
+
if any(token in lowered for token in ("read", "list"))
|
|
531
|
+
else "command"
|
|
532
|
+
if any(token in lowered for token in ("command", "shell", "exec"))
|
|
533
|
+
else "tool"
|
|
534
|
+
)
|
|
535
|
+
batch_id = ":".join(
|
|
536
|
+
str(pending.get("call_id") or index)
|
|
537
|
+
for index, pending in enumerate(ordinary_calls, start=1)
|
|
538
|
+
)
|
|
539
|
+
# Repeated search/fetch/read turns are useful trace evidence but
|
|
540
|
+
# become dozens of duplicate chat rows during long research. Keep
|
|
541
|
+
# one public lifecycle per human activity class.
|
|
542
|
+
if status == "running":
|
|
543
|
+
if activity_kind in run.public_tool_activity_kinds:
|
|
544
|
+
return
|
|
545
|
+
run.public_tool_activity_kinds.add(activity_kind)
|
|
546
|
+
run.public_tool_activity_batches.add(batch_id)
|
|
547
|
+
elif batch_id not in run.public_tool_activity_batches:
|
|
548
|
+
return
|
|
549
|
+
progress_event = engine._event(
|
|
550
|
+
run,
|
|
551
|
+
EventType.RUN_PROGRESS,
|
|
552
|
+
{
|
|
553
|
+
"kind": "tool.batch",
|
|
554
|
+
"status": status,
|
|
555
|
+
"count": len(ordinary_calls),
|
|
556
|
+
"batch_id": batch_id,
|
|
557
|
+
"activity_kind": activity_kind,
|
|
558
|
+
# Tool arguments and results stay in Trace/receipts. The
|
|
559
|
+
# chat surface only receives stable capability names and
|
|
560
|
+
# turns them into human activity summaries.
|
|
561
|
+
"tools": tools,
|
|
562
|
+
},
|
|
563
|
+
)
|
|
564
|
+
run.events.append(progress_event)
|
|
565
|
+
_capture_control_event(progress_event)
|
|
566
|
+
|
|
567
|
+
def _emit_delegation_progress(status: str) -> None:
|
|
568
|
+
if not delegation_calls:
|
|
569
|
+
return
|
|
570
|
+
progress_event = engine._event(
|
|
571
|
+
run,
|
|
572
|
+
EventType.RUN_PROGRESS,
|
|
573
|
+
{
|
|
574
|
+
"kind": "delegation.batch",
|
|
575
|
+
"status": status,
|
|
576
|
+
"count": len(delegation_calls),
|
|
577
|
+
"labels": delegation_labels,
|
|
578
|
+
},
|
|
579
|
+
)
|
|
580
|
+
run.events.append(progress_event)
|
|
581
|
+
_capture_control_event(progress_event)
|
|
582
|
+
|
|
583
|
+
if delegation_calls:
|
|
584
|
+
delegation_labels = [
|
|
585
|
+
engine._delegation_runtime.public_label(
|
|
586
|
+
dict(pending.get("arguments") or {}),
|
|
587
|
+
call_id=str(pending.get("call_id") or ""),
|
|
588
|
+
)
|
|
589
|
+
for pending in delegation_calls
|
|
590
|
+
]
|
|
591
|
+
_emit_delegation_progress("running")
|
|
592
|
+
_emit_tool_progress("running")
|
|
593
|
+
has_subagent_dependencies = any(
|
|
594
|
+
run.sub_agents[name].depends_on
|
|
595
|
+
for name in (str(call.get("name") or "") for call in pending_tool_calls)
|
|
596
|
+
if name in run.sub_agents
|
|
597
|
+
)
|
|
598
|
+
subagent_failure_mode = str(
|
|
599
|
+
run.compiled.spec.execution_strategy.config.get("subagent_failure_mode", "partial")
|
|
600
|
+
)
|
|
601
|
+
def _live_tool_event(event):
|
|
602
|
+
if (event.event_type == EventType.TOOL_CALL_BEGIN
|
|
603
|
+
and str(event.payload.get("call_id") or "") in run.budget_tool_calls):
|
|
604
|
+
return # The same pending delegate resumes; it does not start twice.
|
|
605
|
+
run.seq += 1
|
|
606
|
+
event.seq_id = run.seq
|
|
607
|
+
run.events.append(event)
|
|
608
|
+
_capture_control_event(event)
|
|
609
|
+
|
|
610
|
+
try:
|
|
611
|
+
out = await execute_tool_calls(
|
|
612
|
+
ToolCallInput(
|
|
613
|
+
pending_tool_calls=pending_tool_calls,
|
|
614
|
+
approval_required=frozenset(run.approval_required),
|
|
615
|
+
approval_decider=_mcp_approval_decider,
|
|
616
|
+
parallel_safe_decider=(
|
|
617
|
+
lambda name, _arguments: (
|
|
618
|
+
(
|
|
619
|
+
name in run.sub_agents and _parallel_safe(name, _arguments)
|
|
620
|
+
or (
|
|
621
|
+
engine._delegation_runtime is not None
|
|
622
|
+
and engine._delegation_runtime.is_tool(name)
|
|
623
|
+
)
|
|
624
|
+
)
|
|
625
|
+
and not has_subagent_dependencies
|
|
626
|
+
and subagent_failure_mode != "fail_fast"
|
|
627
|
+
)
|
|
628
|
+
),
|
|
629
|
+
stop_on_error_decider=(
|
|
630
|
+
lambda name, _arguments: (
|
|
631
|
+
subagent_failure_mode == "fail_fast" and name in run.sub_agents
|
|
632
|
+
)
|
|
633
|
+
),
|
|
634
|
+
cancel_pending_decider=lambda name, _arguments: (
|
|
635
|
+
name in run.sub_agents
|
|
636
|
+
or (
|
|
637
|
+
engine._delegation_runtime is not None
|
|
638
|
+
and engine._delegation_runtime.is_tool(name)
|
|
639
|
+
)
|
|
640
|
+
),
|
|
641
|
+
dependencies={
|
|
642
|
+
name: tuple(spec.depends_on)
|
|
643
|
+
for name, spec in run.sub_agents.items()
|
|
644
|
+
if spec.depends_on
|
|
645
|
+
},
|
|
646
|
+
max_parallelism=int(
|
|
647
|
+
run.compiled.spec.execution_strategy.config.get("max_parallel_subagents", 4)
|
|
648
|
+
),
|
|
649
|
+
capability_runtime=engine._capability_runtime,
|
|
650
|
+
tenant_id=engine._tenant_id,
|
|
651
|
+
authorization_agent_id=run.request.metadata.get("authorization_agent_id"),
|
|
652
|
+
succeeded_tools=frozenset(state.get("tool_batch_succeeded") or ()),
|
|
653
|
+
prior_failure=bool(state.get("tool_batch_failed")),
|
|
654
|
+
live_event_sink=_live_tool_event,
|
|
655
|
+
argument_validator=_EngineToolExecutor.validate_arguments,
|
|
656
|
+
approval_resolver=_GraphApprovalResolver(),
|
|
657
|
+
tool_executor=_EngineToolExecutor(),
|
|
658
|
+
agent_id=run.state.agent_id,
|
|
659
|
+
user_id=run.state.user_id,
|
|
660
|
+
session_id=run.state.session_id,
|
|
661
|
+
run_id=run.handle.run_id,
|
|
662
|
+
seq_start=run.seq,
|
|
663
|
+
working_context=run.state.working_context,
|
|
664
|
+
)
|
|
665
|
+
)
|
|
666
|
+
except ChildApprovalPending as exc:
|
|
667
|
+
state["child_approval"] = exc.detail
|
|
668
|
+
state["route"] = "child_approval"
|
|
669
|
+
state["budget"] = budgets.snapshot(run)
|
|
670
|
+
return state
|
|
671
|
+
except BaseException:
|
|
672
|
+
_emit_delegation_progress("failed")
|
|
673
|
+
_emit_tool_progress("failed")
|
|
674
|
+
raise
|
|
675
|
+
for ev in out.events:
|
|
676
|
+
_capture_control_event(ev)
|
|
677
|
+
if ev.event_type == EventType.TOOL_CALL_END:
|
|
678
|
+
if not ev.payload.get("error"):
|
|
679
|
+
state.setdefault("tool_batch_succeeded", []).append(ev.payload["name"])
|
|
680
|
+
elif (
|
|
681
|
+
subagent_failure_mode == "fail_fast"
|
|
682
|
+
and ev.payload.get("name") in run.sub_agents
|
|
683
|
+
):
|
|
684
|
+
state["tool_batch_failed"] = True
|
|
685
|
+
tool_errors = any(
|
|
686
|
+
event.event_type == EventType.TOOL_CALL_END and event.payload.get("error")
|
|
687
|
+
for event in out.events
|
|
688
|
+
if str(event.payload.get("name") or "")
|
|
689
|
+
not in {str(call.get("name") or "") for call in delegation_calls}
|
|
690
|
+
)
|
|
691
|
+
_emit_tool_progress("failed" if tool_errors else "completed")
|
|
692
|
+
# 收口 6:子 Agent 事件统一重排并入(tool.call.begin/end 之后)。
|
|
693
|
+
from ksadk.harness.subagent import resequence_child_events
|
|
694
|
+
|
|
695
|
+
child_events = engine._pending_child_events.pop(run.handle.run_id, [])
|
|
696
|
+
for event in child_events:
|
|
697
|
+
_capture_control_event(event)
|
|
698
|
+
resequence_child_events(run, child_events)
|
|
699
|
+
subagent_events = engine._pending_subagent_events.pop(run.handle.run_id, {})
|
|
700
|
+
for pending in pending_tool_calls:
|
|
701
|
+
pending_events = subagent_events.get(str(pending.get("call_id") or ""), [])
|
|
702
|
+
for event in pending_events:
|
|
703
|
+
_capture_control_event(event)
|
|
704
|
+
resequence_child_events(
|
|
705
|
+
run,
|
|
706
|
+
pending_events,
|
|
707
|
+
)
|
|
708
|
+
if delegation_calls:
|
|
709
|
+
delegated_call_ids = {str(pending.get("call_id") or "") for pending in delegation_calls}
|
|
710
|
+
failed = any(
|
|
711
|
+
event.event_type == EventType.TOOL_CALL_END
|
|
712
|
+
and str(event.payload.get("call_id") or "") in delegated_call_ids
|
|
713
|
+
and bool(event.payload.get("error"))
|
|
714
|
+
for event in out.events
|
|
715
|
+
)
|
|
716
|
+
_emit_delegation_progress("failed" if failed else "completed")
|
|
717
|
+
state["delegation_synthesis_pending"] = True
|
|
718
|
+
state["messages"].extend(out.new_messages)
|
|
719
|
+
if out.working_context is not None:
|
|
720
|
+
run.state.working_context = out.working_context
|
|
721
|
+
state["pending_tool_calls"] = remaining_calls
|
|
722
|
+
state["mcp_listed"] = sorted(cursors.listed)
|
|
723
|
+
state["mcp_schema_read"] = sorted(cursors.schema_read)
|
|
724
|
+
state["route"] = "tool_calls" if remaining_calls else out.route
|
|
725
|
+
if run.controller is not None:
|
|
726
|
+
if (
|
|
727
|
+
run.controller.replan_reason
|
|
728
|
+
and run.controller.guidance_emitted_revision != run.controller.guidance_revision
|
|
729
|
+
):
|
|
730
|
+
run.events.append(
|
|
731
|
+
engine._event(
|
|
732
|
+
run,
|
|
733
|
+
EventType.RUN_PROGRESS,
|
|
734
|
+
{
|
|
735
|
+
"kind": "run_control",
|
|
736
|
+
"status": "in_progress",
|
|
737
|
+
"action": "replan",
|
|
738
|
+
"reason": run.controller.replan_reason,
|
|
739
|
+
"plan_revision": run.controller.guidance_revision,
|
|
740
|
+
},
|
|
741
|
+
)
|
|
742
|
+
)
|
|
743
|
+
state["run_control"] = run.controller.snapshot()
|
|
744
|
+
return state
|
|
745
|
+
|
|
746
|
+
def route(state: _GraphState) -> str:
|
|
747
|
+
return state["route"]
|
|
748
|
+
|
|
749
|
+
def child_approval(state: _GraphState) -> _GraphState:
|
|
750
|
+
info = state["child_approval"]
|
|
751
|
+
decision = interrupt(info)
|
|
752
|
+
state["child_approval_decision"] = {**info, "decision": decision}
|
|
753
|
+
state["child_approval"] = {}
|
|
754
|
+
state["route"] = "tool_calls"
|
|
755
|
+
return state
|
|
756
|
+
|
|
757
|
+
async def plan_node(state: _GraphState) -> _GraphState:
|
|
758
|
+
"""plan-execute 拓扑的规划节点:一次无工具模型调用产出执行计划。"""
|
|
759
|
+
_before_model(state)
|
|
760
|
+
turn: HarnessReasoningTurn = await engine._reasoner.complete(
|
|
761
|
+
model=spec.model.profile_ref,
|
|
762
|
+
prompt=(spec.prompt.instructions or "") + "\n请先给出分步执行计划,再开始执行。",
|
|
763
|
+
messages=tuple(state["messages"]),
|
|
764
|
+
tools=[],
|
|
765
|
+
)
|
|
766
|
+
state["messages"].append(
|
|
767
|
+
{"role": "assistant", "content": "【执行计划】\n" + (turn.final_text or "")}
|
|
768
|
+
)
|
|
769
|
+
run.events.append(
|
|
770
|
+
engine._event(
|
|
771
|
+
run,
|
|
772
|
+
EventType.RUN_PROGRESS,
|
|
773
|
+
{
|
|
774
|
+
"kind": "plan",
|
|
775
|
+
"status": "in_progress",
|
|
776
|
+
"message": turn.final_text or "计划已生成",
|
|
777
|
+
},
|
|
778
|
+
)
|
|
779
|
+
)
|
|
780
|
+
return state
|
|
781
|
+
|
|
782
|
+
async def review_node(state: _GraphState) -> _GraphState:
|
|
783
|
+
"""plan-execute-review 拓扑的独立审查节点:对最终回答做一次批判。"""
|
|
784
|
+
_before_model(state)
|
|
785
|
+
messages = list(state["messages"]) + [
|
|
786
|
+
{"role": "user", "content": "请审查以上回答的准确性与遗漏,指出问题(如有)。"}
|
|
787
|
+
]
|
|
788
|
+
turn: HarnessReasoningTurn = await engine._reasoner.complete(
|
|
789
|
+
model=spec.model.profile_ref,
|
|
790
|
+
prompt=spec.prompt.instructions or "",
|
|
791
|
+
messages=tuple(messages),
|
|
792
|
+
tools=[],
|
|
793
|
+
)
|
|
794
|
+
state["messages"].append(
|
|
795
|
+
{"role": "assistant", "content": "【审查】\n" + (turn.final_text or "")}
|
|
796
|
+
)
|
|
797
|
+
return state
|
|
798
|
+
|
|
799
|
+
def passthrough(state: _GraphState) -> _GraphState:
|
|
800
|
+
# prepare_context / execute:上下文规划已在 _emit_context_plan 完成,
|
|
801
|
+
# execute 由 reason 循环承担——节点存在是为了拓扑可观测。
|
|
802
|
+
return state
|
|
803
|
+
|
|
804
|
+
# 集成项 4:按 ExecutionPlan 组图(不再硬编码 single-agent 拓扑)。
|
|
805
|
+
node_impls = {
|
|
806
|
+
"reason": reason,
|
|
807
|
+
"tool_calls": tool_calls,
|
|
808
|
+
"plan": plan_node,
|
|
809
|
+
"review": review_node,
|
|
810
|
+
"prepare_context": passthrough,
|
|
811
|
+
"execute": passthrough,
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
node_impls = {
|
|
815
|
+
name: wrap_node_span(engine, run, name, impl) for name, impl in node_impls.items()
|
|
816
|
+
}
|
|
817
|
+
plan = run.compiled.plan
|
|
818
|
+
builder = StateGraph(_GraphState)
|
|
819
|
+
builder.add_node("child_approval", child_approval)
|
|
820
|
+
builder.add_edge("child_approval", "tool_calls")
|
|
821
|
+
for node in plan.nodes:
|
|
822
|
+
if node == "final":
|
|
823
|
+
continue # final 是出口,不是图节点。
|
|
824
|
+
impl = node_impls.get(node)
|
|
825
|
+
if impl is None:
|
|
826
|
+
raise ExecutionEngineError(f"引擎不支持拓扑节点: {node!r}")
|
|
827
|
+
builder.add_node(node, impl)
|
|
828
|
+
edges = plan.edges or ()
|
|
829
|
+
successors_of = {src: [dst for s, dst in edges if s == src] for src, _ in edges}
|
|
830
|
+
# 入口:无入边的节点接 START(保持 plan.nodes 顺序稳定)。
|
|
831
|
+
incoming = {dst for _, dst in edges}
|
|
832
|
+
for node in plan.nodes:
|
|
833
|
+
if node != "final" and node not in incoming:
|
|
834
|
+
builder.add_edge(START, node)
|
|
835
|
+
# reason 的出边是条件路由:有工具调用走 tool_calls,否则走出口/审查。
|
|
836
|
+
reason_successors = successors_of.get("reason", [])
|
|
837
|
+
exit_targets = [dst for dst in reason_successors if dst != "tool_calls"]
|
|
838
|
+
exit_target = exit_targets[0] if exit_targets else "final"
|
|
839
|
+
reason_mapping = {}
|
|
840
|
+
if "tool_calls" in reason_successors:
|
|
841
|
+
reason_mapping["tool_calls"] = "tool_calls"
|
|
842
|
+
reason_mapping["final"] = END if exit_target == "final" else exit_target
|
|
843
|
+
if "reason" in node_impls and "reason" in plan.nodes and "reason" != exit_target:
|
|
844
|
+
builder.add_conditional_edges("reason", route, reason_mapping)
|
|
845
|
+
for src, dst in edges:
|
|
846
|
+
if src == "reason":
|
|
847
|
+
continue # 已由条件边覆盖。
|
|
848
|
+
if src == "tool_calls":
|
|
849
|
+
builder.add_conditional_edges("tool_calls", route, {
|
|
850
|
+
"tool_calls": "tool_calls", "child_approval": "child_approval", "reason": dst,
|
|
851
|
+
})
|
|
852
|
+
continue
|
|
853
|
+
if dst == "final":
|
|
854
|
+
if src in node_impls and src != "reason":
|
|
855
|
+
builder.add_edge(src, END)
|
|
856
|
+
continue
|
|
857
|
+
builder.add_edge(src, dst)
|
|
858
|
+
graph = builder.compile(checkpointer=engine._checkpointer)
|
|
859
|
+
return graph
|