agentengine-sdk-python 0.8.5__py3-none-any.whl → 0.8.6__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.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/METADATA +12 -8
- {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/RECORD +823 -388
- ksadk/_async_iterators.py +79 -0
- ksadk/_build_provenance.json +1 -1
- ksadk/_model_anthropic.py +49 -0
- ksadk/_model_input.py +86 -0
- ksadk/_model_json.py +40 -0
- ksadk/_model_reasoning.py +17 -0
- ksadk/_model_refusal.py +20 -0
- ksadk/_model_sse.py +163 -0
- ksadk/a2a/__init__.py +157 -167
- ksadk/a2a/_invocation_state.py +86 -0
- ksadk/a2a/_space_client_events.py +33 -22
- ksadk/a2a/adk.py +194 -0
- ksadk/a2a/adk_invocation_context.py +242 -0
- ksadk/a2a/adk_runtime.py +126 -0
- ksadk/a2a/adk_tools.py +319 -0
- ksadk/a2a/bootstrap.py +149 -23
- ksadk/a2a/build_validation.py +147 -0
- ksadk/a2a/card.py +23 -15
- ksadk/a2a/codex.py +160 -0
- ksadk/a2a/codex_checkpoint.py +111 -0
- ksadk/a2a/codex_recovery.py +96 -0
- ksadk/a2a/codex_recovery_events.py +123 -0
- ksadk/a2a/codex_runtime.py +198 -0
- ksadk/a2a/codex_session_checkpoint.py +162 -0
- ksadk/a2a/composition.py +88 -0
- ksadk/a2a/context_store.py +118 -19
- ksadk/a2a/control_plane.py +108 -106
- ksadk/a2a/event_adapter.py +92 -193
- ksadk/a2a/executor.py +257 -85
- ksadk/a2a/exposure.py +106 -0
- ksadk/a2a/external_transport.py +3 -4
- ksadk/a2a/identity.py +106 -12
- ksadk/a2a/ids.py +14 -3
- ksadk/a2a/inbound_kernel.py +133 -0
- ksadk/a2a/interaction_wire.py +76 -0
- ksadk/a2a/invocation_checkpoint.py +274 -0
- ksadk/a2a/invocation_policy.py +87 -0
- ksadk/a2a/invocation_publication.py +210 -0
- ksadk/a2a/invocation_service.py +972 -0
- ksadk/a2a/invocation_types.py +459 -0
- ksadk/a2a/kernel_task_adapter.py +259 -0
- ksadk/a2a/langgraph.py +20 -7
- ksadk/a2a/langgraph_invocation_context.py +136 -0
- ksadk/a2a/langgraph_managed.py +150 -0
- ksadk/a2a/langgraph_recovery.py +32 -0
- ksadk/a2a/langgraph_runtime.py +89 -0
- ksadk/a2a/langgraph_tool_runtime.py +132 -0
- ksadk/a2a/langgraph_tools.py +63 -0
- ksadk/a2a/message_digest.py +40 -0
- ksadk/a2a/platform.py +389 -0
- ksadk/a2a/policy_refs.py +13 -0
- ksadk/a2a/presentation.py +402 -0
- ksadk/a2a/product_kernel_facts.py +177 -0
- ksadk/a2a/product_key.py +99 -0
- ksadk/a2a/protocol_errors.py +116 -0
- ksadk/a2a/result_text.py +49 -0
- ksadk/a2a/resume_store.py +93 -3
- ksadk/a2a/routes.py +6 -1
- ksadk/a2a/runtime_approval.py +198 -0
- ksadk/a2a/runtime_input.py +151 -0
- ksadk/a2a/server.py +16 -7
- ksadk/a2a/space_client.py +101 -16
- ksadk/a2a/task_adapter.py +19 -5
- ksadk/a2a/task_event_dispatcher.py +39 -2
- ksadk/a2a/task_event_outbox.py +215 -0
- ksadk/a2a/task_event_outbox_owned.py +130 -0
- ksadk/a2a/task_store.py +37 -0
- ksadk/a2a/tool_activity.py +176 -0
- ksadk/a2a/workload_tokens.py +134 -0
- ksadk/api/client.py +32 -79
- ksadk/api/sse_stream.py +96 -0
- ksadk/builders/code_builder.py +83 -106
- ksadk/builders/container_builder.py +11 -29
- ksadk/builders/framework_requirements.py +2 -0
- ksadk/builders/managed_runtime_builder.py +12 -0
- ksadk/builders/source_provenance.py +87 -0
- ksadk/cli/cmd_a2a.py +43 -0
- ksadk/cli/cmd_build.py +9 -0
- ksadk/cli/cmd_deploy.py +27 -2
- ksadk/cli/cmd_invoke.py +45 -92
- ksadk/cli/cmd_studio.py +5 -1
- ksadk/cli/cmd_web.py +2 -0
- ksadk/cli/hosted_invoke.py +206 -0
- ksadk/cli/invoke_content.py +60 -0
- ksadk/cli/runtime_bootstrap.py +27 -5
- ksadk/codex/_expert_request_reader.py +48 -0
- ksadk/codex/a2a_tools.py +140 -0
- ksadk/codex/async_approval.py +169 -0
- ksadk/codex/async_client.py +938 -0
- ksadk/codex/async_proxy.py +216 -0
- ksadk/codex/base_runtime.py +25 -0
- ksadk/codex/client.py +3 -1048
- ksadk/codex/client_payloads.py +85 -0
- ksadk/codex/rollout_checkpoint.py +264 -0
- ksadk/codex/runtime.py +290 -54
- ksadk/common/auth.py +2 -2
- ksadk/common/cloud_headers.py +36 -0
- ksadk/common/diagnostics.py +34 -0
- ksadk/common/kop_client.py +2 -1
- ksadk/configs/env_registry.py +106 -127
- ksadk/configs/env_registry_a2a.py +173 -0
- ksadk/configs/env_registry_studio.py +53 -5
- ksadk/configs/global_config.py +1 -0
- ksadk/configs/settings.py +6 -0
- ksadk/context_engine/assembler.py +9 -0
- ksadk/context_engine/contributors.py +80 -17
- ksadk/context_engine/instruction_authority.py +18 -0
- ksadk/conversations/attachments.py +53 -15
- ksadk/conversations/contracts.py +28 -9
- ksadk/conversations/message_projection.py +30 -125
- ksadk/conversations/message_projection_blocks.py +137 -0
- ksadk/conversations/model_context.py +11 -3
- ksadk/conversations/projector.py +63 -0
- ksadk/conversations/runtime_compaction.py +7 -2
- ksadk/conversations/runtime_input.py +16 -4
- ksadk/conversations/runtime_payloads.py +4 -0
- ksadk/conversations/runtime_persistence.py +192 -24
- ksadk/conversations/runtime_preparation.py +85 -6
- ksadk/conversations/runtime_projection.py +217 -0
- ksadk/conversations/runtime_resume.py +141 -70
- ksadk/conversations/tool_receipt_resume.py +387 -0
- ksadk/conversations/tool_receipts.py +32 -0
- ksadk/deployment/env_forward.py +5 -0
- ksadk/deployment/manager.py +15 -6
- ksadk/deployment/providers/serverless.py +76 -136
- ksadk/deployment/providers/serverless_payloads.py +122 -0
- ksadk/evaluation/agent_eval_client.py +2 -1
- ksadk/evaluation/contracts.py +78 -3
- ksadk/evaluation/evaluators.py +166 -1
- ksadk/evaluation/evidence.py +271 -4
- ksadk/evaluation/local_adapter.py +76 -12
- ksadk/evaluation/studio_build_adapter.py +73 -9
- ksadk/events/adapters/_a2a_checkpoint.py +151 -0
- ksadk/events/adapters/_a2a_snapshot.py +18 -14
- ksadk/events/adapters/_a2a_support.py +15 -3
- ksadk/events/adapters/_a2a_tool_activity.py +123 -0
- ksadk/events/adapters/_codex_errors.py +49 -0
- ksadk/events/adapters/_langgraph_support.py +12 -1
- ksadk/events/adapters/a2a.py +54 -26
- ksadk/events/adapters/adk.py +188 -30
- ksadk/events/adapters/codex.py +33 -7
- ksadk/events/adapters/langgraph.py +16 -6
- ksadk/events/canonical.py +5 -0
- ksadk/events/canonical_store.py +200 -4
- ksadk/events/reducer.py +82 -0
- ksadk/events/run_authority.py +176 -0
- ksadk/harness/__init__.py +4 -0
- ksadk/harness/artifact_adapters/__init__.py +1 -0
- ksadk/harness/artifact_adapters/native_page_budget.py +172 -0
- ksadk/harness/artifact_adapters/native_search.py +249 -0
- ksadk/harness/artifact_adapters/native_search_budget.py +134 -0
- ksadk/harness/artifact_adapters/native_store.py +115 -0
- ksadk/harness/artifact_adapters/native_tool.py +222 -0
- ksadk/harness/artifact_store.py +26 -9
- ksadk/harness/browser_adapters/__init__.py +6 -0
- ksadk/harness/browser_adapters/native_browser_tool.py +92 -0
- ksadk/harness/browser_adapters/native_dom_snapshot.py +187 -0
- ksadk/harness/browser_adapters/native_playwright.py +953 -0
- ksadk/harness/browser_adapters/native_vision.py +295 -0
- ksadk/harness/capability_adapters/__init__.py +1 -0
- ksadk/harness/capability_adapters/native_dsh.py +289 -0
- ksadk/harness/capability_runtime.py +104 -9
- ksadk/harness/compaction_record.py +31 -0
- ksadk/harness/compiler.py +3 -3
- ksadk/harness/config.py +28 -5
- ksadk/harness/conformance/contract.py +9 -11
- ksadk/harness/context_engine.py +18 -33
- ksadk/harness/context_sections.py +397 -0
- ksadk/harness/diagnostic_adapters/__init__.py +1 -0
- ksadk/harness/diagnostic_adapters/contracts.py +70 -0
- ksadk/harness/diagnostic_adapters/lsp_rpc.py +210 -0
- ksadk/harness/diagnostic_adapters/native_lsp.py +286 -0
- ksadk/harness/engine/completion_guard.py +16 -1
- ksadk/harness/engine/context_pipeline.py +864 -92
- ksadk/harness/engine/graph_builder.py +123 -630
- ksadk/harness/engine/hooked_reasoner.py +380 -0
- ksadk/harness/engine/langgraph.py +126 -8
- ksadk/harness/engine/mcp_disclosure.py +65 -114
- ksadk/harness/engine/phases/__init__.py +6 -0
- ksadk/harness/engine/phases/context.py +48 -0
- ksadk/harness/engine/phases/interaction.py +31 -0
- ksadk/harness/engine/phases/reason.py +552 -0
- ksadk/harness/engine/phases/tools.py +638 -0
- ksadk/harness/engine/policy_runtime.py +21 -10
- ksadk/harness/engine/postgres_checkpointer.py +325 -2
- ksadk/harness/engine/run_control_bridge.py +21 -1
- ksadk/harness/engine/run_types.py +10 -0
- ksadk/harness/engine/skill_disclosure.py +98 -12
- ksadk/harness/engine/steering.py +177 -0
- ksadk/harness/engine/subagents.py +18 -1
- ksadk/harness/engine/tool_dispatch.py +112 -7
- ksadk/harness/events.py +39 -2
- ksadk/harness/execution_policy.py +10 -0
- ksadk/harness/hooks.py +259 -0
- ksadk/harness/loop/reason.py +281 -36
- ksadk/harness/loop/tools.py +157 -12
- ksadk/harness/managed_runtime.py +254 -94
- ksadk/harness/mcp_disclosure_contract.py +85 -0
- ksadk/harness/mcp_result_policy.py +44 -0
- ksadk/harness/mcp_runtime.py +33 -0
- ksadk/harness/micro_compact.py +69 -0
- ksadk/harness/model_adapters/__init__.py +1 -0
- ksadk/harness/model_adapters/native_mcp_media.py +100 -0
- ksadk/harness/model_adapters/native_mcp_result.py +36 -0
- ksadk/harness/model_adapters/native_openai.py +703 -0
- ksadk/harness/model_capability.py +223 -8
- ksadk/harness/model_provider.py +214 -4
- ksadk/harness/multimodal.py +57 -0
- ksadk/harness/native/__init__.py +1 -0
- ksadk/harness/native/activation_contract.py +25 -0
- ksadk/harness/native/activation_recovery.py +29 -0
- ksadk/harness/native/adapters.py +291 -0
- ksadk/harness/native/artifact_contract.py +14 -0
- ksadk/harness/native/artifact_partial_read_capacity.py +171 -0
- ksadk/harness/native/artifact_read_capacity.py +182 -0
- ksadk/harness/native/artifact_read_contract.py +27 -0
- ksadk/harness/native/artifact_runtime.py +408 -0
- ksadk/harness/native/artifact_search_capacity.py +206 -0
- ksadk/harness/native/artifact_search_contract.py +40 -0
- ksadk/harness/native/artifact_single_read_capacity.py +170 -0
- ksadk/harness/native/browser_contract.py +229 -0
- ksadk/harness/native/browser_recovery.py +183 -0
- ksadk/harness/native/capabilities.py +204 -0
- ksadk/harness/native/child_approval.py +60 -0
- ksadk/harness/native/child_budget.py +136 -0
- ksadk/harness/native/child_cancellation.py +80 -0
- ksadk/harness/native/child_input.py +98 -0
- ksadk/harness/native/child_input_runtime.py +59 -0
- ksadk/harness/native/child_interruption.py +81 -0
- ksadk/harness/native/child_lifecycle.py +246 -0
- ksadk/harness/native/child_lifecycle_contract.py +91 -0
- ksadk/harness/native/child_notifications.py +75 -0
- ksadk/harness/native/child_promotion.py +66 -0
- ksadk/harness/native/command_runtime.py +99 -0
- ksadk/harness/native/completion.py +302 -0
- ksadk/harness/native/completion_text.py +116 -0
- ksadk/harness/native/context.py +358 -0
- ksadk/harness/native/context_artifact_page.py +75 -0
- ksadk/harness/native/context_compaction_projection.py +131 -0
- ksadk/harness/native/context_contributions.py +320 -0
- ksadk/harness/native/context_contributor_contract.py +133 -0
- ksadk/harness/native/context_driver.py +820 -0
- ksadk/harness/native/context_fresh_tools.py +49 -0
- ksadk/harness/native/context_history.py +272 -0
- ksadk/harness/native/context_microcompact.py +61 -0
- ksadk/harness/native/context_partial_summary.py +58 -0
- ksadk/harness/native/context_partition.py +492 -0
- ksadk/harness/native/context_pruning.py +275 -0
- ksadk/harness/native/context_reduction.py +60 -0
- ksadk/harness/native/context_replay.py +148 -0
- ksadk/harness/native/context_request_projection.py +526 -0
- ksadk/harness/native/context_runtime.py +976 -0
- ksadk/harness/native/context_runtime_contracts.py +409 -0
- ksadk/harness/native/context_search.py +112 -0
- ksadk/harness/native/context_source_fragments.py +188 -0
- ksadk/harness/native/context_source_progress.py +119 -0
- ksadk/harness/native/context_summary_planning.py +788 -0
- ksadk/harness/native/context_summary_recovery.py +105 -0
- ksadk/harness/native/delivery_review.py +331 -0
- ksadk/harness/native/delivery_review_contract.py +54 -0
- ksadk/harness/native/effect_admission.py +82 -0
- ksadk/harness/native/effect_control.py +318 -0
- ksadk/harness/native/effect_receipts.py +729 -0
- ksadk/harness/native/effect_runtime.py +303 -0
- ksadk/harness/native/effective_configuration.py +28 -0
- ksadk/harness/native/engine.py +945 -0
- ksadk/harness/native/final_output.py +34 -0
- ksadk/harness/native/final_submission.py +58 -0
- ksadk/harness/native/finalization_workspace.py +96 -0
- ksadk/harness/native/fork.py +151 -0
- ksadk/harness/native/guidance.py +91 -0
- ksadk/harness/native/history.py +381 -0
- ksadk/harness/native/hook_executor.py +205 -0
- ksadk/harness/native/hook_runtime_contract.py +282 -0
- ksadk/harness/native/interaction_observation.py +117 -0
- ksadk/harness/native/lease.py +103 -0
- ksadk/harness/native/machine.py +974 -0
- ksadk/harness/native/mcp_result_governance.py +156 -0
- ksadk/harness/native/model.py +570 -0
- ksadk/harness/native/model_feedback.py +63 -0
- ksadk/harness/native/model_input.py +30 -0
- ksadk/harness/native/model_recovery_contract.py +35 -0
- ksadk/harness/native/model_replay.py +128 -0
- ksadk/harness/native/model_request.py +133 -0
- ksadk/harness/native/model_runtime.py +196 -0
- ksadk/harness/native/model_takeover.py +419 -0
- ksadk/harness/native/model_tool_batch.py +40 -0
- ksadk/harness/native/observed_progress.py +46 -0
- ksadk/harness/native/operator_guidance.py +201 -0
- ksadk/harness/native/output_contract.py +80 -0
- ksadk/harness/native/output_recovery.py +24 -0
- ksadk/harness/native/ports.py +749 -0
- ksadk/harness/native/precompact_hook_runtime.py +171 -0
- ksadk/harness/native/replay_context.py +149 -0
- ksadk/harness/native/request_media.py +112 -0
- ksadk/harness/native/restore_contract.py +16 -0
- ksadk/harness/native/run_clock.py +120 -0
- ksadk/harness/native/state.py +436 -0
- ksadk/harness/native/steering.py +170 -0
- ksadk/harness/native/stop_hook_runtime.py +151 -0
- ksadk/harness/native/studio_admission.py +29 -0
- ksadk/harness/native/subagents.py +86 -0
- ksadk/harness/native/task_policy.py +99 -0
- ksadk/harness/native/task_progress.py +86 -0
- ksadk/harness/native/terminal_verification.py +43 -0
- ksadk/harness/native/tool_argument_feedback.py +178 -0
- ksadk/harness/native/tool_budget.py +253 -0
- ksadk/harness/native/tool_error_streak.py +89 -0
- ksadk/harness/native/tool_hook_runtime.py +343 -0
- ksadk/harness/native/tool_input_validation.py +58 -0
- ksadk/harness/native/tool_interruption.py +96 -0
- ksadk/harness/native/tool_observation.py +259 -0
- ksadk/harness/native/tool_progress.py +223 -0
- ksadk/harness/native/tool_recovery.py +25 -0
- ksadk/harness/native/tool_scheduling.py +33 -0
- ksadk/harness/native/tool_schema.py +126 -0
- ksadk/harness/native/transitions.py +151 -0
- ksadk/harness/native/turn_control.py +98 -0
- ksadk/harness/native/user_document.py +98 -0
- ksadk/harness/native/user_document_capture.py +49 -0
- ksadk/harness/native/user_input.py +87 -0
- ksadk/harness/native/verification.py +432 -0
- ksadk/harness/native/verification_binding.py +40 -0
- ksadk/harness/native/verification_runtime.py +233 -0
- ksadk/harness/native/verification_workspace.py +67 -0
- ksadk/harness/native_driver_failure.py +123 -0
- ksadk/harness/native_facade.py +977 -0
- ksadk/harness/native_factory.py +244 -0
- ksadk/harness/native_projection.py +503 -0
- ksadk/harness/native_runtime.py +621 -0
- ksadk/harness/native_shadow.py +250 -0
- ksadk/harness/native_shadow_inputs.py +146 -0
- ksadk/harness/progress_adapters/__init__.py +5 -0
- ksadk/harness/progress_adapters/native_todo.py +75 -0
- ksadk/harness/prompt_cache.py +65 -3
- ksadk/harness/public_activity.py +59 -0
- ksadk/harness/public_output.py +30 -0
- ksadk/harness/public_summary.py +36 -0
- ksadk/harness/reasoner.py +331 -22
- ksadk/harness/rpc.py +200 -0
- ksadk/harness/run_control.py +107 -2
- ksadk/harness/runtime.py +11 -2
- ksadk/harness/runtime_capabilities.py +71 -1
- ksadk/harness/sandbox_backend.py +203 -0
- ksadk/harness/sdk.py +153 -0
- ksadk/harness/session_store.py +370 -24
- ksadk/harness/skill_adapters/__init__.py +1 -0
- ksadk/harness/skill_adapters/native_bundle.py +148 -0
- ksadk/harness/skill_adapters/native_disclosure.py +306 -0
- ksadk/harness/skill_intent.py +47 -0
- ksadk/harness/skill_runtime.py +74 -16
- ksadk/harness/spec.py +20 -10
- ksadk/harness/state.py +2 -0
- ksadk/harness/stores/__init__.py +14 -0
- ksadk/harness/stores/native_command_settlement.py +65 -0
- ksadk/harness/stores/native_contract.py +311 -0
- ksadk/harness/stores/native_memory.py +326 -0
- ksadk/harness/stores/native_memory_archive.py +70 -0
- ksadk/harness/stores/native_migration_cli.py +91 -0
- ksadk/harness/stores/native_outbox.py +56 -0
- ksadk/harness/stores/native_sqlite.py +782 -0
- ksadk/harness/stores/native_sqlite_audit.py +29 -0
- ksadk/harness/stores/native_sqlite_migration.py +252 -0
- ksadk/harness/subagent.py +12 -2
- ksadk/harness/subagent_adapters/checkpoint_recovery.py +120 -0
- ksadk/harness/subagent_adapters/native_background_child.py +803 -0
- ksadk/harness/subagent_adapters/native_child.py +819 -0
- ksadk/harness/subagent_adapters/native_child_approval.py +128 -0
- ksadk/harness/subagent_adapters/native_child_continuation.py +51 -0
- ksadk/harness/subagent_adapters/native_child_result.py +392 -0
- ksadk/harness/subagent_adapters/prepared_recovery.py +120 -0
- ksadk/harness/tool_display.py +75 -0
- ksadk/harness/tool_display_contract.py +134 -0
- ksadk/harness/tool_output.py +141 -0
- ksadk/harness/tool_policy.py +3 -0
- ksadk/harness/tool_result_policy.py +216 -0
- ksadk/harness/tools.py +52 -0
- ksadk/harness/workspace_adapters/__init__.py +6 -0
- ksadk/harness/workspace_adapters/native_directory.py +180 -0
- ksadk/harness/workspace_adapters/native_git.py +208 -0
- ksadk/harness/workspace_adapters/native_isolation.py +350 -0
- ksadk/interaction/providers/langgraph.py +8 -1
- ksadk/kernel/bootstrap.py +144 -160
- ksadk/kernel/contract_fingerprints.py +45 -1
- ksadk/kernel/contracts.py +25 -0
- ksadk/kernel/control.py +153 -33
- ksadk/kernel/execution_grants.py +209 -2
- ksadk/kernel/execution_grants_memory.py +127 -8
- ksadk/kernel/execution_grants_postgres.py +188 -10
- ksadk/kernel/execution_grants_sqlite.py +235 -9
- ksadk/kernel/execution_host_ingress.py +1071 -0
- ksadk/kernel/history_projection.py +120 -0
- ksadk/kernel/ingress.py +117 -204
- ksadk/kernel/ingress_bootstrap.py +268 -0
- ksadk/kernel/legacy_history.py +179 -0
- ksadk/kernel/memory_store.py +38 -48
- ksadk/kernel/memory_store_projection.py +63 -0
- ksadk/kernel/postgres_event_log.py +181 -0
- ksadk/kernel/postgres_store.py +167 -198
- ksadk/kernel/readiness.py +125 -0
- ksadk/kernel/recovery.py +89 -3
- ksadk/kernel/recovery_projection.py +124 -0
- ksadk/kernel/runtime_checkpoint.py +34 -0
- ksadk/kernel/sql/001_agent_kernel.sql +5 -0
- ksadk/kernel/sqlite_schema.py +100 -0
- ksadk/kernel/sqlite_store.py +147 -216
- ksadk/kernel/store.py +47 -15
- ksadk/kernel/teams_artifact_tools.py +392 -0
- ksadk/kernel/teams_effects.py +851 -0
- ksadk/kernel/teams_execution_context.py +408 -0
- ksadk/kernel/teams_host_http.py +237 -0
- ksadk/kernel/teams_material_transport.py +245 -0
- ksadk/kernel/teams_materials.py +318 -0
- ksadk/kernel/teams_runtime_bootstrap.py +604 -0
- ksadk/kernel/teams_tool_runtime.py +273 -0
- ksadk/kernel/teams_workspace.py +259 -0
- ksadk/kernel/worker.py +323 -332
- ksadk/kernel/worker_controls.py +454 -0
- ksadk/kernel/worker_identity.py +27 -0
- ksadk/kernel/worker_interactions.py +197 -0
- ksadk/knowledge_base/client.py +15 -1
- ksadk/managed_runtime.py +29 -2
- ksadk/memory/adk/backends/http_ltm_backend.py +2 -1
- ksadk/memory/adk/backends/sdk_ltm_backend.py +15 -1
- ksadk/memory/adk/bounded_database_session_service.py +232 -0
- ksadk/memory/adk/resilient_session_service.py +115 -15
- ksadk/memory/adk/short_term_memory.py +8 -9
- ksadk/memory/extraction.py +120 -7
- ksadk/memory/providers/local_candidates.py +183 -0
- ksadk/memory/providers/local_sqlite.py +252 -78
- ksadk/memory/resolved_policy.py +12 -7
- ksadk/model_gateway/__init__.py +29 -0
- ksadk/model_gateway/client.py +253 -0
- ksadk/model_gateway/events.py +113 -0
- ksadk/model_gateway/matrix.py +297 -0
- ksadk/model_proxy/compat.py +670 -0
- ksadk/model_proxy/server.py +10 -7
- ksadk/model_proxy/transform.py +37 -9
- ksadk/plugins/bridges/dsh.py +18 -20
- ksadk/plugins/bridges/dsh_profile_manifest.py +36 -0
- ksadk/plugins/builtin_resources.py +199 -0
- ksadk/plugins/builtins.py +380 -186
- ksadk/plugins/context_contributor.py +15 -4
- ksadk/plugins/dsh_dependency_policy.py +41 -0
- ksadk/plugins/dsh_toolchain.py +24 -35
- ksadk/plugins/execution_host.py +8 -0
- ksadk/plugins/host.py +73 -5
- ksadk/plugins/kernel_adapter.py +44 -1
- ksadk/plugins/memory_provider.py +180 -0
- ksadk/plugins/providers/_process_group.py +50 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +24 -2
- 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-tools/package.json +1 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +1 -1
- ksadk/plugins/providers/codex.py +42 -38
- ksadk/plugins/providers/codex_native.py +20 -0
- ksadk/plugins/providers/codex_skills.py +46 -0
- ksadk/plugins/providers/dsh_capabilities.py +16 -171
- ksadk/plugins/providers/dsh_connector_lease.py +225 -0
- ksadk/plugins/providers/dsh_mcp.py +163 -1
- ksadk/plugins/providers/harness.py +247 -34
- ksadk/plugins/providers/harness_context.py +61 -0
- ksadk/plugins/providers/harness_contributions.py +241 -0
- ksadk/plugins/providers/harness_delegation.py +91 -14
- ksadk/plugins/providers/harness_hooks.py +121 -0
- ksadk/plugins/providers/harness_managed.py +269 -175
- ksadk/plugins/providers/harness_tools.py +165 -36
- ksadk/plugins/providers/legacy_catalog.py +1 -1
- ksadk/plugins/providers/mcp_projection.py +100 -3
- ksadk/plugins/providers/platform_resources.py +16 -6
- ksadk/plugins/teams/application.py +3 -143
- ksadk/plugins/teams/build_artifacts.py +460 -0
- ksadk/plugins/teams/cloud_contract_fingerprints.py +22 -0
- ksadk/plugins/teams/cloud_contracts.py +928 -0
- ksadk/plugins/teams/cloud_permits.py +250 -0
- ksadk/plugins/teams/domain.py +201 -148
- ksadk/plugins/teams/effect_contracts.py +255 -0
- ksadk/plugins/teams/execution_projection.py +255 -0
- ksadk/plugins/teams/leader_decisions.py +106 -0
- ksadk/plugins/teams/postgres_store.py +299 -85
- ksadk/plugins/teams/release_contracts.py +60 -0
- ksadk/plugins/teams/runtime.py +116 -40
- ksadk/plugins/teams/store.py +214 -6
- ksadk/plugins/teams/task_decisions.py +21 -8
- ksadk/plugins/teams/tool_service.py +152 -0
- ksadk/plugins/teams/transport.py +8 -3
- ksadk/resource_runtime/skill_runtime.py +3 -0
- ksadk/resource_runtime/socket_server.py +11 -0
- ksadk/resource_runtime/worker.py +28 -4
- ksadk/runners/_adk_a2a_stream.py +122 -0
- ksadk/runners/_adk_canonical_stream.py +474 -0
- ksadk/runners/_langgraph_canonical_streams.py +527 -0
- ksadk/runners/_langgraph_runner_streams.py +6 -400
- ksadk/runners/_langgraph_tool_projection.py +86 -0
- ksadk/runners/_langgraph_tools_transformer.py +27 -0
- ksadk/runners/adk_runner.py +195 -290
- ksadk/runners/base_runner.py +6 -5
- ksadk/runners/langgraph_runner.py +82 -86
- ksadk/runners/utils/loader.py +28 -14
- ksadk/runtime/_runner_adapter/a2ui_surface.py +145 -0
- ksadk/runtime/_runner_adapter/gateway_approvals.py +93 -0
- ksadk/runtime/_runner_adapter/stream_mapping.py +83 -128
- ksadk/runtime/adapter.py +40 -3
- ksadk/runtime/conversation_execution.py +4 -2
- ksadk/runtime/executor.py +97 -7
- ksadk/runtime/factory.py +13 -6
- ksadk/runtime/framework_adapters.py +184 -10
- ksadk/runtime/hosted_finalizer.py +4 -6
- ksadk/runtime/launch.py +2 -0
- ksadk/runtime/runner_adapter.py +123 -13
- ksadk/runtime_context.py +2 -0
- ksadk/sandbox/backends/e2b.py +30 -4
- ksadk/sandbox/backends/local_process.py +10 -0
- ksadk/sandbox/e2b_connection.py +9 -1
- ksadk/sandbox/local_controls.py +32 -2
- ksadk/sandbox/local_launcher.py +34 -0
- ksadk/server/factory.py +178 -25
- ksadk/server/history_deadline.py +158 -0
- ksadk/server/history_page_cache.py +129 -0
- ksadk/server/routes/checkpoint_audit.py +88 -0
- ksadk/server/routes/checkpoint_listing.py +294 -0
- ksadk/server/routes/checkpoint_resolution.py +73 -20
- ksadk/server/routes/control.py +51 -3
- ksadk/server/routes/display_projection.py +154 -0
- ksadk/server/routes/kernel_ingress.py +17 -2
- ksadk/server/routes/misc.py +102 -12
- ksadk/server/routes/models.py +25 -1
- ksadk/server/routes/openai_compat.py +6 -0
- ksadk/server/routes/projection.py +159 -216
- ksadk/server/routes/run.py +6 -2
- ksadk/server/routes/sessions.py +301 -342
- ksadk/server/routes/streaming.py +68 -15
- ksadk/server/routes/tool_receipt_claim_routes.py +107 -0
- ksadk/server/routes/workspace.py +5 -2
- ksadk/server/static/assets/{ArtifactsPanel-C1YoaKhx.js → ArtifactsPanel-CILaW-fC.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-DHuAWfr5.js → CodeBlock-BVrNVtJC.js} +1 -1
- ksadk/server/static/assets/{MathMessageMarkdown-cvdrBwYr.js → MathMessageMarkdown-Dp7c4wWD.js} +1 -1
- ksadk/server/static/assets/{MermaidBlock-DeBkbJvI.js → MermaidBlock-Dxop8Rd7.js} +6 -6
- ksadk/server/static/assets/{NativeTerminalPanel-oJj44_sV.js → NativeTerminalPanel-Cjjz8B30.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-Dhfv25o2.js → abnfDiagram-VCTEODGH-ckWDmOzw.js} +1 -1
- ksadk/server/static/assets/{arc-C35w-pn1.js → arc-DqxJede-.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-pn_DuLy6.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-FoMY_u6D.js → architectureDiagram-5GKGNRK7-SEQA4bVi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-zD4Rt7oE.js → blockDiagram-NRAW4CY4-pM0B-6NJ.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BCtGGkhN.js → c4Diagram-UCG6FXSJ-m2tuCNVq.js} +1 -1
- ksadk/server/static/assets/channel-fySsnkft.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-BheGxKRQ.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-C2Ms13_k.js → chunk-5VM5RSS4-GJHDr9Ww.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-BoTj-qgx.js → chunk-F27PBJKO-CbAN45AV.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-DOMyyjHH.js → chunk-G27WJ6UU-D5ngbbzF.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DbJJqDli.js → chunk-JWPE2WC7-Cc5IwuYC.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CLuRCt_W.js → chunk-LCL6LL3I-CprgDDdJ.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-D0Dz847e.js → chunk-POPQ4Y6H-CDZhSy82.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-BWSRzEcd.js → chunk-RHFEMEQ7-CZchUNro.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-CPoHqkCY.js → chunk-SVP7TREG-BVruqk6T.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-Bx1jS-X-.js → chunk-XXDRQBXY-4ld9SxPN.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-DSfLtNYm.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-DSfLtNYm.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-LzyWm4m0.js → cose-bilkent-JH36ORCC-Dmyyk_Vp.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-PFWIGtvA.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-BlW_bHED.js → cynefinDiagram-5FMLGOSQ-BIyq3EJb.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-Bu_S86_i.js → dagre-3AP2YEHR-eBw08Qdk.js} +1 -1
- ksadk/server/static/assets/{dagre-B7nCawed.js → dagre-DfvnEf45.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-W_Zow2Km.js → diagram-S7CK7UJ4-CUSrE3Mg.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-CLIKAHON.js → diagram-UQ7AKVKN-Dq5Zw2gy.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-Dv6_QAlN.js → diagram-VSXAHHWV-DyUHfNwT.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-BWAWRDtZ.js → diagram-VX7I27RA-CREmM89O.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-XA_rWMss.js → diagram-Z3DM3KII-Dw9zhHUK.js} +1 -1
- ksadk/server/static/assets/{dist-CGt_UGeO.js → dist-0uJ4tdx6.js} +1 -1
- ksadk/server/static/assets/{dist-C0J5_3qM.js → dist-AEv-vXf-.js} +1 -1
- ksadk/server/static/assets/{dist-CIpWk_5f.js → dist-B49GzZDb.js} +1 -1
- ksadk/server/static/assets/{dist-B3bA05-e.js → dist-B8Myiet9.js} +1 -1
- ksadk/server/static/assets/{dist-DWfdmz9s.js → dist-BBsYarrI.js} +1 -1
- ksadk/server/static/assets/{dist-BLpRy_Yx.js → dist-BQMrUwdI.js} +1 -1
- ksadk/server/static/assets/{dist-CIRMvUM4.js → dist-BX_-FENW.js} +1 -1
- ksadk/server/static/assets/{dist-BdNFAney.js → dist-CD4L6ymH.js} +1 -1
- ksadk/server/static/assets/{dist-n3n6t_FO.js → dist-CHpW1BHj.js} +1 -1
- ksadk/server/static/assets/{dist-DppE_r-D.js → dist-CVPau3tn.js} +1 -1
- ksadk/server/static/assets/{dist-qe8xjesy.js → dist-C_qdxcSH.js} +1 -1
- ksadk/server/static/assets/{dist-2vL2sAdF.js → dist-Co68Apq4.js} +1 -1
- ksadk/server/static/assets/{dist-1nXCdsej.js → dist-Cp2PaOMY.js} +1 -1
- ksadk/server/static/assets/{dist-DNKuMzWc.js → dist-CuR5Bgme.js} +1 -1
- ksadk/server/static/assets/{dist-t6MzE0jU.js → dist-DDSyLEOX.js} +1 -1
- ksadk/server/static/assets/{dist-CPyieXEf.js → dist-DUxO0R99.js} +1 -1
- ksadk/server/static/assets/{dist-DyG6Ya-z.js → dist-QzbGrED_.js} +1 -1
- ksadk/server/static/assets/{dist-0X_j2Rcc.js → dist-bupkyEBZ.js} +1 -1
- ksadk/server/static/assets/{dist-mqD5TZup.js → dist-cxTGfdqx.js} +1 -1
- ksadk/server/static/assets/{dist-M-SrdhhZ.js → dist-hL5p1til.js} +1 -1
- ksadk/server/static/assets/{dist-D-92S-Fd.js → dist-lOy23y43.js} +1 -1
- ksadk/server/static/assets/{dist-BO_UwatH.js → dist-pq-nD33R.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-BfCzF1Xi.js → ebnfDiagram-PWID7BFC-BS5LdNoR.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-Dpz9_0zn.js → erDiagram-SSCWMZ5O-Bv1QtiY-.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-DsM4upQX.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-D5NA16k9.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-DDaG1f4_.js → ganttDiagram-EL5Y4UJY-musi-e0G.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-DUCVz-ih.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DcxzRwYC.js → gitGraphDiagram-WWUBYQGX-DH37EGkG.js} +1 -1
- ksadk/server/static/assets/index-CZdkAvsv.js +244 -0
- ksadk/server/static/assets/index-CvXdHgF3.css +2 -0
- ksadk/server/static/assets/info-A6RAGUB7-rw0ZNHZp.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CYMdn6lQ.js → infoDiagram-RXCK75RN-C1kEtv2y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CLHFAD6c.js → ishikawaDiagram-5VMMS53U-BCNPyMka.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-BHSKQGAl.js → journeyDiagram-EYS64GPL--cDbKnjP.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-D5W3tjTT.js → kanban-definition-3QL26DDD-R1rAVw2f.js} +1 -1
- ksadk/server/static/assets/{katex-mtjOi4KM.js → katex-BT-X-V7U.js} +1 -1
- ksadk/server/static/assets/{linear-BETqsxE_.js → linear-DTR631iG.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-DPWrvs90.js → mermaid-parser.core-DfFzJhX8.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-CJG2mfBP.js → mindmap-definition-FBJOCRG2-D4by_rmk.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-Ca4Hvki9.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-GjAPNaqn.js → pegDiagram-XKGWAZYB-xWXPEh0c.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-hwiz6fbw.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-ToIewrqr.js → pieDiagram-E7YTZNPT-BudBDlCI.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-4d78KiEY.js → quadrantDiagram-AXDQQJYC-DXZ0PCJF.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-BR1oZXLM.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-DfgEISfX.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-CWOC3rdk.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-CiRvHCLY.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-DSDDyJ2f.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-DKzx4xfv.js → railroadDiagram-O6MQD6OU-BdAYRYB8.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-CJYljxQS.js → requirementDiagram-EFPCY7ZU-CBBmaL70.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-DLU2fV1w.js → sankeyDiagram-P5KCCOFB-Doc3rdwp.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CVqysrA9.js → sequenceDiagram-WJ2MYXX4-0J8R8hWW.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-BUxfmTHc.js → sizeCapture-X5ZJPWSS-CfFLlWsK.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-CNFgYI9E.js → stateDiagram-HBIQ2CUA-jBwkjtTy.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-Cw1fPb5w.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-B6qCMe8N.js → swimlanes-XN3QIQJK-B0WxTQf8.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-Cc3JMBAF.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-CMD3x_U_.js → timeline-definition-24CTP7MA-BfCT_75A.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-C05SJHxo.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-BqNLAhc3.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-BqtUqvXM.js → vennDiagram-4TSXK5OY-9gX1VMDC.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-DokNktqB.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-B5KfDjI-.js → wardleyDiagram-VM6X3IG4-sEs_BP6O.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BaUlSZrn.js → xychartDiagram-S5SC5T6Z-Ll4jvUN9.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/sessions/__init__.py +8 -1
- ksadk/sessions/_checkpoint_resume_audit.py +44 -0
- ksadk/sessions/_in_memory_query.py +112 -0
- ksadk/sessions/_local_service_sync.py +157 -156
- ksadk/sessions/_local_state_sync.py +152 -0
- ksadk/sessions/_local_tables.py +2 -0
- ksadk/sessions/_postgres_checkpoint_read.py +323 -0
- ksadk/sessions/_postgres_checkpoint_stats.py +330 -0
- ksadk/sessions/_postgres_history_read.py +678 -0
- ksadk/sessions/_postgres_schema.py +44 -2
- ksadk/sessions/_postgres_tables.py +2 -0
- ksadk/sessions/_postgres_tool_receipts.py +169 -0
- ksadk/sessions/_resilient_read.py +630 -0
- ksadk/sessions/_tool_receipt_sync.py +119 -0
- ksadk/sessions/agent_identity.py +16 -0
- ksadk/sessions/base.py +278 -0
- ksadk/sessions/db_budget.py +332 -0
- ksadk/sessions/errors.py +12 -0
- ksadk/sessions/history_budget.py +36 -0
- ksadk/sessions/history_identity.py +27 -0
- ksadk/sessions/in_memory.py +376 -113
- ksadk/sessions/local_service.py +345 -0
- ksadk/sessions/postgres_service.py +515 -549
- ksadk/sessions/resilience.py +21 -14
- ksadk/sessions/resilient.py +611 -504
- ksadk/skills/loader.py +44 -2
- ksadk/skills/runtime/backends/e2b.py +17 -14
- ksadk/skills/service_client.py +6 -1
- ksadk/studio/a2a_bindings.py +407 -0
- ksadk/studio/a2a_orchestration.py +178 -0
- ksadk/studio/active_run_output.py +92 -0
- ksadk/studio/activity_records.py +542 -0
- ksadk/studio/agent_configuration.py +173 -0
- ksadk/studio/api.py +219 -389
- ksadk/studio/api_a2a_routes.py +93 -0
- ksadk/studio/api_catalog_routes.py +13 -0
- ksadk/studio/api_cloud_chat_routes.py +382 -0
- ksadk/studio/api_contracts.py +23 -0
- ksadk/studio/attachment_store.py +14 -2
- ksadk/studio/build_resolution.py +117 -0
- ksadk/studio/build_singleflight.py +37 -0
- ksadk/studio/builder.py +20 -2
- ksadk/studio/capabilities.py +8 -3
- ksadk/studio/cloud.py +83 -377
- ksadk/studio/cloud_gateways.py +424 -0
- ksadk/studio/cloud_shared_web.py +7 -0
- ksadk/studio/codex_agent_service.py +17 -0
- ksadk/studio/codex_manifest.py +5 -1
- ksadk/studio/codex_provider_build.py +65 -0
- ksadk/studio/compiler.py +102 -6
- ksadk/studio/contract_base.py +19 -0
- ksadk/studio/contracts.py +231 -201
- ksadk/studio/dsh_application.py +58 -12
- ksadk/studio/dsh_capability_service.py +17 -171
- ksadk/studio/dsh_mcp_transport.py +191 -0
- ksadk/studio/event_store.py +17 -0
- ksadk/studio/execution_host.py +84 -11
- ksadk/studio/framework_run.py +18 -0
- ksadk/studio/interaction_submission.py +265 -0
- ksadk/studio/kernel_registry.py +12 -1
- ksadk/studio/lifecycle_status.py +43 -0
- ksadk/studio/model_buffered_wire.py +227 -0
- ksadk/studio/model_chat_tools.py +143 -0
- ksadk/studio/model_client.py +1241 -761
- ksadk/studio/model_content_stream.py +129 -0
- ksadk/studio/model_credentials.py +196 -0
- ksadk/studio/model_profile_service.py +65 -31
- ksadk/studio/model_request_projection.py +284 -0
- ksadk/studio/model_responses_content.py +296 -0
- ksadk/studio/model_usage.py +109 -0
- ksadk/studio/model_wire_failure.py +110 -0
- ksadk/studio/model_wire_identity.py +138 -0
- ksadk/studio/model_wire_snapshot.py +45 -0
- ksadk/studio/model_wire_tools.py +283 -0
- ksadk/studio/native_acceptance.py +68 -0
- ksadk/studio/native_approval.py +111 -0
- ksadk/studio/native_browser_port.py +861 -0
- ksadk/studio/native_child_mcp.py +87 -0
- ksadk/studio/native_child_publication.py +68 -0
- ksadk/studio/native_child_skills.py +72 -0
- ksadk/studio/native_child_workspace.py +176 -0
- ksadk/studio/native_command_policy.py +53 -0
- ksadk/studio/native_context_port.py +326 -0
- ksadk/studio/native_context_registration.py +54 -0
- ksadk/studio/native_document_input.py +88 -0
- ksadk/studio/native_final_shape.py +852 -0
- ksadk/studio/native_gateway_stream.py +69 -0
- ksadk/studio/native_hook_port.py +145 -0
- ksadk/studio/native_hook_registration.py +70 -0
- ksadk/studio/native_inventory_disclosure.py +223 -0
- ksadk/studio/native_kernel_admission.py +84 -0
- ksadk/studio/native_language_diagnostics.py +320 -0
- ksadk/studio/native_mcp_disclosure.py +198 -0
- ksadk/studio/native_mcp_tool_port.py +219 -0
- ksadk/studio/native_memory_acceptance.py +362 -0
- ksadk/studio/native_memory_context.py +266 -0
- ksadk/studio/native_memory_flush.py +174 -0
- ksadk/studio/native_memory_sources.py +80 -0
- ksadk/studio/native_memory_tool_port.py +360 -0
- ksadk/studio/native_memory_turn.py +183 -0
- ksadk/studio/native_model_port.py +765 -0
- ksadk/studio/native_model_recovery.py +126 -0
- ksadk/studio/native_options.py +75 -0
- ksadk/studio/native_output_fields.py +58 -0
- ksadk/studio/native_planning.py +156 -0
- ksadk/studio/native_product.py +988 -0
- ksadk/studio/native_read_budget.py +426 -0
- ksadk/studio/native_recovery.py +171 -0
- ksadk/studio/native_scope.py +35 -0
- ksadk/studio/native_session_context_port.py +141 -0
- ksadk/studio/native_session_engine.py +14 -0
- ksadk/studio/native_skill_source.py +74 -0
- ksadk/studio/native_subagent_port.py +700 -0
- ksadk/studio/native_terminal_recovery.py +95 -0
- ksadk/studio/native_test_action.py +610 -0
- ksadk/studio/native_tool_port.py +477 -0
- ksadk/studio/native_user_input.py +60 -0
- ksadk/studio/native_verification_presentation.py +65 -0
- ksadk/studio/native_workspace_diagnostics.py +183 -0
- ksadk/studio/native_workspace_port.py +43 -0
- ksadk/studio/operations.py +34 -9
- ksadk/studio/plugin_composition.py +26 -10
- ksadk/studio/plugin_kernel_adapter.py +75 -1
- ksadk/studio/plugin_native_activation.py +163 -0
- ksadk/studio/plugin_runtime.py +639 -119
- ksadk/studio/plugin_runtime_admission.py +57 -0
- ksadk/studio/presentation.py +92 -0
- ksadk/studio/public_output_store.py +69 -0
- ksadk/studio/resource_authority.py +11 -3
- ksadk/studio/resource_catalog.py +8 -12
- ksadk/studio/run_activity.py +338 -385
- ksadk/studio/run_controls.py +185 -0
- ksadk/studio/run_service.py +908 -319
- ksadk/studio/run_submission_receipts.py +68 -0
- ksadk/studio/runtime_catalog.py +23 -4
- ksadk/studio/runtime_prewarm.py +22 -0
- ksadk/studio/scheduler_assistant.py +4 -1
- ksadk/studio/service.py +356 -282
- ksadk/studio/service_settings.py +229 -0
- ksadk/studio/shared_web.py +393 -169
- ksadk/studio/shared_web_response_events.py +180 -0
- ksadk/studio/shared_web_run_state.py +133 -0
- ksadk/studio/skill_discovery.py +305 -3
- ksadk/studio/static/assets/ChannelsPage-xX5HlMId.js +8 -0
- ksadk/studio/static/assets/{CodeBlock-DMIf4h33-UIqo-BPW.js → CodeBlock-DMIf4h33-CkufcPYo.js} +3 -3
- ksadk/studio/static/assets/{MathMessageMarkdown-BesSeCYl-OhNwH4K9.js → MathMessageMarkdown-BesSeCYl-DYG1Wzbx.js} +1 -1
- ksadk/studio/static/assets/{MessageMarkdown-CwMTvgFj-g0I-I4dD.js → MessageMarkdown-CwMTvgFj-BeyLyQHu.js} +2 -2
- ksadk/studio/static/assets/TeamsPage-CCaaGaVp.js +3 -0
- ksadk/studio/static/assets/index-C7DNDik2.css +2 -0
- ksadk/studio/static/assets/index-Cy68gTlH.js +265 -0
- ksadk/studio/static/index.html +3 -3
- ksadk/studio/teams_catalog.py +33 -0
- ksadk/studio/teams_installation.py +4 -1
- ksadk/studio/teams_node.py +4 -0
- ksadk/studio/teams_node_factory.py +558 -0
- ksadk/studio/teams_node_runner.py +3 -0
- ksadk/studio/teams_node_v1.py +935 -0
- ksadk/studio/teams_remote.py +259 -37
- ksadk/studio/templates.py +1 -0
- ksadk/studio/workspace_plugins.py +3 -1
- ksadk/tools/a2a_policy.py +5 -0
- ksadk/tools/artifact_observation.py +53 -0
- ksadk/tools/captured_source_artifact.py +68 -0
- ksadk/tools/schema.py +34 -0
- ksadk/toolsets/__init__.py +82 -88
- ksadk/toolsets/a2a.py +89 -89
- ksadk/toolsets/sandbox.py +377 -6
- ksadk/toolsets/skill_management.py +315 -0
- ksadk/toolsets/tool_selection.py +94 -0
- ksadk/toolsets/workspace.py +342 -324
- ksadk/toolsets/workspace_editing.py +291 -0
- ksadk/toolsets/workspace_model_observation.py +104 -0
- ksadk/toolsets/workspace_mutation.py +75 -0
- ksadk/toolsets/workspace_read_budget.py +216 -0
- ksadk/toolsets/workspace_search.py +192 -0
- ksadk/toolsets/workspace_search_process.py +129 -0
- ksadk/toolsets/workspace_state.py +6 -0
- ksadk/version.py +1 -1
- ksadk_runtime_common/http_headers.py +18 -0
- ksadk_runtime_common/workspace_files/router.py +2 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +0 -1
- ksadk/server/static/assets/channel-_KDifNys.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +0 -1
- ksadk/server/static/assets/index-BMd2mucF.css +0 -2
- ksadk/server/static/assets/index-D5qyyhTH.js +0 -244
- ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +0 -1
- ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +0 -8
- ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +0 -3
- ksadk/studio/static/assets/index-CfEnms6Y.css +0 -2
- ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -0
- {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.5.dist-info → agentengine_sdk_python-0.8.6.dist-info}/top_level.txt +0 -0
|
@@ -7,38 +7,47 @@
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import
|
|
11
|
-
import re
|
|
12
|
-
from typing import Any
|
|
10
|
+
import logging
|
|
13
11
|
|
|
14
12
|
from langgraph.graph import END, START, StateGraph
|
|
15
13
|
from langgraph.types import interrupt
|
|
16
14
|
|
|
17
15
|
from ksadk.harness.engine import budgets
|
|
18
16
|
from ksadk.harness.engine.base import ExecutionEngineError
|
|
17
|
+
from ksadk.harness.engine.hooked_reasoner import (
|
|
18
|
+
_HookedReasoner,
|
|
19
|
+
flush_hook_degradations,
|
|
20
|
+
)
|
|
19
21
|
from ksadk.harness.engine.langgraph import _GraphState
|
|
20
|
-
from ksadk.harness.engine.mcp_disclosure import MCP_CALL_TOOL_TOOL, McpDisclosureCursors
|
|
21
22
|
from ksadk.harness.engine.policy_runtime import revalidate_policy
|
|
22
23
|
from ksadk.harness.engine.spans import wrap_node_span
|
|
23
|
-
from ksadk.harness.engine.subagents import ChildApprovalPending
|
|
24
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
25
|
from ksadk.harness.reasoner import HarnessReasoningTurn
|
|
34
26
|
from ksadk.harness.run_control import ControlAction, RunControlStop
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _model_failure_error(error: ModelFailoverExhausted) -> RuntimeError:
|
|
32
|
+
"""Preserve provider failure facts when the graph boundary wraps errors.
|
|
33
|
+
|
|
34
|
+
The graph engine exposes a plain exception to its outer runner for
|
|
35
|
+
compatibility, but Studio still needs the stable category and HTTP status
|
|
36
|
+
to render an actionable terminal card (especially rate limit 429).
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
wrapped = RuntimeError(str(error))
|
|
40
|
+
failure = error.failure
|
|
41
|
+
# Unknown-kind failures keep the legacy payload shape (no error_category)
|
|
42
|
+
# so sub-agent dispatch still falls back to "child_failed" and applies its
|
|
43
|
+
# retry policy; only classified failures carry their category upstream.
|
|
44
|
+
if failure.kind.value != "unknown":
|
|
45
|
+
setattr(wrapped, "error_category", failure.kind.value)
|
|
46
|
+
if failure.status_code is not None:
|
|
47
|
+
setattr(wrapped, "status_code", failure.status_code)
|
|
48
|
+
if failure.kind.value == "rate_limit":
|
|
49
|
+
setattr(wrapped, "error_code", "MODEL_RATE_LIMITED")
|
|
50
|
+
return wrapped
|
|
42
51
|
|
|
43
52
|
|
|
44
53
|
def build_graph(engine, run):
|
|
@@ -56,8 +65,11 @@ def build_graph(engine, run):
|
|
|
56
65
|
if event.event_type == EventType.USAGE_REPORTED:
|
|
57
66
|
input_tokens = int(event.payload.get("input_tokens") or 0)
|
|
58
67
|
output_tokens = int(event.payload.get("output_tokens") or 0)
|
|
59
|
-
budgets.spend(
|
|
60
|
-
|
|
68
|
+
budgets.spend(
|
|
69
|
+
run,
|
|
70
|
+
"tokens",
|
|
71
|
+
int(event.payload.get("total_tokens") or input_tokens + output_tokens),
|
|
72
|
+
)
|
|
61
73
|
budgets.spend(run, "input_tokens", input_tokens)
|
|
62
74
|
budgets.spend(run, "output_tokens", output_tokens)
|
|
63
75
|
if event.event_type == EventType.ARTIFACT_CREATED:
|
|
@@ -73,6 +85,9 @@ def build_graph(engine, run):
|
|
|
73
85
|
|
|
74
86
|
def _before_model(state: _GraphState) -> None:
|
|
75
87
|
_restore_controller(state)
|
|
88
|
+
if isinstance(engine._reasoner, _HookedReasoner):
|
|
89
|
+
# G5 §5.2:包装后的 Reasoner 从活跃 Run 取钩子上下文(模型调用节点统一设置)。
|
|
90
|
+
engine._active_hook_run = run
|
|
76
91
|
if run.controller is None:
|
|
77
92
|
budgets.check(run, "tokens", 0)
|
|
78
93
|
budgets.check(run, "models")
|
|
@@ -124,262 +139,22 @@ def build_graph(engine, run):
|
|
|
124
139
|
state["turn_count"] += 1
|
|
125
140
|
# 收口 5:Turn 区间事件(模型/工具/usage 事件按 seq 落在区间内)。
|
|
126
141
|
turn_id = f"{run.handle.run_id}:t{state['turn_count']}"
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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)
|
|
142
|
+
# Native Harness Phase 1:reason 主体已抽出为引擎无关的纯函数 handler
|
|
143
|
+
# (engine/phases/reason.py)。本包装负责图内前置(策略重校验 / _before_model
|
|
144
|
+
# / turn_count / turn_id 构造),handler 负责 turn 区间内全部事件与状态推进。
|
|
145
|
+
from ksadk.harness.engine.phases.context import PhaseContext
|
|
146
|
+
from ksadk.harness.engine.phases.reason import reason_phase
|
|
147
|
+
|
|
148
|
+
ctx = PhaseContext(spec=spec, run=run, engine=engine, turn_id=turn_id, state=state)
|
|
149
|
+
result = await reason_phase(ctx)
|
|
150
|
+
state.update(result.state)
|
|
151
|
+
# Phase 1 过渡期:handler 仍直接写 run.events/run.seq,故此处仅作纵深防御
|
|
152
|
+
# (seq_id 已推进时不再重复 append;Phase 2 切断直写后此循环成为唯一出口)。
|
|
153
|
+
for ev in result.events:
|
|
154
|
+
if ev.seq_id > run.seq:
|
|
155
|
+
run.events.append(ev)
|
|
156
|
+
run.seq = max(run.seq, ev.seq_id)
|
|
157
|
+
_capture_control_event(ev)
|
|
383
158
|
return state
|
|
384
159
|
|
|
385
160
|
async def tool_calls(state: _GraphState) -> _GraphState:
|
|
@@ -387,361 +162,62 @@ def build_graph(engine, run):
|
|
|
387
162
|
_restore_controller(state)
|
|
388
163
|
run.child_approval_decision = state.get("child_approval_decision")
|
|
389
164
|
state["child_approval_decision"] = {}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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 []
|
|
165
|
+
# Native Harness Phase 1:tool_calls 主体已抽出为引擎无关的纯函数 handler
|
|
166
|
+
# (engine/phases/tools.py)。本包装负责图内前置(策略重校验 / 控制器恢复 /
|
|
167
|
+
# child-approval 决定接收)与**挂起原语翻译**:handler 返回 NeedInteraction
|
|
168
|
+
# 表示需要外部交互,LangGraph 侧在此调 interrupt() 挂起,resume 后把决定写回
|
|
169
|
+
# 状态并重新进入 handler(同一节点调用内循环,故前置只执行一次——与旧
|
|
170
|
+
# interrupt() 语义下"节点整体重放"的次数一致)。
|
|
171
|
+
from ksadk.harness.engine.phases.context import PhaseContext
|
|
172
|
+
from ksadk.harness.engine.phases.tools import (
|
|
173
|
+
TOOL_APPROVAL_DECISION_KEY,
|
|
174
|
+
TOOL_APPROVAL_REPLAY_ATTR,
|
|
175
|
+
tools_phase,
|
|
511
176
|
)
|
|
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
177
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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")
|
|
178
|
+
# 重放检测:引擎在挂起时把审批 call_id 记到 run.pending_approval_call_id,
|
|
179
|
+
# attach 亦会从 Checkpoint 重建它(跨进程恢复同样成立)。resume 后 LangGraph
|
|
180
|
+
# 整体重放本节点,而重放期间 handler 仍拿不到决定(决定要等下面 interrupt()
|
|
181
|
+
# 返回)会再走一次挂起分支;旧实现里那一次是 interrupt() 内联返回决定、不走
|
|
182
|
+
# 异常分支,故 handler 据此跳过重复补发的失败态进度。Phase 2 Native 引擎以
|
|
183
|
+
# NeedInteraction 表达挂起,不需该标记。
|
|
184
|
+
setattr(
|
|
185
|
+
run,
|
|
186
|
+
TOOL_APPROVAL_REPLAY_ATTR,
|
|
187
|
+
str(getattr(run, "pending_approval_call_id", "") or ""),
|
|
600
188
|
)
|
|
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
189
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
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
|
|
190
|
+
ctx = PhaseContext(spec=spec, run=run, engine=engine, turn_id="", state=state)
|
|
191
|
+
while True:
|
|
192
|
+
result = await tools_phase(ctx)
|
|
193
|
+
state.update(result.state)
|
|
194
|
+
# Phase 1 过渡期:handler 仍直接写 run.events/run.seq,故此处仅作纵深防御
|
|
195
|
+
# (seq_id 已推进时不再重复 append;Phase 2 切断直写后此循环成为唯一出口)。
|
|
196
|
+
for ev in result.events:
|
|
197
|
+
if ev.seq_id > run.seq:
|
|
198
|
+
run.events.append(ev)
|
|
199
|
+
run.seq = max(run.seq, ev.seq_id)
|
|
200
|
+
_capture_control_event(ev)
|
|
201
|
+
if result.interaction is None:
|
|
202
|
+
return state
|
|
203
|
+
if result.interaction.kind == "child_approval":
|
|
204
|
+
# Phase 1:子 Agent 审批仍由专用 ``child_approval`` 节点挂起
|
|
205
|
+
# (route="child_approval" 由 handler 写入)。不在本节点内 interrupt 的
|
|
206
|
+
# 实测原因:在**已 resume 过**的 tool_calls 任务里再次 interrupt,
|
|
207
|
+
# LangGraph 会把 Checkpoint 的 ``next`` 清空,attach 无法从 snapshot
|
|
208
|
+
# 推断挂起(test_second_child_approval_never_reuses_first_decision)。
|
|
209
|
+
# handler 仍把 child_approval NeedInteraction 显式交还,供 Phase 2
|
|
210
|
+
# Native 引擎直接挂起(届时不再需要图节点)。
|
|
211
|
+
return state
|
|
212
|
+
payload = result.interaction.request_payload
|
|
213
|
+
# LangGraph suspension: interrupt() resumes with the approval decision.
|
|
214
|
+
decision = interrupt(payload)
|
|
215
|
+
state[TOOL_APPROVAL_DECISION_KEY] = {
|
|
216
|
+
"call_id": str(payload.get("call_id") or ""),
|
|
217
|
+
"decision": decision,
|
|
218
|
+
}
|
|
219
|
+
# Re-enter tools to execute the now-decided call.
|
|
694
220
|
|
|
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
221
|
|
|
746
222
|
def route(state: _GraphState) -> str:
|
|
747
223
|
return state["route"]
|
|
@@ -757,12 +233,16 @@ def build_graph(engine, run):
|
|
|
757
233
|
async def plan_node(state: _GraphState) -> _GraphState:
|
|
758
234
|
"""plan-execute 拓扑的规划节点:一次无工具模型调用产出执行计划。"""
|
|
759
235
|
_before_model(state)
|
|
236
|
+
reasoning_effort = str(run.request.config.get("effort") or "").strip().lower() or None
|
|
760
237
|
turn: HarnessReasoningTurn = await engine._reasoner.complete(
|
|
761
238
|
model=spec.model.profile_ref,
|
|
762
239
|
prompt=(spec.prompt.instructions or "") + "\n请先给出分步执行计划,再开始执行。",
|
|
763
240
|
messages=tuple(state["messages"]),
|
|
764
241
|
tools=[],
|
|
242
|
+
**({"reasoning_effort": reasoning_effort} if reasoning_effort else {}),
|
|
765
243
|
)
|
|
244
|
+
# 直接调 Reasoner 的节点也要先 flush 降级再发自己的后续事件,保持 seq 单调。
|
|
245
|
+
flush_hook_degradations(engine, run)
|
|
766
246
|
state["messages"].append(
|
|
767
247
|
{"role": "assistant", "content": "【执行计划】\n" + (turn.final_text or "")}
|
|
768
248
|
)
|
|
@@ -782,6 +262,7 @@ def build_graph(engine, run):
|
|
|
782
262
|
async def review_node(state: _GraphState) -> _GraphState:
|
|
783
263
|
"""plan-execute-review 拓扑的独立审查节点:对最终回答做一次批判。"""
|
|
784
264
|
_before_model(state)
|
|
265
|
+
reasoning_effort = str(run.request.config.get("effort") or "").strip().lower() or None
|
|
785
266
|
messages = list(state["messages"]) + [
|
|
786
267
|
{"role": "user", "content": "请审查以上回答的准确性与遗漏,指出问题(如有)。"}
|
|
787
268
|
]
|
|
@@ -790,7 +271,9 @@ def build_graph(engine, run):
|
|
|
790
271
|
prompt=spec.prompt.instructions or "",
|
|
791
272
|
messages=tuple(messages),
|
|
792
273
|
tools=[],
|
|
274
|
+
**({"reasoning_effort": reasoning_effort} if reasoning_effort else {}),
|
|
793
275
|
)
|
|
276
|
+
flush_hook_degradations(engine, run)
|
|
794
277
|
state["messages"].append(
|
|
795
278
|
{"role": "assistant", "content": "【审查】\n" + (turn.final_text or "")}
|
|
796
279
|
)
|
|
@@ -839,6 +322,10 @@ def build_graph(engine, run):
|
|
|
839
322
|
reason_mapping = {}
|
|
840
323
|
if "tool_calls" in reason_successors:
|
|
841
324
|
reason_mapping["tool_calls"] = "tool_calls"
|
|
325
|
+
# A live user correction may arrive while the final model response is in
|
|
326
|
+
# flight. The reason handler rejects that stale candidate and re-enters
|
|
327
|
+
# itself with the accepted correction, even for text-only plans.
|
|
328
|
+
reason_mapping["reason"] = "reason"
|
|
842
329
|
reason_mapping["final"] = END if exit_target == "final" else exit_target
|
|
843
330
|
if "reason" in node_impls and "reason" in plan.nodes and "reason" != exit_target:
|
|
844
331
|
builder.add_conditional_edges("reason", route, reason_mapping)
|
|
@@ -846,9 +333,15 @@ def build_graph(engine, run):
|
|
|
846
333
|
if src == "reason":
|
|
847
334
|
continue # 已由条件边覆盖。
|
|
848
335
|
if src == "tool_calls":
|
|
849
|
-
builder.add_conditional_edges(
|
|
850
|
-
"tool_calls"
|
|
851
|
-
|
|
336
|
+
builder.add_conditional_edges(
|
|
337
|
+
"tool_calls",
|
|
338
|
+
route,
|
|
339
|
+
{
|
|
340
|
+
"tool_calls": "tool_calls",
|
|
341
|
+
"child_approval": "child_approval",
|
|
342
|
+
"reason": dst,
|
|
343
|
+
},
|
|
344
|
+
)
|
|
852
345
|
continue
|
|
853
346
|
if dst == "final":
|
|
854
347
|
if src in node_impls and src != "reason":
|