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
|
@@ -0,0 +1,974 @@
|
|
|
1
|
+
"""Pure runtime decisions. The Store is the sole owner of committed state."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from .completion_text import abandon_continuation, complete_continuation, fragment_digest
|
|
9
|
+
from .delivery_review import delivery_review_readers, reduce_delivery_review, review_pending
|
|
10
|
+
from .final_output import normalize_final_output
|
|
11
|
+
from .final_submission import FINAL_SUBMISSION_TOOL, submitted_final_text
|
|
12
|
+
from .guidance import apply_guidance
|
|
13
|
+
from .interaction_observation import advance_browser_observation, advance_interaction_observation
|
|
14
|
+
from .model import ModelTurnResult
|
|
15
|
+
from .model_feedback import model_feedback_messages
|
|
16
|
+
from .model_replay import replay_binding_failure, replay_fields
|
|
17
|
+
from .model_tool_batch import begin_tool_batch
|
|
18
|
+
from .output_recovery import output_recovery_mode
|
|
19
|
+
from .ports import (
|
|
20
|
+
ArtifactRef,
|
|
21
|
+
RunConfiguration,
|
|
22
|
+
ToolResult,
|
|
23
|
+
WorkspaceObservation,
|
|
24
|
+
)
|
|
25
|
+
from .state import (
|
|
26
|
+
CommitBatch,
|
|
27
|
+
RunCommand,
|
|
28
|
+
RunPhase,
|
|
29
|
+
RunSnapshot,
|
|
30
|
+
move,
|
|
31
|
+
workspace_observation_cursor,
|
|
32
|
+
)
|
|
33
|
+
from .steering import apply_steering
|
|
34
|
+
from .task_progress import TODO_WRITE_NAME, parse_task_progress
|
|
35
|
+
from .terminal_verification import prepare_terminal_verification
|
|
36
|
+
from .tool_budget import (
|
|
37
|
+
dispatch_tool_budget,
|
|
38
|
+
finalization_only,
|
|
39
|
+
model_tool_surface,
|
|
40
|
+
model_turn_control,
|
|
41
|
+
refuse_pending_batch,
|
|
42
|
+
refused_pending_tools,
|
|
43
|
+
tools_exhausted,
|
|
44
|
+
)
|
|
45
|
+
from .tool_error_streak import advance_tool_error_streak, tool_error_streak_exhausted
|
|
46
|
+
from .tool_hook_runtime import (
|
|
47
|
+
hook_execution_metadata,
|
|
48
|
+
prepare_tool_hook,
|
|
49
|
+
tool_hook_feedback_messages,
|
|
50
|
+
)
|
|
51
|
+
from .tool_observation import (
|
|
52
|
+
append_executed_tool_message,
|
|
53
|
+
executed_tool_message,
|
|
54
|
+
parallel_result_violation,
|
|
55
|
+
)
|
|
56
|
+
from .tool_progress import tool_progress_feedback
|
|
57
|
+
from .tool_scheduling import scheduled_tool_calls
|
|
58
|
+
from .transitions import commit_transition, finish, prepare_effect
|
|
59
|
+
from .user_input import current_user_has_media
|
|
60
|
+
from .verification_workspace import changed_verification_subject
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def reduce_command(
|
|
64
|
+
snapshot: RunSnapshot,
|
|
65
|
+
command: RunCommand,
|
|
66
|
+
*,
|
|
67
|
+
bound_tool_names: frozenset[str] | None = None,
|
|
68
|
+
guidance_enabled: bool = False,
|
|
69
|
+
replay_configuration: RunConfiguration | None = None,
|
|
70
|
+
) -> CommitBatch:
|
|
71
|
+
kind, updated, reason = command.kind, snapshot, "applied"
|
|
72
|
+
extra = ()
|
|
73
|
+
if kind == "cancel":
|
|
74
|
+
updated = move(snapshot, RunPhase.CANCELED).model_copy(
|
|
75
|
+
update={
|
|
76
|
+
"outcome": "unverified",
|
|
77
|
+
"reason": "user_canceled",
|
|
78
|
+
"pending_intent": None,
|
|
79
|
+
"pending_interaction": None,
|
|
80
|
+
"interaction_host_id": None,
|
|
81
|
+
"interaction": None,
|
|
82
|
+
"child_approval": None,
|
|
83
|
+
"pending_tools": (),
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
elif kind == "policy_revoked":
|
|
87
|
+
# A revoked Run cannot enter steerable finalization or promote its
|
|
88
|
+
# previous candidate. Its accepted inbox is settled by the Store.
|
|
89
|
+
updated = move(snapshot, RunPhase.FAILED).model_copy(
|
|
90
|
+
update={
|
|
91
|
+
"outcome": "blocked",
|
|
92
|
+
"reason": "policy_revoked",
|
|
93
|
+
"pending_intent": None,
|
|
94
|
+
"pending_interaction": None,
|
|
95
|
+
"interaction_host_id": None,
|
|
96
|
+
"interaction": None,
|
|
97
|
+
"child_approval": None,
|
|
98
|
+
"pending_tools": (),
|
|
99
|
+
"final_text": "",
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
elif kind == "pause":
|
|
103
|
+
if snapshot.phase == RunPhase.PAUSED:
|
|
104
|
+
reason = "already_paused"
|
|
105
|
+
else:
|
|
106
|
+
updated = move(snapshot, RunPhase.PAUSED)
|
|
107
|
+
elif kind == "resume" and snapshot.phase == RunPhase.PAUSED:
|
|
108
|
+
updated = move(snapshot, snapshot.paused_from or RunPhase.PREPARING_CONTEXT)
|
|
109
|
+
elif kind == "submit_interaction" and snapshot.phase == RunPhase.AWAITING_INTERACTION:
|
|
110
|
+
if command.payload.get(
|
|
111
|
+
"interaction_id"
|
|
112
|
+
) != snapshot.pending_interaction or command.payload.get("decision") not in {
|
|
113
|
+
"allow",
|
|
114
|
+
"deny",
|
|
115
|
+
}:
|
|
116
|
+
reason = "interaction_mismatch"
|
|
117
|
+
else:
|
|
118
|
+
updated = move(snapshot, snapshot.resume_phase or RunPhase.EXECUTING_TOOLS).model_copy(
|
|
119
|
+
update={
|
|
120
|
+
"interaction": {
|
|
121
|
+
"interaction_id": snapshot.interaction_host_id,
|
|
122
|
+
"decision": command.payload["decision"],
|
|
123
|
+
},
|
|
124
|
+
"pending_interaction": None,
|
|
125
|
+
}
|
|
126
|
+
)
|
|
127
|
+
extra = (
|
|
128
|
+
(
|
|
129
|
+
"approval.resolved",
|
|
130
|
+
{
|
|
131
|
+
"approval_id": snapshot.pending_interaction,
|
|
132
|
+
"call_id": (
|
|
133
|
+
snapshot.child_approval.tool_call.call_id
|
|
134
|
+
if snapshot.child_approval
|
|
135
|
+
else snapshot.pending_tools[0]["call_id"]
|
|
136
|
+
),
|
|
137
|
+
"decision": command.payload["decision"],
|
|
138
|
+
},
|
|
139
|
+
),
|
|
140
|
+
)
|
|
141
|
+
elif kind == "steer":
|
|
142
|
+
updated, reason = apply_steering(snapshot, command, bound_tool_names=bound_tool_names)
|
|
143
|
+
if reason == "applied" and command.payload.get("task_contract") is not None:
|
|
144
|
+
from .context_replay import reset_steered_replay
|
|
145
|
+
|
|
146
|
+
updated, replay_reset = reset_steered_replay(snapshot, updated, replay_configuration)
|
|
147
|
+
if replay_reset is not None:
|
|
148
|
+
extra = (("context.replay_root_reset", replay_reset),)
|
|
149
|
+
elif kind == "guide":
|
|
150
|
+
if guidance_enabled:
|
|
151
|
+
updated, reason = apply_guidance(snapshot, command)
|
|
152
|
+
else:
|
|
153
|
+
reason = "guidance_policy_unavailable"
|
|
154
|
+
if reason == "applied":
|
|
155
|
+
extra = (("input.guidance_applied", {
|
|
156
|
+
"command_id": command.command_id, "input_id": command.command_id,
|
|
157
|
+
"goal_revision": snapshot.goal_revision, "delivery": "guide",
|
|
158
|
+
}),)
|
|
159
|
+
else:
|
|
160
|
+
reason = "command_not_applicable"
|
|
161
|
+
if kind in {"steer", "guide"} and reason == "applied":
|
|
162
|
+
from .operator_guidance import bind_operator_input_history
|
|
163
|
+
|
|
164
|
+
updated, operator_input = bind_operator_input_history(
|
|
165
|
+
snapshot, updated, replay_configuration, command.command_id,
|
|
166
|
+
)
|
|
167
|
+
if operator_input is not None:
|
|
168
|
+
extra = (*extra, ("input.operator_guidance_superseded", operator_input))
|
|
169
|
+
if (
|
|
170
|
+
kind in {"cancel", "policy_revoked", "steer"}
|
|
171
|
+
and snapshot.pending_interaction
|
|
172
|
+
and updated.pending_interaction is None
|
|
173
|
+
):
|
|
174
|
+
extra = (*extra,
|
|
175
|
+
(
|
|
176
|
+
"approval.resolved",
|
|
177
|
+
{
|
|
178
|
+
"approval_id": snapshot.pending_interaction,
|
|
179
|
+
"call_id": (
|
|
180
|
+
snapshot.child_approval.tool_call.call_id
|
|
181
|
+
if snapshot.child_approval
|
|
182
|
+
else snapshot.pending_tools[0]["call_id"]
|
|
183
|
+
),
|
|
184
|
+
"decision": "canceled",
|
|
185
|
+
"reason": kind,
|
|
186
|
+
},
|
|
187
|
+
),
|
|
188
|
+
)
|
|
189
|
+
if snapshot.pending_guidance_ids and (
|
|
190
|
+
kind in {"cancel", "policy_revoked"} or kind == "steer" and reason == "applied"
|
|
191
|
+
):
|
|
192
|
+
extra = (*extra, *(("input.guidance_discarded", {
|
|
193
|
+
"input_id": input_id, "reason": kind,
|
|
194
|
+
}) for input_id in snapshot.pending_guidance_ids))
|
|
195
|
+
updated = updated.model_copy(update={"pending_guidance_ids": ()})
|
|
196
|
+
if kind == "cancel":
|
|
197
|
+
extra = (*extra, ("run.canceled", {"outcome": updated.outcome, "reason": updated.reason}))
|
|
198
|
+
elif kind == "policy_revoked":
|
|
199
|
+
extra = (*extra, ("run.failed", {"outcome": updated.outcome, "reason": updated.reason}))
|
|
200
|
+
return commit_transition(
|
|
201
|
+
snapshot,
|
|
202
|
+
updated,
|
|
203
|
+
"command.consumed",
|
|
204
|
+
{
|
|
205
|
+
"command_id": command.command_id,
|
|
206
|
+
"kind": kind,
|
|
207
|
+
"reason": reason,
|
|
208
|
+
"outcome": updated.outcome,
|
|
209
|
+
},
|
|
210
|
+
command_id=command.command_id,
|
|
211
|
+
extra_events=extra,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def host_resolved_candidate(snapshot: RunSnapshot, config: RunConfiguration) -> CommitBatch | None:
|
|
216
|
+
"""Submit a trusted host answer once, through the ordinary verifier path.
|
|
217
|
+
|
|
218
|
+
Goal text and revision both pin the answer: steering under an unchanged
|
|
219
|
+
contract cannot reuse it. A failed candidate enters ordinary model repair.
|
|
220
|
+
Command precedence and CAS remain the driver's and Store's responsibility.
|
|
221
|
+
"""
|
|
222
|
+
from .stop_hook_runtime import stop_hook_state
|
|
223
|
+
|
|
224
|
+
answer = config.contract.host_resolved_answer
|
|
225
|
+
if (
|
|
226
|
+
answer is None
|
|
227
|
+
# Inline guidance preserves the original goal/contract, but the old
|
|
228
|
+
# host answer cannot attest to the newly admitted user requirement.
|
|
229
|
+
or snapshot.pending_guidance_ids
|
|
230
|
+
or current_user_has_media(snapshot.messages, snapshot.goal)
|
|
231
|
+
or snapshot.phase != RunPhase.PREPARING_CONTEXT
|
|
232
|
+
or snapshot.goal_revision != answer.goal_revision
|
|
233
|
+
or hashlib.sha256(snapshot.goal.encode()).hexdigest() != answer.goal_digest
|
|
234
|
+
or snapshot.model_calls
|
|
235
|
+
or snapshot.tool_calls
|
|
236
|
+
or snapshot.repair_attempts
|
|
237
|
+
or stop_hook_state(snapshot).continuation_count
|
|
238
|
+
or config.contract.allowed_tool_names != ()
|
|
239
|
+
or config.final_submission_schema is not None
|
|
240
|
+
or config.final_output_format != "text"
|
|
241
|
+
):
|
|
242
|
+
return None
|
|
243
|
+
candidate = {
|
|
244
|
+
"candidate_id": f"{snapshot.run_id}:host-candidate:{snapshot.goal_revision}",
|
|
245
|
+
"final_text": answer.text,
|
|
246
|
+
}
|
|
247
|
+
updated = move(snapshot, RunPhase.VERIFYING).model_copy(
|
|
248
|
+
update={"candidate": candidate, "prepared_context": None}
|
|
249
|
+
)
|
|
250
|
+
return commit_transition(
|
|
251
|
+
snapshot,
|
|
252
|
+
updated,
|
|
253
|
+
"completion.host_candidate",
|
|
254
|
+
{
|
|
255
|
+
"authority": answer.authority,
|
|
256
|
+
"evidence_ref": answer.evidence_ref,
|
|
257
|
+
"goal_revision": snapshot.goal_revision,
|
|
258
|
+
"answer_digest": hashlib.sha256(answer.text.encode()).hexdigest(),
|
|
259
|
+
},
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def next_transition(snapshot: RunSnapshot, config: RunConfiguration) -> CommitBatch | None:
|
|
264
|
+
phase = snapshot.phase
|
|
265
|
+
if phase.terminal or phase in {RunPhase.PAUSED, RunPhase.AWAITING_INTERACTION}:
|
|
266
|
+
return None
|
|
267
|
+
if phase == RunPhase.CREATED:
|
|
268
|
+
return commit_transition(
|
|
269
|
+
snapshot,
|
|
270
|
+
move(snapshot, RunPhase.PREPARING_CONTEXT),
|
|
271
|
+
"run.started" if snapshot.event_seq == 0 else "run.phase_changed",
|
|
272
|
+
)
|
|
273
|
+
if phase == RunPhase.PREPARING_CONTEXT:
|
|
274
|
+
if resolved := host_resolved_candidate(snapshot, config):
|
|
275
|
+
return resolved
|
|
276
|
+
if snapshot.model_budget_claimed >= config.limits.max_model_calls:
|
|
277
|
+
updated = finish(snapshot, "budget_exhausted", "model_budget_exhausted")
|
|
278
|
+
else:
|
|
279
|
+
updated = move(snapshot, RunPhase.REQUESTING_MODEL)
|
|
280
|
+
return commit_transition(
|
|
281
|
+
snapshot, updated, "run.phase_changed", {"phase": updated.phase.value}
|
|
282
|
+
)
|
|
283
|
+
if phase == RunPhase.REQUESTING_MODEL:
|
|
284
|
+
payload = {"model_call": snapshot.model_calls + 1}
|
|
285
|
+
if review_pending(snapshot):
|
|
286
|
+
payload["purpose"] = "delivery_review"
|
|
287
|
+
elif control := model_turn_control(snapshot, config):
|
|
288
|
+
payload["purpose"] = "finalization" if control.finalization_only else "task"
|
|
289
|
+
payload["turn_control"] = control.model_dump(mode="json")
|
|
290
|
+
from .model_request import capture_request_context
|
|
291
|
+
|
|
292
|
+
return capture_request_context(snapshot, prepare_effect(snapshot, "model", payload), config)
|
|
293
|
+
if phase == RunPhase.EXECUTING_TOOLS:
|
|
294
|
+
if hook := prepare_tool_hook(snapshot, config):
|
|
295
|
+
return hook
|
|
296
|
+
if not snapshot.pending_tools:
|
|
297
|
+
if tool_error_streak_exhausted(snapshot):
|
|
298
|
+
updated = finish(snapshot, "blocked", "repeated_tool_error_no_progress")
|
|
299
|
+
return commit_transition(
|
|
300
|
+
snapshot,
|
|
301
|
+
updated,
|
|
302
|
+
"tools.completed",
|
|
303
|
+
{"reason": "repeated_tool_error_no_progress"},
|
|
304
|
+
)
|
|
305
|
+
feedback = tool_progress_feedback(
|
|
306
|
+
tool_hook_feedback_messages(snapshot, snapshot.messages)
|
|
307
|
+
)
|
|
308
|
+
updated = move(snapshot, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
309
|
+
update={"messages": feedback.messages}
|
|
310
|
+
)
|
|
311
|
+
return commit_transition(snapshot, updated, "tools.completed")
|
|
312
|
+
if tools_exhausted(snapshot, config):
|
|
313
|
+
return refuse_pending_batch(snapshot)
|
|
314
|
+
# ZCode schedules explicitly concurrent-safe tool calls in a bounded
|
|
315
|
+
# parallel group. Keep the same conservative rule here: only a
|
|
316
|
+
# contiguous prefix of host-declared, read-only calls can share one
|
|
317
|
+
# effect. Writes, browser actions and approval-capable tools stay in
|
|
318
|
+
# the ordinary per-call ledger path.
|
|
319
|
+
parallel = scheduled_tool_calls(snapshot, config)
|
|
320
|
+
if len(parallel) > 1:
|
|
321
|
+
definition = next(tool for tool in config.tools if tool.name == parallel[0]["name"])
|
|
322
|
+
payload = {
|
|
323
|
+
"calls": list(parallel), "parallel_readonly": True,
|
|
324
|
+
"parallel_delegation": definition.delegated_read_only,
|
|
325
|
+
}
|
|
326
|
+
delegated = definition.delegated_read_only
|
|
327
|
+
calls = parallel
|
|
328
|
+
else:
|
|
329
|
+
calls = (snapshot.pending_tools[0],)
|
|
330
|
+
payload = {"call": calls[0]}
|
|
331
|
+
definition = next((tool for tool in config.tools
|
|
332
|
+
if tool.name == calls[0]["name"]), None)
|
|
333
|
+
delegated = definition is not None and definition.child_budget_policy in {
|
|
334
|
+
"delegate/v1", "start/v1",
|
|
335
|
+
}
|
|
336
|
+
if config.child_lifecycle_policy == "owned-background/v2" and delegated:
|
|
337
|
+
# Preserve the actual admission before any member reports usage
|
|
338
|
+
# or reserves a child. Cancel/resume must not recalculate a grant
|
|
339
|
+
# from the later, partly charged parent snapshot.
|
|
340
|
+
payload["child_dispatch_budgets"] = [
|
|
341
|
+
dispatch_tool_budget(snapshot, config, batch_size=len(calls), index=index)
|
|
342
|
+
.model_dump(mode="json") for index in range(len(calls))
|
|
343
|
+
]
|
|
344
|
+
return prepare_effect(snapshot, "tool", payload)
|
|
345
|
+
if phase == RunPhase.VERIFYING:
|
|
346
|
+
if any(child.settled_usage_digest is None for child in snapshot.child_budget_reservations):
|
|
347
|
+
return commit_transition(
|
|
348
|
+
snapshot, finish(snapshot, "unverified", "background_children_unsettled"),
|
|
349
|
+
"child.delivery_unsettled", {
|
|
350
|
+
"child_run_ids": [
|
|
351
|
+
child.child_run_id for child in snapshot.child_budget_reservations
|
|
352
|
+
if child.settled_usage_digest is None
|
|
353
|
+
],
|
|
354
|
+
},
|
|
355
|
+
)
|
|
356
|
+
if snapshot.browser_reobservation_required:
|
|
357
|
+
# Every final protocol reaches this gate, including structured
|
|
358
|
+
# final submission. Model prose cannot clear resource continuity.
|
|
359
|
+
return commit_transition(
|
|
360
|
+
snapshot, move(snapshot, RunPhase.PREPARING_CONTEXT).model_copy(update={
|
|
361
|
+
"candidate": None, "verification": None,
|
|
362
|
+
"messages": (*snapshot.messages, {
|
|
363
|
+
"role": "user", "kind": "browser_recovery_observation",
|
|
364
|
+
"content": json.dumps({"fresh_observation_required": True,
|
|
365
|
+
"candidate_accepted": False}),
|
|
366
|
+
}),
|
|
367
|
+
}), "browser.candidate_rejected", {"reason": "fresh_observation_required"},
|
|
368
|
+
)
|
|
369
|
+
from .stop_hook_runtime import prepare_stop_hook
|
|
370
|
+
|
|
371
|
+
return prepare_stop_hook(snapshot, config) or prepare_effect(
|
|
372
|
+
snapshot, "verify", snapshot.candidate or {}
|
|
373
|
+
)
|
|
374
|
+
if phase == RunPhase.FINALIZING:
|
|
375
|
+
qualified = prepare_terminal_verification(snapshot, config)
|
|
376
|
+
if qualified.reason in {"effect_outcome_unknown", "browser_session_unavailable"}:
|
|
377
|
+
terminal = RunPhase.INTERRUPTED
|
|
378
|
+
elif qualified.outcome == "failed" or not qualified.final_text.strip():
|
|
379
|
+
# A terminal without deliverable text cannot be a completed turn.
|
|
380
|
+
# Studio applies the same nonempty-delivery gate to Native runs.
|
|
381
|
+
terminal = RunPhase.FAILED
|
|
382
|
+
else:
|
|
383
|
+
terminal = RunPhase.COMPLETED
|
|
384
|
+
updated = move(qualified, terminal)
|
|
385
|
+
extra = ()
|
|
386
|
+
if snapshot.final_text:
|
|
387
|
+
extra = (("text.completed", {"text": snapshot.final_text, "phase": "final_answer"}),)
|
|
388
|
+
report_ref = None
|
|
389
|
+
if updated.verification:
|
|
390
|
+
report_ref = f"verification:{updated.run_id}:{updated.verification['candidate_id']}"
|
|
391
|
+
# Only the committed finalization emits final text; a model candidate is
|
|
392
|
+
# never projected as an accepted user answer.
|
|
393
|
+
return commit_transition(
|
|
394
|
+
snapshot,
|
|
395
|
+
updated,
|
|
396
|
+
"run.finalizing",
|
|
397
|
+
extra_events=(
|
|
398
|
+
*extra,
|
|
399
|
+
(
|
|
400
|
+
f"run.{terminal.value}",
|
|
401
|
+
{
|
|
402
|
+
"outcome": updated.outcome,
|
|
403
|
+
"reason": updated.reason,
|
|
404
|
+
"contract_revision": config.contract.revision,
|
|
405
|
+
"verification_report_ref": report_ref,
|
|
406
|
+
"verification": updated.verification,
|
|
407
|
+
},
|
|
408
|
+
),
|
|
409
|
+
),
|
|
410
|
+
)
|
|
411
|
+
raise ValueError(f"unsupported phase: {phase.value}")
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def reduce_model(
|
|
415
|
+
snapshot: RunSnapshot, result: ModelTurnResult, config: RunConfiguration
|
|
416
|
+
) -> RunSnapshot:
|
|
417
|
+
from .model_input import input_binding_failure, observe_input
|
|
418
|
+
|
|
419
|
+
kind = result.response_kind
|
|
420
|
+
updated = snapshot.model_copy(
|
|
421
|
+
update={
|
|
422
|
+
"model_calls": snapshot.model_calls + 1,
|
|
423
|
+
"pending_intent": None,
|
|
424
|
+
"provider_errors": (
|
|
425
|
+
snapshot.provider_errors + 1 if kind == "provider_retryable_error" else 0
|
|
426
|
+
),
|
|
427
|
+
}
|
|
428
|
+
)
|
|
429
|
+
if failure := input_binding_failure(config.profile, result.input_receipt):
|
|
430
|
+
return finish(updated, "failed", failure)
|
|
431
|
+
updated = observe_input(updated, result.input_receipt)
|
|
432
|
+
if (config.model_recovery_policy == "pure-inference-takeover/v1"
|
|
433
|
+
and kind == "provider_retryable_error"):
|
|
434
|
+
updated = updated.model_copy(update={"model_recovery_retries_spent": max(
|
|
435
|
+
snapshot.model_recovery_retries_spent, snapshot.provider_errors
|
|
436
|
+
) + 1})
|
|
437
|
+
if failure := replay_binding_failure(
|
|
438
|
+
config.profile, result.provider_replay,
|
|
439
|
+
required=kind in {"tool_calls", "final_candidate", "output_limit"},
|
|
440
|
+
):
|
|
441
|
+
return finish(updated, "failed", failure)
|
|
442
|
+
if (result.provider_replay is not None
|
|
443
|
+
and config.profile.provider_replay_projection_policy
|
|
444
|
+
== "anthropic-client-compaction/v1"):
|
|
445
|
+
from .model_request import model_request
|
|
446
|
+
from .replay_context import bind_replay_input
|
|
447
|
+
|
|
448
|
+
request = model_request(snapshot, config, key=result.request_id, payload={
|
|
449
|
+
"purpose": "delivery_review" if review_pending(snapshot) else "task",
|
|
450
|
+
})
|
|
451
|
+
result = bind_replay_input(result, request)
|
|
452
|
+
if review_pending(snapshot) and kind == "tool_calls":
|
|
453
|
+
# Admit the surface advertised for this request. Charging its model
|
|
454
|
+
# call must not revoke an already offered source read; the next
|
|
455
|
+
# request uses the updated budget and read-round count.
|
|
456
|
+
readers = {tool.name for tool in delivery_review_readers(snapshot, config)}
|
|
457
|
+
if readers and all(call.name in readers for call in result.tool_calls):
|
|
458
|
+
# Same tool ledger and permissions; only existing host-declared
|
|
459
|
+
# source readers are admitted. Private review prose stays private.
|
|
460
|
+
updated = updated.model_copy(update={
|
|
461
|
+
"delivery_review": snapshot.delivery_review.model_copy(update={
|
|
462
|
+
"read_rounds": snapshot.delivery_review.read_rounds + 1,
|
|
463
|
+
"continuation_messages": (),
|
|
464
|
+
}),
|
|
465
|
+
})
|
|
466
|
+
sealed = begin_tool_batch(snapshot, updated, result)
|
|
467
|
+
return sealed.model_copy(update={"messages": (
|
|
468
|
+
*sealed.messages[:-1],
|
|
469
|
+
{**sealed.messages[-1], "kind": "delivery_review_source"},
|
|
470
|
+
)})
|
|
471
|
+
if review_pending(snapshot) and kind not in {
|
|
472
|
+
"provider_retryable_error", "policy_abort", "user_abort", "context_overflow",
|
|
473
|
+
"provider_terminal_error",
|
|
474
|
+
}:
|
|
475
|
+
return reduce_delivery_review(updated, result, config)
|
|
476
|
+
if kind == "tool_calls":
|
|
477
|
+
if config.final_submission_schema is not None and any(
|
|
478
|
+
call.name == FINAL_SUBMISSION_TOOL for call in result.tool_calls
|
|
479
|
+
):
|
|
480
|
+
if len(result.tool_calls) == 1:
|
|
481
|
+
submitted = submitted_final_text(result.tool_calls[0], config)
|
|
482
|
+
if submitted is not None:
|
|
483
|
+
return move(updated, RunPhase.VERIFYING).model_copy(
|
|
484
|
+
update={
|
|
485
|
+
"candidate": {
|
|
486
|
+
"candidate_id": (
|
|
487
|
+
f"{snapshot.run_id}:candidate:{updated.model_calls}"
|
|
488
|
+
),
|
|
489
|
+
"final_text": submitted,
|
|
490
|
+
},
|
|
491
|
+
"candidate_replay": result.provider_replay,
|
|
492
|
+
"model_errors": 0,
|
|
493
|
+
"continuations": 0,
|
|
494
|
+
}
|
|
495
|
+
)
|
|
496
|
+
# The internal submission must be a single valid call. Seal all
|
|
497
|
+
# model-declared calls with non-execution receipts; never dispatch
|
|
498
|
+
# a mixed batch or allow its ordinary tools to cause effects.
|
|
499
|
+
errors = snapshot.model_errors + 1
|
|
500
|
+
declared = begin_tool_batch(snapshot, updated, result)
|
|
501
|
+
refused = move(declared, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
502
|
+
update={
|
|
503
|
+
"pending_tools": (),
|
|
504
|
+
"model_errors": errors,
|
|
505
|
+
"messages": (
|
|
506
|
+
*declared.messages,
|
|
507
|
+
*refused_pending_tools(
|
|
508
|
+
declared, reason="final_submission_schema_or_batch_invalid"
|
|
509
|
+
),
|
|
510
|
+
),
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
if errors > config.profile.max_retries:
|
|
514
|
+
return finish(refused, "unverified", "final_submission_retry_exhausted")
|
|
515
|
+
return refused
|
|
516
|
+
if tools_exhausted(snapshot, config):
|
|
517
|
+
return finish(updated, "budget_exhausted", "tool_call_after_budget_exhaustion")
|
|
518
|
+
if finalization_only(snapshot, config):
|
|
519
|
+
return finish(updated, "budget_exhausted", "tool_call_after_finalization_reserve")
|
|
520
|
+
advertised = {tool.name for tool in model_tool_surface(snapshot, config)}
|
|
521
|
+
if any(call.name not in advertised for call in result.tool_calls):
|
|
522
|
+
# Never execute a batch containing a call outside current admission. Pair all
|
|
523
|
+
# sealed calls with non-execution receipts so the model can correct
|
|
524
|
+
# an occasional invented name, but bound consecutive violations.
|
|
525
|
+
# A known tool withheld for this turn does not consume that retry
|
|
526
|
+
# allowance; catalog visibility does not grant execution authority.
|
|
527
|
+
bound = {tool.name for tool in config.tools}
|
|
528
|
+
if any(call.name not in bound for call in result.tool_calls):
|
|
529
|
+
errors = snapshot.model_errors + 1
|
|
530
|
+
declared = begin_tool_batch(snapshot, updated, result)
|
|
531
|
+
refused = move(declared, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
532
|
+
update={
|
|
533
|
+
"pending_tools": (),
|
|
534
|
+
"model_errors": errors,
|
|
535
|
+
"messages": (
|
|
536
|
+
*declared.messages,
|
|
537
|
+
*refused_pending_tools(declared, reason="tool_not_bound"),
|
|
538
|
+
),
|
|
539
|
+
}
|
|
540
|
+
)
|
|
541
|
+
if errors > config.profile.max_retries:
|
|
542
|
+
return finish(refused, "blocked", "tool_call_not_advertised_retry_exhausted")
|
|
543
|
+
return refused
|
|
544
|
+
declared = begin_tool_batch(snapshot, updated, result)
|
|
545
|
+
return move(declared, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
546
|
+
update={
|
|
547
|
+
"pending_tools": (),
|
|
548
|
+
"messages": (
|
|
549
|
+
*declared.messages,
|
|
550
|
+
*refused_pending_tools(
|
|
551
|
+
declared,
|
|
552
|
+
reason="tool_unavailable_in_current_turn",
|
|
553
|
+
available_tools=tuple(sorted(advertised)),
|
|
554
|
+
),
|
|
555
|
+
),
|
|
556
|
+
}
|
|
557
|
+
)
|
|
558
|
+
return begin_tool_batch(snapshot, updated, result)
|
|
559
|
+
if kind == "final_candidate":
|
|
560
|
+
if config.final_submission_schema is not None:
|
|
561
|
+
errors = snapshot.model_errors + 1
|
|
562
|
+
if errors > config.profile.max_retries or (
|
|
563
|
+
updated.model_budget_claimed
|
|
564
|
+
>= config.limits.max_model_calls
|
|
565
|
+
):
|
|
566
|
+
return finish(updated, "unverified", "final_submission_missing")
|
|
567
|
+
# The provider completed a real assistant step, but used ordinary
|
|
568
|
+
# text instead of the host-owned submission tool. Keep that exact
|
|
569
|
+
# draft in the same turn so the next request can repair only the
|
|
570
|
+
# delivery envelope. The typed kind keeps it out of public Session
|
|
571
|
+
# history and it remains explicitly rejected, never a candidate.
|
|
572
|
+
draft = {
|
|
573
|
+
"role": "assistant",
|
|
574
|
+
"kind": "unstructured_final_draft",
|
|
575
|
+
"content": result.text,
|
|
576
|
+
"candidate_status": "rejected",
|
|
577
|
+
"request_id": result.request_id,
|
|
578
|
+
"attempt_id": result.attempt_id,
|
|
579
|
+
**replay_fields(result.provider_replay),
|
|
580
|
+
}
|
|
581
|
+
return move(updated, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
582
|
+
update={
|
|
583
|
+
"model_errors": errors,
|
|
584
|
+
"messages": (
|
|
585
|
+
*snapshot.messages,
|
|
586
|
+
draft,
|
|
587
|
+
{
|
|
588
|
+
"role": "user",
|
|
589
|
+
"kind": "final_submission_required",
|
|
590
|
+
"content": (
|
|
591
|
+
"The final answer must be submitted through the "
|
|
592
|
+
"submit_final_output tool matching its schema."
|
|
593
|
+
),
|
|
594
|
+
},
|
|
595
|
+
),
|
|
596
|
+
}
|
|
597
|
+
)
|
|
598
|
+
final_text = normalize_final_output(
|
|
599
|
+
complete_continuation(snapshot.messages, result.text),
|
|
600
|
+
output_format=config.final_output_format,
|
|
601
|
+
)
|
|
602
|
+
return move(updated, RunPhase.VERIFYING).model_copy(
|
|
603
|
+
update={
|
|
604
|
+
"candidate": {
|
|
605
|
+
"candidate_id": f"{snapshot.run_id}:candidate:{updated.model_calls}",
|
|
606
|
+
"final_text": final_text,
|
|
607
|
+
},
|
|
608
|
+
"candidate_replay": result.provider_replay,
|
|
609
|
+
"model_errors": 0,
|
|
610
|
+
}
|
|
611
|
+
)
|
|
612
|
+
if kind == "output_limit":
|
|
613
|
+
if snapshot.continuations >= config.profile.max_continuations:
|
|
614
|
+
if snapshot.output_restarts < config.limits.max_output_restarts:
|
|
615
|
+
return move(updated, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
616
|
+
update={
|
|
617
|
+
"continuations": 0,
|
|
618
|
+
"output_restarts": snapshot.output_restarts + 1,
|
|
619
|
+
"messages": abandon_continuation(snapshot.messages, result.text),
|
|
620
|
+
}
|
|
621
|
+
)
|
|
622
|
+
return finish(updated, "unverified", "continuation_budget_exhausted")
|
|
623
|
+
messages = snapshot.messages
|
|
624
|
+
recovery_mode = output_recovery_mode(updated, config) if result.text else "empty_output"
|
|
625
|
+
if result.text:
|
|
626
|
+
response_id = f"{result.request_id}:{result.attempt_id}"
|
|
627
|
+
digest = fragment_digest(result.text)
|
|
628
|
+
messages = (
|
|
629
|
+
*messages,
|
|
630
|
+
{
|
|
631
|
+
"role": "assistant",
|
|
632
|
+
"kind": "continuation_fragment",
|
|
633
|
+
"content": result.text,
|
|
634
|
+
**replay_fields(result.provider_replay),
|
|
635
|
+
"continuation_response_id": response_id,
|
|
636
|
+
},
|
|
637
|
+
)
|
|
638
|
+
else:
|
|
639
|
+
response_id = f"{result.request_id}:{result.attempt_id}"
|
|
640
|
+
digest = fragment_digest("")
|
|
641
|
+
return move(updated, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
642
|
+
update={
|
|
643
|
+
"continuations": snapshot.continuations + 1,
|
|
644
|
+
"messages": (
|
|
645
|
+
*messages,
|
|
646
|
+
{
|
|
647
|
+
"role": "user",
|
|
648
|
+
"kind": "continuation_observation",
|
|
649
|
+
"content": (
|
|
650
|
+
"The previous output was interrupted while task tools remain "
|
|
651
|
+
"available. It is work in progress, not a completed delivery. "
|
|
652
|
+
"Continue from the last committed state using the available tools "
|
|
653
|
+
"as needed; break remaining work into smaller actions. Incomplete "
|
|
654
|
+
"tool calls were not executed. Give a fresh final answer only after "
|
|
655
|
+
"the task is complete."
|
|
656
|
+
if recovery_mode == "task_resume"
|
|
657
|
+
else
|
|
658
|
+
"The last response hit its output limit. Return only the exact "
|
|
659
|
+
"missing suffix of that response. Incomplete tool calls were not "
|
|
660
|
+
"executed."
|
|
661
|
+
if result.text
|
|
662
|
+
else "The last response hit its output limit without visible content "
|
|
663
|
+
"or a committed tool call. Continue the task from the last committed "
|
|
664
|
+
"state; take the next useful action or answer only if the task is "
|
|
665
|
+
"complete."
|
|
666
|
+
),
|
|
667
|
+
"continuation_mode": recovery_mode,
|
|
668
|
+
"continuation_response_id": response_id,
|
|
669
|
+
"continuation_fragment_digest": digest,
|
|
670
|
+
},
|
|
671
|
+
),
|
|
672
|
+
}
|
|
673
|
+
)
|
|
674
|
+
if kind in {"empty_response", "malformed_tool_call", "provider_retryable_error"}:
|
|
675
|
+
provider_error = kind == "provider_retryable_error"
|
|
676
|
+
errors = updated.provider_errors if provider_error else snapshot.model_errors + 1
|
|
677
|
+
if provider_error and config.model_recovery_policy == "pure-inference-takeover/v1":
|
|
678
|
+
errors = max(errors, updated.model_recovery_retries_spent)
|
|
679
|
+
updated = updated.model_copy(
|
|
680
|
+
update={
|
|
681
|
+
"model_errors": 0 if provider_error else errors,
|
|
682
|
+
"messages": model_feedback_messages(
|
|
683
|
+
snapshot, result, tools_available=bool(model_tool_surface(snapshot, config))
|
|
684
|
+
),
|
|
685
|
+
}
|
|
686
|
+
)
|
|
687
|
+
limit = (
|
|
688
|
+
config.profile.max_provider_retries if provider_error else config.profile.max_retries
|
|
689
|
+
)
|
|
690
|
+
if errors > limit:
|
|
691
|
+
# No sealed final candidate exists. Report a failed ledger terminal
|
|
692
|
+
# so the native state agrees with the Studio delivery failure.
|
|
693
|
+
return move(updated, RunPhase.FAILED).model_copy(
|
|
694
|
+
update={"outcome": "failed", "reason": f"{kind}_retry_exhausted"}
|
|
695
|
+
)
|
|
696
|
+
return move(updated, RunPhase.PREPARING_CONTEXT)
|
|
697
|
+
if kind == "policy_abort":
|
|
698
|
+
return finish(updated, "blocked", "model_policy_abort")
|
|
699
|
+
if kind == "user_abort":
|
|
700
|
+
return move(updated, RunPhase.CANCELED).model_copy(
|
|
701
|
+
update={"outcome": "unverified", "reason": "user_canceled"}
|
|
702
|
+
)
|
|
703
|
+
if kind == "context_overflow":
|
|
704
|
+
if snapshot.context_binding and snapshot.context_overflows < config.profile.max_retries:
|
|
705
|
+
return move(updated, RunPhase.PREPARING_CONTEXT).model_copy(
|
|
706
|
+
update={
|
|
707
|
+
"force_compaction": True,
|
|
708
|
+
"prepared_context": None,
|
|
709
|
+
"context_overflows": snapshot.context_overflows + 1,
|
|
710
|
+
}
|
|
711
|
+
)
|
|
712
|
+
return finish(updated, "blocked", "context_compaction_unavailable")
|
|
713
|
+
return move(updated, RunPhase.FAILED).model_copy(
|
|
714
|
+
update={"outcome": "failed", "reason": "provider_terminal_error"}
|
|
715
|
+
)
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
def reduce_tool(
|
|
719
|
+
snapshot: RunSnapshot,
|
|
720
|
+
result: ToolResult,
|
|
721
|
+
*,
|
|
722
|
+
observation_role: str = "none",
|
|
723
|
+
definition=None,
|
|
724
|
+
observation_policy=None,
|
|
725
|
+
) -> RunSnapshot:
|
|
726
|
+
from .child_budget import apply_child_budget
|
|
727
|
+
from .observed_progress import advance_observed_progress
|
|
728
|
+
from .task_policy import invalidates_browser_observation
|
|
729
|
+
|
|
730
|
+
updated = snapshot.model_copy(update={"pending_intent": None})
|
|
731
|
+
if result.status == "approval_required":
|
|
732
|
+
if result.child_approval is not None:
|
|
733
|
+
from .child_approval import host_id, stage_child_approval
|
|
734
|
+
|
|
735
|
+
if (definition is None or definition.child_approval_policy is None
|
|
736
|
+
or result.interaction_id != host_id(result.child_approval)):
|
|
737
|
+
raise ValueError("child_approval_authority_mismatch")
|
|
738
|
+
return stage_child_approval(updated, result.child_approval,
|
|
739
|
+
operation_key=snapshot.pending_intent,
|
|
740
|
+
resume_phase=RunPhase.EXECUTING_TOOLS)
|
|
741
|
+
return move(updated, RunPhase.AWAITING_INTERACTION).model_copy(
|
|
742
|
+
update={
|
|
743
|
+
"resume_phase": RunPhase.EXECUTING_TOOLS,
|
|
744
|
+
"pending_interaction": f"{snapshot.pending_intent}:approval",
|
|
745
|
+
"interaction_host_id": result.interaction_id,
|
|
746
|
+
"interaction": None,
|
|
747
|
+
}
|
|
748
|
+
)
|
|
749
|
+
budget_snapshot, usage = apply_child_budget(snapshot, result, definition)
|
|
750
|
+
updated = updated.model_copy(update={"child_approval": None})
|
|
751
|
+
updated = updated.model_copy(update={
|
|
752
|
+
"child_budget_reservations": budget_snapshot.child_budget_reservations,
|
|
753
|
+
})
|
|
754
|
+
updated = updated.model_copy(
|
|
755
|
+
update={
|
|
756
|
+
"tool_calls": snapshot.tool_calls + 1,
|
|
757
|
+
"descendant_model_calls": snapshot.descendant_model_calls + usage.model_calls,
|
|
758
|
+
"descendant_tool_calls": snapshot.descendant_tool_calls + usage.tool_calls,
|
|
759
|
+
"child_run_ids": tuple(dict.fromkeys(
|
|
760
|
+
(*budget_snapshot.child_run_ids, *usage.child_run_ids)
|
|
761
|
+
)),
|
|
762
|
+
}
|
|
763
|
+
)
|
|
764
|
+
if observation_role == "browser" and result.browser_session_ref is not None:
|
|
765
|
+
from .browser_recovery import remember_browser
|
|
766
|
+
|
|
767
|
+
updated = remember_browser(
|
|
768
|
+
updated, result.browser_session_ref, closed=result.browser_session_closed
|
|
769
|
+
)
|
|
770
|
+
if updated.phase == RunPhase.FINALIZING:
|
|
771
|
+
return updated
|
|
772
|
+
if result.status == "uncertain":
|
|
773
|
+
return finish(updated, "unverified", "effect_outcome_unknown")
|
|
774
|
+
message = executed_tool_message(
|
|
775
|
+
result, call_id=snapshot.pending_tools[0]["call_id"], definition=definition,
|
|
776
|
+
receipt_ref=snapshot.pending_intent, goal_revision=snapshot.goal_revision,
|
|
777
|
+
tool_call=updated.tool_calls, hook_metadata=hook_execution_metadata(snapshot),
|
|
778
|
+
)
|
|
779
|
+
artifacts = {
|
|
780
|
+
ref.uri: ref
|
|
781
|
+
for ref in (ArtifactRef.model_validate(item) for item in snapshot.artifact_refs)
|
|
782
|
+
}
|
|
783
|
+
for ref in result.artifact_refs:
|
|
784
|
+
previous = artifacts.get(ref.uri)
|
|
785
|
+
if previous is not None and previous != ref:
|
|
786
|
+
return finish(updated, "failed", "artifact_reference_conflict")
|
|
787
|
+
artifacts[ref.uri] = ref
|
|
788
|
+
values = {
|
|
789
|
+
"pending_tools": snapshot.pending_tools[1:],
|
|
790
|
+
"messages": append_executed_tool_message(snapshot.messages, message),
|
|
791
|
+
"artifact_refs": tuple(ref.model_dump(mode="json") for ref in artifacts.values()),
|
|
792
|
+
"workspace_modified_paths": tuple(
|
|
793
|
+
dict.fromkeys((*snapshot.workspace_modified_paths, *result.workspace_changed_paths))
|
|
794
|
+
)[:2048],
|
|
795
|
+
"workspace_dirty_since_checkpoint": (
|
|
796
|
+
snapshot.workspace_dirty_since_checkpoint or bool(result.workspace_changed_paths)
|
|
797
|
+
),
|
|
798
|
+
"last_workspace_mutation_tool_call": (
|
|
799
|
+
updated.tool_calls
|
|
800
|
+
if result.workspace_changed_paths
|
|
801
|
+
else snapshot.last_workspace_mutation_tool_call
|
|
802
|
+
),
|
|
803
|
+
"last_web_mutation_tool_call": (
|
|
804
|
+
updated.tool_calls
|
|
805
|
+
if invalidates_browser_observation(result, observation_policy)
|
|
806
|
+
else snapshot.last_web_mutation_tool_call
|
|
807
|
+
),
|
|
808
|
+
"unresolved_interaction_observation": advance_interaction_observation(
|
|
809
|
+
snapshot.unresolved_interaction_observation,
|
|
810
|
+
role=observation_role,
|
|
811
|
+
tool_name=snapshot.pending_tools[0]["name"],
|
|
812
|
+
tool_call=updated.tool_calls,
|
|
813
|
+
result=result,
|
|
814
|
+
),
|
|
815
|
+
"last_browser_observation": advance_browser_observation(
|
|
816
|
+
snapshot.last_browser_observation,
|
|
817
|
+
role=observation_role,
|
|
818
|
+
tool_call=updated.tool_calls,
|
|
819
|
+
result=result,
|
|
820
|
+
),
|
|
821
|
+
"last_browser_attempt_tool_call": (
|
|
822
|
+
updated.tool_calls
|
|
823
|
+
if observation_role == "browser"
|
|
824
|
+
else snapshot.last_browser_attempt_tool_call
|
|
825
|
+
),
|
|
826
|
+
"interaction": None,
|
|
827
|
+
"interaction_host_id": None,
|
|
828
|
+
**advance_tool_error_streak(snapshot, result, definition),
|
|
829
|
+
**advance_observed_progress(snapshot, result, definition),
|
|
830
|
+
}
|
|
831
|
+
if snapshot.browser_reobservation_required and observation_role == "browser":
|
|
832
|
+
from .browser_recovery import remaining_reobservations
|
|
833
|
+
|
|
834
|
+
values["browser_reobservation_refs"] = remaining_reobservations(
|
|
835
|
+
snapshot, result, values["last_browser_observation"]
|
|
836
|
+
)
|
|
837
|
+
if snapshot.pending_tools[0]["name"] == TODO_WRITE_NAME and result.status == "ok":
|
|
838
|
+
try:
|
|
839
|
+
values.update(
|
|
840
|
+
task_progress=parse_task_progress(snapshot.pending_tools[0]["arguments"]),
|
|
841
|
+
task_progress_revision=snapshot.task_progress_revision + 1,
|
|
842
|
+
)
|
|
843
|
+
except ValueError:
|
|
844
|
+
# A conforming reserved port cannot return ok for an invalid plan.
|
|
845
|
+
return finish(updated, "failed", "invalid_task_progress_receipt")
|
|
846
|
+
return updated.model_copy(update=values)
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
def reduce_parallel_readonly_tools(
|
|
850
|
+
snapshot: RunSnapshot,
|
|
851
|
+
result: ToolResult,
|
|
852
|
+
calls: object,
|
|
853
|
+
*,
|
|
854
|
+
delegated: bool = False,
|
|
855
|
+
definitions=(),
|
|
856
|
+
observation_policy=None,
|
|
857
|
+
) -> RunSnapshot:
|
|
858
|
+
"""Commit ordered receipts from one bounded, read-only effect batch."""
|
|
859
|
+
|
|
860
|
+
content = result.content
|
|
861
|
+
rows = content.get("batch_results") if isinstance(content, dict) else None
|
|
862
|
+
if (
|
|
863
|
+
not isinstance(calls, list)
|
|
864
|
+
or len(calls) < 2
|
|
865
|
+
or len(snapshot.pending_tools) < len(calls)
|
|
866
|
+
or tuple(snapshot.pending_tools[: len(calls)]) != tuple(calls)
|
|
867
|
+
):
|
|
868
|
+
return finish(snapshot, "failed", "parallel_tool_receipt_invalid")
|
|
869
|
+
|
|
870
|
+
def account_batch(current: RunSnapshot) -> RunSnapshot:
|
|
871
|
+
# All members were admitted together. Early receipt rejection cannot
|
|
872
|
+
# erase that cost or fabricate observations/descendant resource usage.
|
|
873
|
+
# Keep per-member receipt indices assigned by reduce_tool unchanged.
|
|
874
|
+
return current.model_copy(update={"tool_calls": snapshot.tool_calls + len(calls)})
|
|
875
|
+
|
|
876
|
+
if not isinstance(rows, list) or len(rows) != len(calls):
|
|
877
|
+
return account_batch(finish(snapshot, "failed", "parallel_tool_receipt_invalid"))
|
|
878
|
+
updated = snapshot
|
|
879
|
+
for index, raw in enumerate(rows):
|
|
880
|
+
try:
|
|
881
|
+
item = ToolResult.model_validate(raw)
|
|
882
|
+
except ValueError:
|
|
883
|
+
return account_batch(finish(updated, "failed", "parallel_tool_receipt_invalid"))
|
|
884
|
+
usage = item.resource_usage
|
|
885
|
+
if parallel_result_violation(item, delegated=delegated):
|
|
886
|
+
return account_batch(finish(updated, "blocked", "parallel_readonly_contract_violation"))
|
|
887
|
+
if delegated:
|
|
888
|
+
call_id = updated.pending_tools[0]["call_id"]
|
|
889
|
+
if call_id not in snapshot.parallel_child_settlements:
|
|
890
|
+
return account_batch(finish(updated, "blocked", "parallel_child_receipt_missing"))
|
|
891
|
+
reservation = item.child_budget_reservation
|
|
892
|
+
if reservation is not None and (
|
|
893
|
+
reservation.parent_operation_key != f"{snapshot.pending_intent}:call:{index + 1}"
|
|
894
|
+
or reservation.parent_tool_call_id != call_id
|
|
895
|
+
or reservation not in snapshot.child_budget_reservations
|
|
896
|
+
):
|
|
897
|
+
return account_batch(finish(updated, "blocked", "parallel_child_receipt_mismatch"))
|
|
898
|
+
# The member receipt already registered either its allocation or
|
|
899
|
+
# its sealed usage before this batch completed. Publish the model
|
|
900
|
+
# result here without applying that accounting for a second time.
|
|
901
|
+
item = item.model_copy(update={
|
|
902
|
+
"resource_usage": type(usage)(), "child_budget_reservation": None,
|
|
903
|
+
})
|
|
904
|
+
updated = reduce_tool(
|
|
905
|
+
updated.model_copy(update={"pending_intent": snapshot.pending_intent}),
|
|
906
|
+
item,
|
|
907
|
+
definition=next(
|
|
908
|
+
(d for d in definitions if d.name == updated.pending_tools[0]["name"]), None
|
|
909
|
+
),
|
|
910
|
+
observation_policy=observation_policy,
|
|
911
|
+
)
|
|
912
|
+
if updated.phase.terminal or updated.phase == RunPhase.FINALIZING:
|
|
913
|
+
return account_batch(updated)
|
|
914
|
+
if delegated:
|
|
915
|
+
updated = updated.model_copy(update={"parallel_child_settlements": ()})
|
|
916
|
+
return updated
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
def reduce_workspace(
|
|
920
|
+
snapshot: RunSnapshot,
|
|
921
|
+
observation: WorkspaceObservation,
|
|
922
|
+
cursor: str,
|
|
923
|
+
config: RunConfiguration,
|
|
924
|
+
) -> RunSnapshot:
|
|
925
|
+
purpose = "verification" if snapshot.phase == RunPhase.VERIFYING else "model"
|
|
926
|
+
expected_cursor = workspace_observation_cursor(snapshot, purpose)
|
|
927
|
+
if observation.operation_key != snapshot.pending_intent or cursor != expected_cursor:
|
|
928
|
+
return finish(snapshot, "unverified", "workspace_observation_mismatch")
|
|
929
|
+
if snapshot.phase == RunPhase.VERIFYING:
|
|
930
|
+
changed = changed_verification_subject(
|
|
931
|
+
snapshot,
|
|
932
|
+
observation,
|
|
933
|
+
config.limits.max_repairs,
|
|
934
|
+
reason="candidate_workspace_changed",
|
|
935
|
+
)
|
|
936
|
+
if changed is not None:
|
|
937
|
+
return changed
|
|
938
|
+
revision_changed = (
|
|
939
|
+
snapshot.tool_calls > 0
|
|
940
|
+
and snapshot.workspace_revision is not None
|
|
941
|
+
and observation.revision is not None
|
|
942
|
+
and observation.revision != snapshot.workspace_revision
|
|
943
|
+
)
|
|
944
|
+
# Browser screenshots may be written into the visible workspace. They are
|
|
945
|
+
# observations, not project edits; a fresh browser receipt at this cursor
|
|
946
|
+
# must not schedule another source-verification checkpoint by itself.
|
|
947
|
+
browser_artifact_only = (
|
|
948
|
+
not observation.changed_paths
|
|
949
|
+
and isinstance(snapshot.last_browser_observation, dict)
|
|
950
|
+
and snapshot.last_browser_observation.get("tool_call") == snapshot.tool_calls
|
|
951
|
+
and snapshot.last_workspace_mutation_tool_call != snapshot.tool_calls
|
|
952
|
+
)
|
|
953
|
+
values = {
|
|
954
|
+
"pending_intent": None,
|
|
955
|
+
"workspace_revision": observation.revision,
|
|
956
|
+
"workspace_changed_paths": observation.changed_paths,
|
|
957
|
+
"workspace_modified_paths": tuple(
|
|
958
|
+
dict.fromkeys((*snapshot.workspace_modified_paths, *observation.changed_paths))
|
|
959
|
+
)[:2048],
|
|
960
|
+
"workspace_dirty_since_checkpoint": (
|
|
961
|
+
snapshot.workspace_dirty_since_checkpoint
|
|
962
|
+
or bool(observation.changed_paths)
|
|
963
|
+
or (revision_changed and not browser_artifact_only)
|
|
964
|
+
),
|
|
965
|
+
"last_workspace_mutation_tool_call": (
|
|
966
|
+
snapshot.tool_calls
|
|
967
|
+
if revision_changed and not browser_artifact_only
|
|
968
|
+
else snapshot.last_workspace_mutation_tool_call
|
|
969
|
+
),
|
|
970
|
+
"workspace_observation_status": observation.status,
|
|
971
|
+
"workspace_observation_reason": observation.reason,
|
|
972
|
+
"workspace_observation_cursor": cursor,
|
|
973
|
+
}
|
|
974
|
+
return snapshot.model_copy(update=values)
|