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,803 @@
|
|
|
1
|
+
"""Single-process child owner, sharing the existing Native child execution path.
|
|
2
|
+
|
|
3
|
+
Handles own asyncio resources only. Run state, initial identity, reservations and
|
|
4
|
+
results remain in the original scoped Store and parent effect receipts. Missing
|
|
5
|
+
owners are never reconstructed by blindly launching the child again.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Literal
|
|
13
|
+
|
|
14
|
+
from pydantic import Field, model_validator
|
|
15
|
+
|
|
16
|
+
from ksadk.harness.native.child_lifecycle import ChildLifecycleRequest, ChildLifecycleResult
|
|
17
|
+
from ksadk.harness.native.child_lifecycle_contract import (
|
|
18
|
+
ChildInterruptedReceipt,
|
|
19
|
+
ChildInterruptedReceiptRequest,
|
|
20
|
+
ChildReadyRequest,
|
|
21
|
+
ChildReadyResult,
|
|
22
|
+
ChildResourceReleaseRequest,
|
|
23
|
+
)
|
|
24
|
+
from ksadk.harness.native.effect_admission import owned_child_admission
|
|
25
|
+
from ksadk.harness.native.engine import NativeKernel
|
|
26
|
+
from ksadk.harness.native.model import ModelToolCall
|
|
27
|
+
from ksadk.harness.native.ports import (
|
|
28
|
+
ChildBudgetSettlement,
|
|
29
|
+
RunConfiguration,
|
|
30
|
+
ToolDefinition,
|
|
31
|
+
ToolRequest,
|
|
32
|
+
ToolResult,
|
|
33
|
+
digest,
|
|
34
|
+
)
|
|
35
|
+
from ksadk.harness.native.state import (
|
|
36
|
+
ChildApproval,
|
|
37
|
+
ChildBudgetReservation,
|
|
38
|
+
Contract,
|
|
39
|
+
RunScope,
|
|
40
|
+
RunSnapshot,
|
|
41
|
+
)
|
|
42
|
+
from ksadk.harness.native.subagents import ChildRole, ChildRunRequest
|
|
43
|
+
from ksadk.harness.stores.native_contract import RunStore, ScopeMismatch, StoreConflict
|
|
44
|
+
|
|
45
|
+
from .native_child import ChildFactory, NativeChildToolPort, _settle
|
|
46
|
+
from .native_child_approval import (
|
|
47
|
+
answer_original_pause,
|
|
48
|
+
await_decision,
|
|
49
|
+
current_approval,
|
|
50
|
+
observe_until_ready,
|
|
51
|
+
)
|
|
52
|
+
from .native_child_continuation import bind_child_continuation
|
|
53
|
+
from .native_child_result import NativeChildResultPort
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
async def _join(tasks):
|
|
57
|
+
return await asyncio.gather(*tasks, return_exceptions=True)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _finish_startup(task: asyncio.Task, ready: asyncio.Future) -> None:
|
|
61
|
+
# A Task cancelled before its first step never enters _drive's finally.
|
|
62
|
+
# The owner still owes every launch waiter a settled readiness signal.
|
|
63
|
+
if not ready.done():
|
|
64
|
+
ready.set_result(False)
|
|
65
|
+
if not task.cancelled():
|
|
66
|
+
task.exception()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class _Launch(Contract):
|
|
70
|
+
role: str = Field(min_length=1)
|
|
71
|
+
task: str = Field(min_length=1, max_length=32000, pattern=r"\S")
|
|
72
|
+
model_call_limit: int = Field(default=4, strict=True, ge=1)
|
|
73
|
+
tool_call_limit: int = Field(default=8, strict=True, ge=0)
|
|
74
|
+
output_format: Literal["text", "json_object"] | None = None
|
|
75
|
+
output_contract: Literal["parent"] | None = None
|
|
76
|
+
continuation_of: str | None = Field(default=None, min_length=1, max_length=256, pattern=r"\S")
|
|
77
|
+
background: bool = Field(default=True, strict=True)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class _Control(Contract):
|
|
81
|
+
child_run_id: str = Field(min_length=1, max_length=256)
|
|
82
|
+
action: Literal["wait", "send", "stop"]
|
|
83
|
+
message: str | None = Field(default=None, min_length=1, max_length=32000, pattern=r"\S")
|
|
84
|
+
wait_seconds: float = Field(default=15, ge=0, le=30, allow_inf_nan=False)
|
|
85
|
+
|
|
86
|
+
@model_validator(mode="after")
|
|
87
|
+
def message_only_for_send(self):
|
|
88
|
+
if (self.action == "send") != (self.message is not None):
|
|
89
|
+
raise ValueError("send requires a message; other actions cannot send one")
|
|
90
|
+
return self
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class _Handle:
|
|
95
|
+
request: ChildRunRequest
|
|
96
|
+
ready: asyncio.Future
|
|
97
|
+
task: asyncio.Task | None = None
|
|
98
|
+
kernel: NativeKernel | None = None
|
|
99
|
+
reservation: ChildBudgetReservation | None = None
|
|
100
|
+
background: bool = True
|
|
101
|
+
promotion: asyncio.Event | None = None
|
|
102
|
+
# Resource ownership is common; the original foreground receipt protocol
|
|
103
|
+
# and its declared profile stay sealed until an explicit migration.
|
|
104
|
+
sealed_runner: NativeChildToolPort | None = None
|
|
105
|
+
approval: ChildApproval | None = None
|
|
106
|
+
approval_ready: asyncio.Event = field(default_factory=asyncio.Event)
|
|
107
|
+
approval_decision: asyncio.Future | None = None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class _GuidedChildToolPort(NativeChildToolPort):
|
|
111
|
+
@staticmethod
|
|
112
|
+
def _configuration(child, bindings):
|
|
113
|
+
# Background send is supplemental guidance, not a replacement task.
|
|
114
|
+
# Pin that supported control policy before the child Run is published;
|
|
115
|
+
# synchronous delegates keep their original host configuration.
|
|
116
|
+
config = NativeChildToolPort._configuration(child, bindings).model_dump(mode="json")
|
|
117
|
+
config["guidance_policy"] = "boundary-guide/v1"
|
|
118
|
+
return RunConfiguration.model_validate(config)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class NativeBackgroundChildToolPort:
|
|
122
|
+
def __init__(
|
|
123
|
+
self,
|
|
124
|
+
*,
|
|
125
|
+
scope: RunScope,
|
|
126
|
+
roles: tuple[ChildRole, ...],
|
|
127
|
+
factory: ChildFactory,
|
|
128
|
+
store: RunStore,
|
|
129
|
+
approval_bridge: bool = False,
|
|
130
|
+
):
|
|
131
|
+
self._delegate = _GuidedChildToolPort(scope=scope, roles=roles, factory=factory)
|
|
132
|
+
self.scope, self.store = self._delegate.scope, store
|
|
133
|
+
self._reader = NativeChildResultPort(scope=scope, roles=roles, store=store)
|
|
134
|
+
self._handles: dict[str, _Handle] = {}
|
|
135
|
+
self._locks: dict[str, asyncio.Lock] = {}
|
|
136
|
+
self._closed = False
|
|
137
|
+
self.approval_bridge = approval_bridge
|
|
138
|
+
|
|
139
|
+
def definitions(self) -> tuple[ToolDefinition, ...]:
|
|
140
|
+
properties = dict(self._delegate.definition().parameters["properties"])
|
|
141
|
+
properties.update(
|
|
142
|
+
background={"type": "boolean", "default": True, "description": (
|
|
143
|
+
"False waits in the foreground. The host may move this same child to "
|
|
144
|
+
"the background while it runs; true starts in the background immediately."
|
|
145
|
+
)},
|
|
146
|
+
model_call_limit={"type": "integer", "minimum": 1, "default": 4},
|
|
147
|
+
tool_call_limit={"type": "integer", "minimum": 0, "default": 8},
|
|
148
|
+
continuation_of={
|
|
149
|
+
"type": "string", "minLength": 1, "maxLength": 256,
|
|
150
|
+
"description": (
|
|
151
|
+
"Continue an already collected terminal child in its original session. "
|
|
152
|
+
"Use the same role and a new task; the returned Run ID is new. "
|
|
153
|
+
"First wait/collect the source result. Omit for an independent child."
|
|
154
|
+
),
|
|
155
|
+
},
|
|
156
|
+
)
|
|
157
|
+
return (
|
|
158
|
+
ToolDefinition(
|
|
159
|
+
name="native_start_child",
|
|
160
|
+
description=(
|
|
161
|
+
"Start a bounded approved child (background by default), then continue "
|
|
162
|
+
"independent "
|
|
163
|
+
"parent work. The startup result reserves shared budget; it is not findings. "
|
|
164
|
+
"Use native_child_control to send input, stop, wait and consume its result "
|
|
165
|
+
"before final delivery. No parent acceptance is inherited. For a follow-up, "
|
|
166
|
+
"provide continuation_of after collecting the previous result; its history "
|
|
167
|
+
"is retained but its immutable Run and usage are not reopened."
|
|
168
|
+
),
|
|
169
|
+
parameters={
|
|
170
|
+
"type": "object",
|
|
171
|
+
"additionalProperties": False,
|
|
172
|
+
"required": ["role", "task"],
|
|
173
|
+
"properties": properties,
|
|
174
|
+
},
|
|
175
|
+
child_budget_policy="start/v1",
|
|
176
|
+
),
|
|
177
|
+
ToolDefinition(
|
|
178
|
+
name="native_child_control",
|
|
179
|
+
description=(
|
|
180
|
+
"Control a child started by this parent: send additional input, stop it, "
|
|
181
|
+
"or wait up to 30 seconds and consume its terminal findings. A running "
|
|
182
|
+
"response is not completion; terminal results settle actual usage once. "
|
|
183
|
+
"A terminal child is immutable; use native_start_child with continuation_of "
|
|
184
|
+
"for a follow-up after collecting its result."
|
|
185
|
+
),
|
|
186
|
+
parameters={
|
|
187
|
+
"type": "object",
|
|
188
|
+
"additionalProperties": False,
|
|
189
|
+
"required": ["child_run_id", "action"],
|
|
190
|
+
"properties": {
|
|
191
|
+
"child_run_id": {"type": "string", "minLength": 1, "maxLength": 256},
|
|
192
|
+
"action": {"type": "string", "enum": ["wait", "send", "stop"]},
|
|
193
|
+
"message": {"type": "string", "minLength": 1, "maxLength": 32000},
|
|
194
|
+
"wait_seconds": {"type": "number", "minimum": 0, "maximum": 30},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
child_budget_policy="settle/v1",
|
|
198
|
+
child_approval_policy="owned-child-approval/v1" if self.approval_bridge else None,
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
def _child_request(self, request: ToolRequest) -> ChildRunRequest:
|
|
203
|
+
launch = _Launch.model_validate(request.call.arguments)
|
|
204
|
+
allowance = request.budget
|
|
205
|
+
model_slots = allowance.max_model_calls_remaining - (
|
|
206
|
+
0 if allowance.parent_finalization_reserved else 1
|
|
207
|
+
)
|
|
208
|
+
# Preserve a parent collection/control call rather than allocate every
|
|
209
|
+
# remaining tool slot to the child. The outer final model reserve stays.
|
|
210
|
+
tool_slots = allowance.max_tool_calls_remaining - 1
|
|
211
|
+
if model_slots < 1 or tool_slots < 0:
|
|
212
|
+
raise ValueError("child_budget_exhausted")
|
|
213
|
+
args = {"role": launch.role, "task": launch.task}
|
|
214
|
+
if launch.output_format is not None:
|
|
215
|
+
args["output_format"] = launch.output_format
|
|
216
|
+
if launch.output_contract is not None:
|
|
217
|
+
args["output_contract"] = launch.output_contract
|
|
218
|
+
adapted = request.model_copy(
|
|
219
|
+
update={
|
|
220
|
+
"call": ModelToolCall(
|
|
221
|
+
call_id=request.call.call_id, name="native_delegate", arguments=args
|
|
222
|
+
),
|
|
223
|
+
"definition": self._delegate.definition(),
|
|
224
|
+
"budget": allowance.model_copy(
|
|
225
|
+
update={
|
|
226
|
+
"max_model_calls_remaining": min(model_slots, launch.model_call_limit),
|
|
227
|
+
"max_tool_calls_remaining": min(tool_slots, launch.tool_call_limit),
|
|
228
|
+
"parent_finalization_reserved": True,
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
child = self._delegate._request(adapted)
|
|
234
|
+
if launch.continuation_of is None:
|
|
235
|
+
return child
|
|
236
|
+
child = bind_child_continuation(
|
|
237
|
+
child, launch.continuation_of, store=self.store,
|
|
238
|
+
roles=tuple(self._delegate.roles.values()),
|
|
239
|
+
)
|
|
240
|
+
self._check_continuation_resource(child)
|
|
241
|
+
return child
|
|
242
|
+
|
|
243
|
+
def _check_continuation_resource(self, child: ChildRunRequest) -> None:
|
|
244
|
+
handle = self._handles.get(child.continuation_of)
|
|
245
|
+
if handle is None:
|
|
246
|
+
return
|
|
247
|
+
if handle.request.role != child.role:
|
|
248
|
+
raise ValueError("child_followup_role_mismatch")
|
|
249
|
+
if handle.task is None or not handle.task.done():
|
|
250
|
+
raise ValueError("child_followup_requires_result_collection")
|
|
251
|
+
|
|
252
|
+
async def _drive(self, handle: _Handle) -> ToolResult:
|
|
253
|
+
child = handle.request
|
|
254
|
+
runner = handle.sealed_runner or self._delegate
|
|
255
|
+
|
|
256
|
+
def ready(kernel: NativeKernel, config: RunConfiguration, snapshot: RunSnapshot):
|
|
257
|
+
handle.kernel = kernel
|
|
258
|
+
handle.reservation = ChildBudgetReservation(
|
|
259
|
+
child_run_id=child.child_run_id,
|
|
260
|
+
child_scope=child.scope,
|
|
261
|
+
parent_operation_key=child.parent_operation_key,
|
|
262
|
+
parent_tool_call_id=child.parent_tool_call_id,
|
|
263
|
+
child_request_digest=digest(child),
|
|
264
|
+
configuration_digest=config.digest,
|
|
265
|
+
max_model_calls=config.limits.max_model_calls,
|
|
266
|
+
max_tool_calls=config.limits.max_tool_calls,
|
|
267
|
+
)
|
|
268
|
+
handle.ready.set_result(True)
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
async def interaction(kernel, snapshot):
|
|
272
|
+
await await_decision(handle, kernel, snapshot)
|
|
273
|
+
|
|
274
|
+
result = await runner._run(
|
|
275
|
+
child, digest(child), on_ready=ready,
|
|
276
|
+
on_interaction=interaction if self.approval_bridge else None,
|
|
277
|
+
)
|
|
278
|
+
runner._results[child.child_run_id] = (digest(child), result)
|
|
279
|
+
return result
|
|
280
|
+
finally:
|
|
281
|
+
if not handle.ready.done():
|
|
282
|
+
handle.ready.set_result(False)
|
|
283
|
+
|
|
284
|
+
async def execute_foreground(
|
|
285
|
+
self, request: ToolRequest, *, delegate: NativeChildToolPort
|
|
286
|
+
) -> ToolResult:
|
|
287
|
+
"""Own the declared delegate, preserving legacy sealed SDK delivery."""
|
|
288
|
+
try:
|
|
289
|
+
request = ToolRequest.model_validate_json(request.model_dump_json())
|
|
290
|
+
if delegate.scope != self.scope or delegate.roles != self._delegate.roles:
|
|
291
|
+
raise ValueError("child_scope_or_definition_mismatch")
|
|
292
|
+
child = delegate._request(request)
|
|
293
|
+
self._check_continuation_resource(child)
|
|
294
|
+
except (ValueError, TypeError) as error:
|
|
295
|
+
codes = {"child_scope_or_definition_mismatch", "child_arguments_invalid",
|
|
296
|
+
"child_budget_exhausted", "child_followup_not_available",
|
|
297
|
+
"child_followup_role_mismatch", "child_followup_requires_result_collection"}
|
|
298
|
+
return delegate._error(str(error) if str(error) in codes else "child_request_rejected")
|
|
299
|
+
async with self._locks.setdefault(child.child_run_id, asyncio.Lock()):
|
|
300
|
+
if self._closed:
|
|
301
|
+
return delegate._error("child_owner_closed")
|
|
302
|
+
handle = self._handles.get(child.child_run_id)
|
|
303
|
+
if handle is not None and (
|
|
304
|
+
handle.request != child or handle.sealed_runner is not delegate
|
|
305
|
+
):
|
|
306
|
+
return delegate._error("child_operation_conflict")
|
|
307
|
+
# The original runner seals a cancellation receipt before its
|
|
308
|
+
# Task raises. Repeated callers consume that receipt, not the
|
|
309
|
+
# cancelled Task, and must never relaunch its effects.
|
|
310
|
+
cached = delegate._results.get(child.child_run_id)
|
|
311
|
+
if cached is not None:
|
|
312
|
+
if cached[0] != digest(child):
|
|
313
|
+
return delegate._error("child_operation_conflict")
|
|
314
|
+
if (child.delivery_mode is None or child.delivery_mode == "foreground"
|
|
315
|
+
and not handle.promotion.is_set()):
|
|
316
|
+
return ToolResult.model_validate_json(cached[1].model_dump_json())
|
|
317
|
+
return self._startup_result(handle)
|
|
318
|
+
if handle is None:
|
|
319
|
+
with owned_child_admission():
|
|
320
|
+
handle = _Handle(child, asyncio.get_running_loop().create_future(),
|
|
321
|
+
background=child.delivery_mode == "background",
|
|
322
|
+
promotion=asyncio.Event() if child.delivery_mode else None,
|
|
323
|
+
sealed_runner=delegate)
|
|
324
|
+
self._handles[child.child_run_id] = handle
|
|
325
|
+
handle.task = asyncio.create_task(self._drive(handle))
|
|
326
|
+
handle.task.add_done_callback(
|
|
327
|
+
lambda completed: _finish_startup(completed, handle.ready)
|
|
328
|
+
)
|
|
329
|
+
if child.delivery_mode is not None:
|
|
330
|
+
return await self._deliver_owned(handle, sealed_foreground=True)
|
|
331
|
+
try:
|
|
332
|
+
result = await asyncio.shield(handle.task)
|
|
333
|
+
except asyncio.CancelledError:
|
|
334
|
+
handle.task.cancel()
|
|
335
|
+
await _settle(_join((handle.task,)), propagate_cancel=False)
|
|
336
|
+
raise
|
|
337
|
+
return ToolResult.model_validate_json(result.model_dump_json())
|
|
338
|
+
|
|
339
|
+
@staticmethod
|
|
340
|
+
def _startup_result(handle: _Handle) -> ToolResult:
|
|
341
|
+
return ToolResult(
|
|
342
|
+
status="ok",
|
|
343
|
+
content={
|
|
344
|
+
"child_run_id": handle.request.child_run_id,
|
|
345
|
+
"started": True,
|
|
346
|
+
"parent_acceptance": "not_evaluated",
|
|
347
|
+
"result_consumed": False,
|
|
348
|
+
"control_tool": "native_child_control",
|
|
349
|
+
"background": handle.background or handle.promotion.is_set(),
|
|
350
|
+
},
|
|
351
|
+
child_budget_reservation=handle.reservation,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
async def _deliver_owned(self, handle: _Handle, *, sealed_foreground: bool) -> ToolResult:
|
|
355
|
+
try:
|
|
356
|
+
ready = await asyncio.shield(handle.ready)
|
|
357
|
+
if not ready:
|
|
358
|
+
return await handle.task
|
|
359
|
+
if not handle.background:
|
|
360
|
+
promotion = asyncio.create_task(handle.promotion.wait())
|
|
361
|
+
approval = asyncio.create_task(handle.approval_ready.wait())
|
|
362
|
+
try:
|
|
363
|
+
await asyncio.wait((handle.task, promotion, approval),
|
|
364
|
+
return_when=asyncio.FIRST_COMPLETED)
|
|
365
|
+
finally:
|
|
366
|
+
promotion.cancel()
|
|
367
|
+
approval.cancel()
|
|
368
|
+
await _settle(_join((promotion, approval)), propagate_cancel=False)
|
|
369
|
+
if handle.task.done() and (
|
|
370
|
+
not sealed_foreground or not handle.promotion.is_set()
|
|
371
|
+
):
|
|
372
|
+
result = await handle.task
|
|
373
|
+
if sealed_foreground:
|
|
374
|
+
return ToolResult.model_validate_json(result.model_dump_json())
|
|
375
|
+
return self._startup_result(handle)
|
|
376
|
+
except asyncio.CancelledError:
|
|
377
|
+
handle.task.cancel()
|
|
378
|
+
await _settle(_join((handle.task,)), propagate_cancel=False)
|
|
379
|
+
raise
|
|
380
|
+
|
|
381
|
+
async def _start(self, request: ToolRequest) -> ToolResult:
|
|
382
|
+
launch = _Launch.model_validate(request.call.arguments)
|
|
383
|
+
try:
|
|
384
|
+
child = self._child_request(request)
|
|
385
|
+
except ValueError as error:
|
|
386
|
+
if str(error) not in {
|
|
387
|
+
"child_followup_not_available", "child_followup_role_mismatch",
|
|
388
|
+
"child_followup_requires_result_collection", "child_budget_exhausted",
|
|
389
|
+
}:
|
|
390
|
+
raise
|
|
391
|
+
return self._delegate._error(str(error))
|
|
392
|
+
async with self._locks.setdefault(child.child_run_id, asyncio.Lock()):
|
|
393
|
+
if self._closed:
|
|
394
|
+
return self._delegate._error("child_owner_closed")
|
|
395
|
+
handle = self._handles.get(child.child_run_id)
|
|
396
|
+
if handle is not None and (
|
|
397
|
+
handle.request != child or handle.background != launch.background
|
|
398
|
+
):
|
|
399
|
+
return self._delegate._error("child_operation_conflict")
|
|
400
|
+
if handle is None:
|
|
401
|
+
with owned_child_admission():
|
|
402
|
+
handle = _Handle(child, asyncio.get_running_loop().create_future())
|
|
403
|
+
handle.background = launch.background
|
|
404
|
+
handle.promotion = asyncio.Event()
|
|
405
|
+
self._handles[child.child_run_id] = handle
|
|
406
|
+
handle.task = asyncio.create_task(self._drive(handle))
|
|
407
|
+
handle.task.add_done_callback(
|
|
408
|
+
lambda completed: _finish_startup(completed, handle.ready)
|
|
409
|
+
)
|
|
410
|
+
return await self._deliver_owned(handle, sealed_foreground=False)
|
|
411
|
+
|
|
412
|
+
def _waiting_handle(self, parent: RunSnapshot, child_run_id: str, *, read_closed=False):
|
|
413
|
+
handle = self._handles.get(child_run_id)
|
|
414
|
+
if (self._closed and not read_closed or parent.scope != self.scope or parent.phase.terminal
|
|
415
|
+
or handle is None or handle.kernel is None or handle.reservation is None
|
|
416
|
+
or handle.request.parent_scope != parent.scope
|
|
417
|
+
or handle.request.parent_run_id != parent.run_id or parent.pending_intent is None):
|
|
418
|
+
return None
|
|
419
|
+
intent = self.store.get_intent(self.scope, parent.run_id, parent.pending_intent)
|
|
420
|
+
call = None
|
|
421
|
+
if intent is not None and handle.request.parent_operation_key == intent.operation_key:
|
|
422
|
+
call = intent.payload.get("call")
|
|
423
|
+
elif intent is not None and intent.payload.get("parallel_delegation") is True:
|
|
424
|
+
for index, member in enumerate(intent.payload.get("calls", ()), 1):
|
|
425
|
+
if handle.request.parent_operation_key == f"{intent.operation_key}:call:{index}":
|
|
426
|
+
call = member
|
|
427
|
+
break
|
|
428
|
+
name = "native_delegate" if handle.sealed_runner is not None else "native_start_child"
|
|
429
|
+
if (intent is None or intent.kind != "tool" or intent.status != "running"
|
|
430
|
+
or not isinstance(call, dict) or call.get("name") != name
|
|
431
|
+
or call.get("call_id") != handle.request.parent_tool_call_id):
|
|
432
|
+
return None
|
|
433
|
+
args = call.get("arguments")
|
|
434
|
+
child = self.store.load(handle.request.scope, child_run_id)
|
|
435
|
+
if (not isinstance(args, dict) or args.get("role") != handle.request.role.role_id
|
|
436
|
+
or args.get("task") != handle.request.task
|
|
437
|
+
or child.origin is None or child.origin.get("parent_run_id") != parent.run_id
|
|
438
|
+
or child.origin.get("parent_scope") != parent.scope.model_dump(mode="json")
|
|
439
|
+
or child.origin.get("parent_operation_key") != handle.request.parent_operation_key
|
|
440
|
+
or child.origin.get("parent_tool_call_id") != handle.request.parent_tool_call_id
|
|
441
|
+
or child.configuration_digest != handle.reservation.configuration_digest):
|
|
442
|
+
return None
|
|
443
|
+
return handle
|
|
444
|
+
|
|
445
|
+
def _foreground_handle(self, parent: RunSnapshot, child_run_id: str):
|
|
446
|
+
handle = self._waiting_handle(parent, child_run_id)
|
|
447
|
+
if (handle is None or (handle.sealed_runner is not None
|
|
448
|
+
and handle.request.delivery_mode is None) or handle.background
|
|
449
|
+
or handle.task.done()
|
|
450
|
+
or self.store.load(handle.request.scope, child_run_id).phase.terminal):
|
|
451
|
+
return None
|
|
452
|
+
return handle
|
|
453
|
+
|
|
454
|
+
def can_promote(self, parent: RunSnapshot, child_run_id: str) -> bool:
|
|
455
|
+
handle = self._foreground_handle(parent, child_run_id)
|
|
456
|
+
return handle is not None and not handle.promotion.is_set()
|
|
457
|
+
|
|
458
|
+
def release_foreground(self, parent: RunSnapshot, child_run_id: str) -> None:
|
|
459
|
+
# The Kernel commits child.promoted before releasing this local wait.
|
|
460
|
+
# Both operations are synchronous under its original driver ownership.
|
|
461
|
+
handle = self._foreground_handle(parent, child_run_id)
|
|
462
|
+
if handle is not None:
|
|
463
|
+
handle.promotion.set()
|
|
464
|
+
|
|
465
|
+
def child_tasks(self, parent: RunSnapshot) -> tuple[dict, ...]:
|
|
466
|
+
if parent.scope != self.scope:
|
|
467
|
+
raise ValueError("child_task_scope_mismatch")
|
|
468
|
+
rows = []
|
|
469
|
+
promoted_ids = {e.payload.get("child_run_id")
|
|
470
|
+
for e in self.store.events(self.scope, parent.run_id)
|
|
471
|
+
if e.kind == "child.promoted"}
|
|
472
|
+
for child_id in dict.fromkeys((*parent.child_run_ids, *self._handles)):
|
|
473
|
+
handle = self._waiting_handle(parent, child_id)
|
|
474
|
+
child = (self.store.load(handle.request.scope, child_id) if handle is not None
|
|
475
|
+
else self._reader._load_direct_child(parent, child_id))
|
|
476
|
+
if child is None:
|
|
477
|
+
continue
|
|
478
|
+
original = self.store.get_intent(
|
|
479
|
+
self.scope, parent.run_id, child.origin["parent_operation_key"]
|
|
480
|
+
)
|
|
481
|
+
original_call = original.payload.get("call", {}) if original is not None else {}
|
|
482
|
+
if handle is not None:
|
|
483
|
+
foreground = not handle.background and child_id not in promoted_ids
|
|
484
|
+
else:
|
|
485
|
+
foreground = (
|
|
486
|
+
original_call.get("name") == "native_delegate"
|
|
487
|
+
and original_call.get("arguments", {}).get("background", False) is False
|
|
488
|
+
or original_call.get("name") == "native_start_child"
|
|
489
|
+
and original_call.get("arguments", {}).get("background") is False
|
|
490
|
+
) and child_id not in promoted_ids
|
|
491
|
+
rows.append({"child_run_id": child_id, "session_id": child.session_id,
|
|
492
|
+
"role": child.origin.get("role"), "phase": child.phase.value,
|
|
493
|
+
"delivery": "foreground" if foreground else "background",
|
|
494
|
+
"can_promote": self.can_promote(parent, child_id),
|
|
495
|
+
"can_cancel": self.can_cancel(parent, child_id),
|
|
496
|
+
"goal_revision": child.goal_revision,
|
|
497
|
+
"can_send_input": self.child_input_target(parent, child_id) is not None})
|
|
498
|
+
return tuple(rows)
|
|
499
|
+
|
|
500
|
+
def can_cancel(self, parent: RunSnapshot, child_run_id: str) -> bool:
|
|
501
|
+
handle = self._waiting_handle(parent, child_run_id)
|
|
502
|
+
child = (self.store.load(handle.request.scope, child_run_id) if handle is not None
|
|
503
|
+
else self._reader._load_direct_child(parent, child_run_id))
|
|
504
|
+
handle = handle or self._handles.get(child_run_id)
|
|
505
|
+
return bool(not self._closed and parent.scope == self.scope and not parent.phase.terminal
|
|
506
|
+
and child is not None and not child.phase.terminal and handle is not None
|
|
507
|
+
and handle.kernel is not None and not handle.task.done()
|
|
508
|
+
and handle.request.parent_run_id == parent.run_id
|
|
509
|
+
and handle.request.parent_scope == parent.scope
|
|
510
|
+
and handle.request.scope == child.scope)
|
|
511
|
+
|
|
512
|
+
async def cancel_child(self, parent: RunSnapshot, child_run_id: str) -> None:
|
|
513
|
+
if not self.can_cancel(parent, child_run_id):
|
|
514
|
+
return # The child may have naturally finished after admission.
|
|
515
|
+
task = self._handles[child_run_id].task
|
|
516
|
+
if not task.cancelling():
|
|
517
|
+
task.cancel()
|
|
518
|
+
# Join the existing runner's bounded cleanup; it remains the authority
|
|
519
|
+
# for child terminal facts and usage. A slow cleanup is still not success.
|
|
520
|
+
await asyncio.wait((task,), timeout=1.0)
|
|
521
|
+
|
|
522
|
+
def child_execution_view(self, parent: RunSnapshot, child_run_id: str) -> dict:
|
|
523
|
+
"""Read only an admitted direct child through its original scope/receipt."""
|
|
524
|
+
from ksadk.harness.native_projection import NativeEventProjection
|
|
525
|
+
|
|
526
|
+
if parent.scope != self.scope:
|
|
527
|
+
raise ValueError("child_task_scope_mismatch")
|
|
528
|
+
handle = self._waiting_handle(parent, child_run_id)
|
|
529
|
+
child = (self.store.load(handle.request.scope, child_run_id) if handle is not None
|
|
530
|
+
else self._reader._load_direct_child(parent, child_run_id))
|
|
531
|
+
if child is None:
|
|
532
|
+
raise ValueError("child_not_owned")
|
|
533
|
+
projection = NativeEventProjection(child.scope, child.run_id)
|
|
534
|
+
events = [event.model_dump(mode="json")
|
|
535
|
+
for native in self.store.events(child.scope, child.run_id)
|
|
536
|
+
for event in projection.consume(native)]
|
|
537
|
+
return {"child_run_id": child.run_id, "session_id": child.session_id,
|
|
538
|
+
"call_id": child.origin.get("parent_tool_call_id"),
|
|
539
|
+
"role": child.origin.get("role"), "phase": child.phase.value,
|
|
540
|
+
"events": events}
|
|
541
|
+
|
|
542
|
+
def child_input_target(self, parent: RunSnapshot, child_run_id: str):
|
|
543
|
+
from ksadk.harness.native.child_input import ChildInputTarget
|
|
544
|
+
|
|
545
|
+
handle = self._waiting_handle(parent, child_run_id)
|
|
546
|
+
child = (self.store.load(handle.request.scope, child_run_id) if handle is not None
|
|
547
|
+
else self._reader._load_direct_child(parent, child_run_id))
|
|
548
|
+
handle = handle or self._handles.get(child_run_id)
|
|
549
|
+
if (self._closed or parent.scope != self.scope or parent.phase.terminal
|
|
550
|
+
or child is None or child.phase.terminal or handle is None
|
|
551
|
+
or handle.kernel is None or handle.task.done()
|
|
552
|
+
or handle.kernel.configuration.guidance_policy is None
|
|
553
|
+
or handle.request.parent_run_id != parent.run_id
|
|
554
|
+
or handle.request.parent_scope != parent.scope
|
|
555
|
+
or handle.request.scope != child.scope):
|
|
556
|
+
return None
|
|
557
|
+
return ChildInputTarget(scope=child.scope, run_id=child.run_id,
|
|
558
|
+
configuration_digest=child.configuration_digest,
|
|
559
|
+
parent_operation_key=handle.request.parent_operation_key,
|
|
560
|
+
parent_tool_call_id=handle.request.parent_tool_call_id)
|
|
561
|
+
|
|
562
|
+
def wake_child_input(self, parent: RunSnapshot, child_run_id: str) -> None:
|
|
563
|
+
target = self.child_input_target(parent, child_run_id)
|
|
564
|
+
if target is not None:
|
|
565
|
+
self._handles[child_run_id].kernel.notify_pending_commands(child_run_id)
|
|
566
|
+
|
|
567
|
+
def interrupted_receipts(
|
|
568
|
+
self, request: ChildInterruptedReceiptRequest
|
|
569
|
+
) -> tuple[ChildInterruptedReceipt, ...]:
|
|
570
|
+
request = ChildInterruptedReceiptRequest.model_validate_json(request.model_dump_json())
|
|
571
|
+
if request.scope != self.scope:
|
|
572
|
+
raise ValueError("child_interrupted_receipt_scope_mismatch")
|
|
573
|
+
parent = self.store.load(self.scope, request.run_id)
|
|
574
|
+
if parent.pending_intent != request.parent_operation_key or parent.phase.terminal:
|
|
575
|
+
raise ValueError("child_interrupted_receipt_parent_changed")
|
|
576
|
+
results = []
|
|
577
|
+
for child_id in self._handles:
|
|
578
|
+
handle = self._waiting_handle(parent, child_id, read_closed=True)
|
|
579
|
+
if handle is None or (handle.sealed_runner is not None
|
|
580
|
+
and handle.request.delivery_mode is None):
|
|
581
|
+
continue
|
|
582
|
+
# Reading a known receipt never runs a factory or model, and does
|
|
583
|
+
# not require a cancelled Task to return successfully. In-progress
|
|
584
|
+
# owned resources enter the parent's existing cancellation ledger.
|
|
585
|
+
runner = handle.sealed_runner or self._delegate
|
|
586
|
+
cached = runner._results.get(child_id)
|
|
587
|
+
child = self.store.load(handle.request.scope, child_id)
|
|
588
|
+
if (handle.request.delivery_mode == "foreground"
|
|
589
|
+
and handle.task.done() and child.phase.terminal and cached is not None
|
|
590
|
+
and cached[0] == digest(handle.request)
|
|
591
|
+
and not handle.background and not handle.promotion.is_set()):
|
|
592
|
+
result = ToolResult.model_validate_json(cached[1].model_dump_json())
|
|
593
|
+
else:
|
|
594
|
+
result = self._startup_result(handle)
|
|
595
|
+
results.append(ChildInterruptedReceipt(
|
|
596
|
+
parent_operation_key=handle.request.parent_operation_key,
|
|
597
|
+
parent_tool_call_id=handle.request.parent_tool_call_id,
|
|
598
|
+
result=result,
|
|
599
|
+
))
|
|
600
|
+
return tuple(results)
|
|
601
|
+
|
|
602
|
+
async def _control(self, request: ToolRequest) -> ToolResult:
|
|
603
|
+
control = _Control.model_validate(request.call.arguments)
|
|
604
|
+
parent = self.store.load(self.scope, request.run_id)
|
|
605
|
+
child = self._reader._load_direct_child(parent, control.child_run_id)
|
|
606
|
+
handle = self._handles.get(control.child_run_id)
|
|
607
|
+
if child is None or handle is None or handle.kernel is None:
|
|
608
|
+
return self._delegate._error("child_owner_unavailable_or_not_authorized")
|
|
609
|
+
if not any(item.child_run_id == child.run_id for item in parent.child_budget_reservations):
|
|
610
|
+
# Its original receipt already charged usage. Returning an
|
|
611
|
+
# allocation settlement would charge it again or break the parent
|
|
612
|
+
# reducer. Keep reads on the existing scoped result query seam.
|
|
613
|
+
return ToolResult(status="error", content={
|
|
614
|
+
"error_code": "child_already_accounted_use_result_tool",
|
|
615
|
+
"result_tool": "native_child_result",
|
|
616
|
+
})
|
|
617
|
+
if request.child_approval is not None:
|
|
618
|
+
if request.child_approval.child_run_id != child.run_id or control.action != "wait":
|
|
619
|
+
raise ValueError("child_approval_control_changed")
|
|
620
|
+
answer_original_pause(self, parent, request)
|
|
621
|
+
if not child.phase.terminal and control.action == "send":
|
|
622
|
+
accepted = handle.kernel.guide(
|
|
623
|
+
child.run_id,
|
|
624
|
+
text=control.message,
|
|
625
|
+
command_id=request.operation_key,
|
|
626
|
+
expected_goal_revision=handle.kernel.reserved_goal_revision(child.run_id),
|
|
627
|
+
)
|
|
628
|
+
return ToolResult(
|
|
629
|
+
status="ok",
|
|
630
|
+
content={
|
|
631
|
+
"child_run_id": child.run_id,
|
|
632
|
+
"input_status": accepted.status,
|
|
633
|
+
"input_reason": accepted.reason,
|
|
634
|
+
"result_consumed": False,
|
|
635
|
+
},
|
|
636
|
+
)
|
|
637
|
+
if control.action == "send":
|
|
638
|
+
return self._delegate._error("child_terminal_requires_new_run")
|
|
639
|
+
if control.action == "stop" and not handle.task.done():
|
|
640
|
+
handle.task.cancel()
|
|
641
|
+
await _settle(_join((handle.task,)))
|
|
642
|
+
elif not handle.task.done() and control.wait_seconds:
|
|
643
|
+
# Timeout ends this observation only; shield the independently
|
|
644
|
+
# owned child so a bounded poll cannot cancel its work.
|
|
645
|
+
try:
|
|
646
|
+
await asyncio.wait_for(observe_until_ready((handle,)), control.wait_seconds)
|
|
647
|
+
except TimeoutError:
|
|
648
|
+
pass
|
|
649
|
+
if not handle.task.done():
|
|
650
|
+
if (approval := current_approval(handle)) is not None:
|
|
651
|
+
from ksadk.harness.native.child_approval import host_id
|
|
652
|
+
|
|
653
|
+
return ToolResult(status="approval_required", interaction_id=host_id(approval),
|
|
654
|
+
child_approval=approval,
|
|
655
|
+
content={"child_run_id": child.run_id})
|
|
656
|
+
current = self.store.load(child.scope, child.run_id)
|
|
657
|
+
return ToolResult(
|
|
658
|
+
status="ok",
|
|
659
|
+
content={
|
|
660
|
+
"child_run_id": child.run_id,
|
|
661
|
+
"phase": current.phase.value,
|
|
662
|
+
"result_consumed": False,
|
|
663
|
+
"parent_acceptance": "not_evaluated",
|
|
664
|
+
},
|
|
665
|
+
)
|
|
666
|
+
return self._terminal_result(handle)
|
|
667
|
+
|
|
668
|
+
def _terminal_result(self, handle: _Handle) -> ToolResult:
|
|
669
|
+
child = handle.request
|
|
670
|
+
runner = handle.sealed_runner or self._delegate
|
|
671
|
+
cached = runner._results.get(child.child_run_id)
|
|
672
|
+
if cached is None:
|
|
673
|
+
return self._delegate._error("child_terminal_receipt_unavailable")
|
|
674
|
+
current = self.store.load(child.scope, child.child_run_id)
|
|
675
|
+
if not current.phase.terminal:
|
|
676
|
+
return ToolResult(status="uncertain", content={"error_code": "child_owner_lost"})
|
|
677
|
+
return cached[1].model_copy(
|
|
678
|
+
deep=True,
|
|
679
|
+
update={
|
|
680
|
+
"child_budget_settlement": ChildBudgetSettlement(
|
|
681
|
+
child_run_id=child.child_run_id,
|
|
682
|
+
parent_operation_key=handle.request.parent_operation_key,
|
|
683
|
+
child_request_digest=digest(handle.request),
|
|
684
|
+
terminal_snapshot_digest=digest(current),
|
|
685
|
+
),
|
|
686
|
+
},
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
async def collect(self, request: ChildLifecycleRequest) -> ChildLifecycleResult:
|
|
690
|
+
request = ChildLifecycleRequest.model_validate_json(request.model_dump_json())
|
|
691
|
+
if request.scope != self.scope:
|
|
692
|
+
raise ValueError("child_lifecycle_scope_mismatch")
|
|
693
|
+
parent = self.store.load(self.scope, request.run_id)
|
|
694
|
+
expected = tuple(item for item in parent.child_budget_reservations
|
|
695
|
+
if item.settled_usage_digest is None)
|
|
696
|
+
if (parent.phase.terminal or parent.pending_intent != request.operation_key
|
|
697
|
+
or expected != request.reservations):
|
|
698
|
+
raise ValueError("child_lifecycle_parent_changed")
|
|
699
|
+
if request.child_approval is not None:
|
|
700
|
+
answer_original_pause(self, parent, request)
|
|
701
|
+
handles, pending, error = [], [], None
|
|
702
|
+
for allocation in request.reservations:
|
|
703
|
+
child = self._reader._load_direct_child(parent, allocation.child_run_id)
|
|
704
|
+
handle = self._handles.get(allocation.child_run_id)
|
|
705
|
+
if (child is None or handle is None or handle.kernel is None
|
|
706
|
+
or handle.reservation != allocation):
|
|
707
|
+
pending.append(allocation.child_run_id)
|
|
708
|
+
error = "child_owner_unavailable"
|
|
709
|
+
else:
|
|
710
|
+
handles.append(handle)
|
|
711
|
+
if request.action == "cancel":
|
|
712
|
+
for handle in handles:
|
|
713
|
+
if not handle.task.done():
|
|
714
|
+
handle.task.cancel()
|
|
715
|
+
await _settle(_join(tuple(handle.task for handle in handles)))
|
|
716
|
+
elif request.action == "wait":
|
|
717
|
+
# The enclosing parent effect owns a deadline and cancellation.
|
|
718
|
+
# Ending observation cannot itself cancel an independent child.
|
|
719
|
+
if self.approval_bridge:
|
|
720
|
+
await observe_until_ready(handles)
|
|
721
|
+
else:
|
|
722
|
+
await asyncio.gather(*(asyncio.shield(handle.task) for handle in handles),
|
|
723
|
+
return_exceptions=True)
|
|
724
|
+
results, approvals = [], []
|
|
725
|
+
for handle in handles:
|
|
726
|
+
if not handle.task.done():
|
|
727
|
+
pending.append(handle.request.child_run_id)
|
|
728
|
+
if self.approval_bridge and (approval := current_approval(handle)) is not None:
|
|
729
|
+
approvals.append(approval)
|
|
730
|
+
continue
|
|
731
|
+
result = self._terminal_result(handle)
|
|
732
|
+
if result.child_budget_settlement is None:
|
|
733
|
+
pending.append(handle.request.child_run_id)
|
|
734
|
+
error = "child_receipt_unavailable"
|
|
735
|
+
else:
|
|
736
|
+
results.append(result)
|
|
737
|
+
return ChildLifecycleResult(
|
|
738
|
+
operation_key=request.operation_key, results=tuple(results),
|
|
739
|
+
pending_child_run_ids=tuple(pending), error_code=error,
|
|
740
|
+
approvals=tuple(approvals),
|
|
741
|
+
)
|
|
742
|
+
|
|
743
|
+
def ready_children(self, request: ChildReadyRequest) -> ChildReadyResult:
|
|
744
|
+
"""Hint from original owned terminal receipts; never mutate parent facts."""
|
|
745
|
+
request = ChildReadyRequest.model_validate_json(request.model_dump_json())
|
|
746
|
+
if request.scope != self.scope:
|
|
747
|
+
raise ValueError("child_lifecycle_scope_mismatch")
|
|
748
|
+
parent = self.store.load(self.scope, request.run_id)
|
|
749
|
+
expected = tuple(item for item in parent.child_budget_reservations
|
|
750
|
+
if item.settled_usage_digest is None)
|
|
751
|
+
if parent.phase.terminal or expected != request.reservations:
|
|
752
|
+
raise ValueError("child_lifecycle_parent_changed")
|
|
753
|
+
ready = []
|
|
754
|
+
for allocation in request.reservations:
|
|
755
|
+
child = self._reader._load_direct_child(parent, allocation.child_run_id)
|
|
756
|
+
handle = self._handles.get(allocation.child_run_id)
|
|
757
|
+
if (child is not None and handle is not None and handle.reservation == allocation
|
|
758
|
+
and handle.task is not None and (
|
|
759
|
+
handle.task.done()
|
|
760
|
+
and self._terminal_result(handle).child_budget_settlement is not None
|
|
761
|
+
or request.include_approvals and self.approval_bridge
|
|
762
|
+
and current_approval(handle) is not None
|
|
763
|
+
)):
|
|
764
|
+
ready.append(allocation.child_run_id)
|
|
765
|
+
return ChildReadyResult(child_run_ids=tuple(ready))
|
|
766
|
+
|
|
767
|
+
async def execute(self, request: ToolRequest) -> ToolResult:
|
|
768
|
+
request = ToolRequest.model_validate_json(request.model_dump_json())
|
|
769
|
+
definitions = {item.name: item for item in self.definitions()}
|
|
770
|
+
if self._closed:
|
|
771
|
+
return self._delegate._error("child_owner_closed")
|
|
772
|
+
if request.scope != self.scope or request.definition != definitions.get(request.call.name):
|
|
773
|
+
return self._delegate._error("child_scope_or_definition_mismatch")
|
|
774
|
+
try:
|
|
775
|
+
if request.call.name == "native_start_child":
|
|
776
|
+
return await self._start(request)
|
|
777
|
+
return await self._control(request)
|
|
778
|
+
except (ValueError, KeyError, ScopeMismatch, StoreConflict):
|
|
779
|
+
return self._delegate._error("child_lifecycle_request_rejected")
|
|
780
|
+
|
|
781
|
+
async def close(self):
|
|
782
|
+
self._closed = True
|
|
783
|
+
tasks = [handle.task for handle in self._handles.values() if handle.task is not None]
|
|
784
|
+
for task in tasks:
|
|
785
|
+
if not task.done():
|
|
786
|
+
task.cancel()
|
|
787
|
+
if tasks:
|
|
788
|
+
await _settle(_join(tasks))
|
|
789
|
+
|
|
790
|
+
async def release_run(self, request: ChildResourceReleaseRequest) -> None:
|
|
791
|
+
request = ChildResourceReleaseRequest.model_validate_json(request.model_dump_json())
|
|
792
|
+
if request.scope != self.scope:
|
|
793
|
+
raise ValueError("child_release_scope_mismatch")
|
|
794
|
+
tasks = [handle.task for handle in self._handles.values()
|
|
795
|
+
if handle.request.parent_run_id == request.run_id
|
|
796
|
+
and handle.request.parent_scope == request.scope and handle.task is not None]
|
|
797
|
+
for task in tasks:
|
|
798
|
+
if not task.done():
|
|
799
|
+
task.cancel()
|
|
800
|
+
if tasks:
|
|
801
|
+
await _settle(_join(tasks))
|
|
802
|
+
# The activation is reusable by later parent turns. Do not close the
|
|
803
|
+
# owner, mutate parent facts, or stop another parent's resources.
|