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,58 @@
|
|
|
1
|
+
"""Pure validation of pinned tool input; never normalize or grant permission."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
from jsonschema import FormatChecker
|
|
8
|
+
from jsonschema.exceptions import ValidationError as SchemaValidationError
|
|
9
|
+
from jsonschema.validators import validator_for
|
|
10
|
+
from pydantic import JsonValue
|
|
11
|
+
|
|
12
|
+
from .tool_argument_feedback import argument_error
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _reject_external_refs(value: object) -> None:
|
|
16
|
+
if isinstance(value, dict):
|
|
17
|
+
for key, child in value.items():
|
|
18
|
+
if key in {"$ref", "$dynamicRef", "$recursiveRef"}:
|
|
19
|
+
if not isinstance(child, str) or not child.startswith("#"):
|
|
20
|
+
raise ValueError("tool schemas may only reference local fragments")
|
|
21
|
+
_reject_external_refs(child)
|
|
22
|
+
elif isinstance(value, list):
|
|
23
|
+
for child in value:
|
|
24
|
+
_reject_external_refs(child)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ToolInputValidator:
|
|
28
|
+
"""The same detached schema and diagnostic semantics at both boundaries.
|
|
29
|
+
|
|
30
|
+
The Kernel uses this before entering a ToolPort. StrictToolExecutor keeps
|
|
31
|
+
a compiled instance alongside its pinned callback and checks again before
|
|
32
|
+
current authorization. Success is only a schema fact, never approval.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, parameters: dict[str, JsonValue]) -> None:
|
|
36
|
+
try:
|
|
37
|
+
self._parameters = json.loads(json.dumps(parameters, allow_nan=False))
|
|
38
|
+
except (TypeError, ValueError) as exc:
|
|
39
|
+
raise ValueError("invalid tool schema") from exc
|
|
40
|
+
_reject_external_refs(self._parameters)
|
|
41
|
+
try:
|
|
42
|
+
validator_class = validator_for(self._parameters)
|
|
43
|
+
validator_class.check_schema(self._parameters)
|
|
44
|
+
self._validator = validator_class(self._parameters, format_checker=FormatChecker())
|
|
45
|
+
except Exception as exc:
|
|
46
|
+
raise ValueError("invalid tool schema") from exc
|
|
47
|
+
|
|
48
|
+
def rejection(self, arguments: dict[str, JsonValue]) -> dict[str, JsonValue] | None:
|
|
49
|
+
try:
|
|
50
|
+
# Validate detached finite JSON without replacing the admitted
|
|
51
|
+
# arguments. Defaults and coercion never rewrite an action.
|
|
52
|
+
value = json.loads(json.dumps(arguments, allow_nan=False))
|
|
53
|
+
self._validator.validate(value)
|
|
54
|
+
except SchemaValidationError as exc:
|
|
55
|
+
return argument_error(exc, self._parameters, self._validator)
|
|
56
|
+
except Exception:
|
|
57
|
+
return {"code": "invalid_arguments"}
|
|
58
|
+
return None
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Bind interrupted batch dispositions to the original host transcript."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from .state import (
|
|
9
|
+
CommitBatch,
|
|
10
|
+
EffectIntent,
|
|
11
|
+
EffectReceipt,
|
|
12
|
+
InterruptedToolCall,
|
|
13
|
+
RunSnapshot,
|
|
14
|
+
ToolBatchInterruption,
|
|
15
|
+
)
|
|
16
|
+
from .transitions import insert_event_before_terminal
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def tool_batch_digest(message: dict) -> str:
|
|
20
|
+
raw = json.dumps(message, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
|
|
21
|
+
return hashlib.sha256(raw.encode("utf-8")).hexdigest()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def record_tool_interruption(
|
|
25
|
+
previous: RunSnapshot, batch: CommitBatch,
|
|
26
|
+
intent: EffectIntent | None = None, receipt: EffectReceipt | None = None,
|
|
27
|
+
) -> CommitBatch:
|
|
28
|
+
"""Keep dispatch knowledge when a host transition clears an unfinished batch.
|
|
29
|
+
|
|
30
|
+
No model/tool prose supplies execution authority. Claimed effects remain
|
|
31
|
+
unknown; only calls outside that effect, or a prepared effect, are known
|
|
32
|
+
undispatched. Original messages, receipts and admission counters stay intact.
|
|
33
|
+
Legacy/malformed histories without an exact source keep their unknown fallback.
|
|
34
|
+
"""
|
|
35
|
+
if (not previous.pending_tools or batch.snapshot.pending_tools
|
|
36
|
+
or batch.snapshot.outcome is None):
|
|
37
|
+
return batch
|
|
38
|
+
pending = {call["call_id"] for call in previous.pending_tools}
|
|
39
|
+
source = next((
|
|
40
|
+
(index, message) for index, message in reversed(tuple(enumerate(previous.messages)))
|
|
41
|
+
if message.get("role") == "assistant"
|
|
42
|
+
and pending.issubset({call.get("id") for call in message.get("tool_calls", ())})
|
|
43
|
+
), None)
|
|
44
|
+
if source is None:
|
|
45
|
+
return batch
|
|
46
|
+
index, message = source
|
|
47
|
+
completed = {item.get("tool_call_id") for item in batch.snapshot.messages[index + 1:]
|
|
48
|
+
if item.get("role") == "tool"}
|
|
49
|
+
pending -= completed
|
|
50
|
+
if not pending:
|
|
51
|
+
return batch
|
|
52
|
+
scheduled, unknown = set(), set()
|
|
53
|
+
if intent is not None and intent.kind == "tool":
|
|
54
|
+
raw = intent.payload.get("calls")
|
|
55
|
+
raw = raw if isinstance(raw, list) else [intent.payload.get("call")]
|
|
56
|
+
scheduled = {call.get("call_id") for call in raw if isinstance(call, dict)}
|
|
57
|
+
explicitly_undispatched = (
|
|
58
|
+
receipt is not None and receipt.status == "failed"
|
|
59
|
+
and receipt.result.get("reason") == "not_dispatched"
|
|
60
|
+
)
|
|
61
|
+
if not scheduled or None in scheduled:
|
|
62
|
+
unknown = pending
|
|
63
|
+
elif not explicitly_undispatched and (receipt is not None or intent.status == "running"):
|
|
64
|
+
unknown = scheduled
|
|
65
|
+
elif intent is None:
|
|
66
|
+
if previous.pending_intent is not None:
|
|
67
|
+
unknown = pending # Missing host dispatch evidence is never a non-execution proof.
|
|
68
|
+
elif previous.pending_interaction is not None:
|
|
69
|
+
# A paused tool/child has already entered its Port. Its nonterminal
|
|
70
|
+
# approval is not a committed execution result or rollback proof.
|
|
71
|
+
unknown = {previous.pending_tools[0]["call_id"]}
|
|
72
|
+
observation = ToolBatchInterruption(
|
|
73
|
+
source_message_index=index, source_message_digest=tool_batch_digest(message),
|
|
74
|
+
reason=batch.snapshot.reason or "interrupted_tool_batch",
|
|
75
|
+
calls=tuple(InterruptedToolCall(
|
|
76
|
+
call_id=call["call_id"],
|
|
77
|
+
execution_status="unknown" if call["call_id"] in unknown else "not_dispatched",
|
|
78
|
+
operation_key=(intent.operation_key if intent is not None
|
|
79
|
+
and call["call_id"] in scheduled else None),
|
|
80
|
+
) for call in previous.pending_tools if call["call_id"] in pending),
|
|
81
|
+
)
|
|
82
|
+
batch = batch.model_copy(update={"snapshot": batch.snapshot.model_copy(update={
|
|
83
|
+
"tool_batch_interruption": observation,
|
|
84
|
+
})})
|
|
85
|
+
return insert_event_before_terminal(previous, batch, (
|
|
86
|
+
"tools.interrupted", observation.model_dump(mode="json"),
|
|
87
|
+
))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def interrupted_tool_calls(parent: RunSnapshot, index: int, message: dict) -> dict:
|
|
91
|
+
"""Use a disposition only for its exact original assistant batch."""
|
|
92
|
+
observation = parent.tool_batch_interruption
|
|
93
|
+
if (observation is None or observation.source_message_index != index
|
|
94
|
+
or observation.source_message_digest != tool_batch_digest(message)):
|
|
95
|
+
return {}
|
|
96
|
+
return {call.call_id: call for call in observation.calls}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""Separate a canonical executed receipt from its host-selected model view.
|
|
2
|
+
|
|
3
|
+
Hashes detect inconsistent persisted projections, not hostile Store rewrites.
|
|
4
|
+
Only the reducer creates this top-level field from a locked tool policy. Tool
|
|
5
|
+
payload text cannot create it or acquire execution/verification authority.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import json
|
|
12
|
+
|
|
13
|
+
from .model import ModelImageContent, ModelTextContent
|
|
14
|
+
|
|
15
|
+
VERSION = "canonical-tool-model-view/v1"
|
|
16
|
+
OBSERVED_HISTORY_VERSION = "canonical-tool-model-view/v2"
|
|
17
|
+
TYPED_HISTORY_VERSION = "canonical-tool-model-view/v3"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def executed_tool_message(
|
|
21
|
+
result, *, call_id, definition=None, receipt_ref=None, goal_revision=0,
|
|
22
|
+
tool_call=0, hook_metadata=None,
|
|
23
|
+
):
|
|
24
|
+
"""Use the same canonical observation for a single or completed batch member."""
|
|
25
|
+
if result.model_observation is not None and (
|
|
26
|
+
definition is None or definition.result_model_policy != result.model_observation.version
|
|
27
|
+
):
|
|
28
|
+
raise ValueError("tool_model_policy_mismatch")
|
|
29
|
+
canonical = (
|
|
30
|
+
definition is not None
|
|
31
|
+
and definition.result_archive_policy in {
|
|
32
|
+
"archived-model-view/v3", "archived-model-view/v4", "archived-model-view/v5",
|
|
33
|
+
}
|
|
34
|
+
and result.status == "ok" and result.model_content is not None
|
|
35
|
+
)
|
|
36
|
+
message = {
|
|
37
|
+
"role": "tool", "tool_call_id": call_id,
|
|
38
|
+
"content": (
|
|
39
|
+
result.model_content
|
|
40
|
+
if result.status == "ok" and result.model_content is not None and not canonical
|
|
41
|
+
else json.dumps(
|
|
42
|
+
{"status": result.status, "content": result.content}, ensure_ascii=False,
|
|
43
|
+
)
|
|
44
|
+
),
|
|
45
|
+
}
|
|
46
|
+
if receipt_ref is not None:
|
|
47
|
+
message.update(receipt_ref=receipt_ref, receipt_goal_revision=goal_revision,
|
|
48
|
+
receipt_tool_call=tool_call)
|
|
49
|
+
message.update(hook_metadata or {})
|
|
50
|
+
if result.artifact_refs:
|
|
51
|
+
message["artifact_refs"] = [ref.model_dump(mode="json") for ref in result.artifact_refs]
|
|
52
|
+
if result.content_blocks:
|
|
53
|
+
message["content"] = [
|
|
54
|
+
{"type": "text", "text": message["content"]},
|
|
55
|
+
*(block.model_dump(mode="json") for block in result.content_blocks),
|
|
56
|
+
]
|
|
57
|
+
if canonical:
|
|
58
|
+
message = seal_model_view(
|
|
59
|
+
message, result.model_content,
|
|
60
|
+
observed_history=definition.result_archive_policy in {
|
|
61
|
+
"archived-model-view/v4", "archived-model-view/v5",
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
return (seal_typed_model_view(message, result.model_observation)
|
|
65
|
+
if result.model_observation is not None else message)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def append_executed_tool_message(messages, message):
|
|
69
|
+
"""Seal once, retaining declaration order independently of completion events."""
|
|
70
|
+
insertion = len(messages)
|
|
71
|
+
if message.get("receipt_ref") is not None:
|
|
72
|
+
found = []
|
|
73
|
+
for index in range(len(messages) - 1, -1, -1):
|
|
74
|
+
item = messages[index]
|
|
75
|
+
if item.get("role") == "assistant" and item.get("tool_calls"):
|
|
76
|
+
break
|
|
77
|
+
if (item.get("role") == "tool"
|
|
78
|
+
and item.get("receipt_ref") == message["receipt_ref"]
|
|
79
|
+
and item.get("tool_call_id") == message["tool_call_id"]):
|
|
80
|
+
found.append(item)
|
|
81
|
+
if (item.get("role") == "tool"
|
|
82
|
+
and item.get("receipt_ref") == message["receipt_ref"]
|
|
83
|
+
and item.get("receipt_tool_call", 0) > message.get("receipt_tool_call", 0)):
|
|
84
|
+
insertion = min(insertion, index)
|
|
85
|
+
if found:
|
|
86
|
+
if len(found) != 1 or found[0] != message:
|
|
87
|
+
raise ValueError("tool_member_observation_conflict")
|
|
88
|
+
return messages
|
|
89
|
+
return (*messages[:insertion], message, *messages[insertion:])
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def ordered_tool_artifact_refs(refs, messages, receipt_ref, baseline):
|
|
93
|
+
"""Keep pre-batch references, then member attachments in declaration order."""
|
|
94
|
+
if baseline is None:
|
|
95
|
+
return refs # An old intent does not authorize a reconstructed baseline.
|
|
96
|
+
available = {ref["uri"]: ref for ref in refs}
|
|
97
|
+
if any(uri not in available for uri in baseline):
|
|
98
|
+
raise ValueError("parallel_artifact_baseline_missing")
|
|
99
|
+
batch = []
|
|
100
|
+
for item in reversed(messages):
|
|
101
|
+
if item.get("role") == "assistant" and item.get("tool_calls"):
|
|
102
|
+
break
|
|
103
|
+
if item.get("role") == "tool" and item.get("receipt_ref") == receipt_ref:
|
|
104
|
+
batch.append(item)
|
|
105
|
+
order = dict.fromkeys((*baseline, *(
|
|
106
|
+
ref["uri"] for item in reversed(batch) for ref in item.get("artifact_refs", ())
|
|
107
|
+
), *available))
|
|
108
|
+
return tuple(available[uri] for uri in order)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def parallel_result_violation(result, *, delegated):
|
|
112
|
+
usage = result.resource_usage
|
|
113
|
+
return (
|
|
114
|
+
result.status in {"approval_required", "uncertain"}
|
|
115
|
+
or bool(result.workspace_changed_paths)
|
|
116
|
+
or not delegated and bool(usage.model_calls or usage.tool_calls or usage.child_run_ids)
|
|
117
|
+
or delegated and not usage.child_run_ids and bool(usage.model_calls)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _digest(value):
|
|
122
|
+
text = json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":"))
|
|
123
|
+
return hashlib.sha256(text.encode("utf-8")).hexdigest()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def seal_model_view(message, content, *, observed_history=False):
|
|
127
|
+
return {
|
|
128
|
+
**message,
|
|
129
|
+
"model_view": {
|
|
130
|
+
"version": OBSERVED_HISTORY_VERSION if observed_history else VERSION,
|
|
131
|
+
"source_digest": _digest(message["content"]),
|
|
132
|
+
"view_digest": _digest(content),
|
|
133
|
+
"content": content,
|
|
134
|
+
},
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def seal_typed_model_view(message, observation):
|
|
139
|
+
content = observation.message_content()
|
|
140
|
+
return {
|
|
141
|
+
**message,
|
|
142
|
+
"model_view": {
|
|
143
|
+
"version": TYPED_HISTORY_VERSION,
|
|
144
|
+
"source_digest": _digest(message["content"]),
|
|
145
|
+
"view_digest": _digest(content),
|
|
146
|
+
"content": content,
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _typed_model_content(content):
|
|
152
|
+
if isinstance(content, str):
|
|
153
|
+
blocks = ({"type": "text", "text": content},)
|
|
154
|
+
elif isinstance(content, list) and content:
|
|
155
|
+
blocks = tuple(content)
|
|
156
|
+
else:
|
|
157
|
+
raise ValueError("tool_model_view_invalid")
|
|
158
|
+
validated = tuple(
|
|
159
|
+
(ModelImageContent if block.get("type") == "image_url" else ModelTextContent)
|
|
160
|
+
.model_validate(block).model_dump(mode="json")
|
|
161
|
+
for block in blocks if isinstance(block, dict)
|
|
162
|
+
)
|
|
163
|
+
if len(validated) != len(blocks) or validated[0]["type"] != "text":
|
|
164
|
+
raise ValueError("tool_model_view_invalid")
|
|
165
|
+
text_bytes = sum(len(b["text"].encode()) for b in validated if b["type"] == "text")
|
|
166
|
+
images = [b for b in validated if b["type"] == "image_url"]
|
|
167
|
+
if not 0 < text_bytes <= 65536 or len(images) > 8:
|
|
168
|
+
raise ValueError("tool_model_view_invalid")
|
|
169
|
+
# Rehydration admits only the contract's absolute ceiling. Each live Run
|
|
170
|
+
# already governed media against its own (possibly smaller) pinned limit.
|
|
171
|
+
if sum(len(json.dumps(b, ensure_ascii=False, sort_keys=True,
|
|
172
|
+
separators=(",", ":")).encode()) for b in images) > 64 * 1024 * 1024:
|
|
173
|
+
raise ValueError("tool_model_view_invalid")
|
|
174
|
+
return validated
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def model_observation_message(message):
|
|
178
|
+
"""Project without I/O or mutating the authoritative receipt."""
|
|
179
|
+
copied = json.loads(json.dumps(message, ensure_ascii=False))
|
|
180
|
+
view = copied.pop("model_view", None)
|
|
181
|
+
if view is None:
|
|
182
|
+
return copied
|
|
183
|
+
if isinstance(view, dict) and view.get("version") == TYPED_HISTORY_VERSION:
|
|
184
|
+
try:
|
|
185
|
+
if (
|
|
186
|
+
copied.get("role") != "tool"
|
|
187
|
+
or set(view) != {"version", "source_digest", "view_digest", "content"}
|
|
188
|
+
or view["source_digest"] != _digest(copied.get("content"))
|
|
189
|
+
or view["view_digest"] != _digest(view["content"])
|
|
190
|
+
):
|
|
191
|
+
raise ValueError
|
|
192
|
+
blocks = _typed_model_content(view["content"])
|
|
193
|
+
source = json.loads(copied["content"])
|
|
194
|
+
projected = json.loads(blocks[0]["text"])
|
|
195
|
+
if (
|
|
196
|
+
not isinstance(source, dict) or not isinstance(projected, dict)
|
|
197
|
+
or source.get("status") not in {"ok", "error"}
|
|
198
|
+
or projected.get("status") != source["status"]
|
|
199
|
+
or set(source) != {"status", "content"}
|
|
200
|
+
or set(projected) != {"status", "content"}
|
|
201
|
+
):
|
|
202
|
+
raise ValueError
|
|
203
|
+
except (ValueError, TypeError, KeyError, AttributeError):
|
|
204
|
+
raise ValueError("tool_model_view_invalid") from None
|
|
205
|
+
copied["content"] = view["content"]
|
|
206
|
+
return copied
|
|
207
|
+
if (
|
|
208
|
+
copied.get("role") != "tool"
|
|
209
|
+
or not isinstance(view, dict)
|
|
210
|
+
or set(view) != {"version", "source_digest", "view_digest", "content"}
|
|
211
|
+
or view["version"] not in {VERSION, OBSERVED_HISTORY_VERSION}
|
|
212
|
+
or not isinstance(view["content"], str)
|
|
213
|
+
or not 0 < len(view["content"].encode("utf-8")) <= 65536
|
|
214
|
+
or view["source_digest"] != _digest(copied.get("content"))
|
|
215
|
+
or view["view_digest"] != _digest(view["content"])
|
|
216
|
+
):
|
|
217
|
+
raise ValueError("tool_model_view_invalid")
|
|
218
|
+
source = copied.get("content")
|
|
219
|
+
if isinstance(source, list):
|
|
220
|
+
if not source or source[0].get("type") != "text":
|
|
221
|
+
raise ValueError("tool_model_view_invalid")
|
|
222
|
+
source = source[0].get("text")
|
|
223
|
+
try:
|
|
224
|
+
original, projected = json.loads(source), json.loads(view["content"])
|
|
225
|
+
if any(
|
|
226
|
+
not isinstance(value, dict) or value.get("status") != "ok" or "content" not in value
|
|
227
|
+
for value in (original, projected)
|
|
228
|
+
):
|
|
229
|
+
raise ValueError
|
|
230
|
+
except (ValueError, TypeError):
|
|
231
|
+
raise ValueError("tool_model_view_invalid") from None
|
|
232
|
+
# A textual alternate view cannot resurrect auxiliary oversized text. The
|
|
233
|
+
# exact text stays canonical; explicit image blocks keep their own budget.
|
|
234
|
+
blocks = copied.get("content")
|
|
235
|
+
copied["content"] = (
|
|
236
|
+
[{"type": "text", "text": view["content"]},
|
|
237
|
+
*(block for block in blocks if block.get("type") == "image_url")]
|
|
238
|
+
if isinstance(blocks, list) else view["content"]
|
|
239
|
+
)
|
|
240
|
+
return copied
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def model_observation_messages(messages):
|
|
244
|
+
return tuple(model_observation_message(message) for message in messages)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def history_observation_message(message):
|
|
248
|
+
"""The locked receipt policy selects its historical observation consumer.
|
|
249
|
+
|
|
250
|
+
v1 deliberately quotes the canonical result. v2 quotes the complete
|
|
251
|
+
bounded model observation, including unread ranges and artifact access;
|
|
252
|
+
archiving raw text does not implicitly schedule that text for the model.
|
|
253
|
+
"""
|
|
254
|
+
view = message.get("model_view")
|
|
255
|
+
return (
|
|
256
|
+
model_observation_message(message)
|
|
257
|
+
if isinstance(view, dict)
|
|
258
|
+
and view.get("version") in {OBSERVED_HISTORY_VERSION, TYPED_HISTORY_VERSION} else message
|
|
259
|
+
)
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Warn once per unchanged tool streak, only after complete protocol batches.
|
|
2
|
+
|
|
3
|
+
Reference: OpenCode fe3f3a41 processor.ts:29,358-379 uses a threshold of
|
|
4
|
+
three repeated inputs; ZCode 872ad960 turn-tool-warnings.ts:52-79 injects
|
|
5
|
+
anomaly reminders. This independent adaptation also requires unchanged results
|
|
6
|
+
and only emits an observation: it never approves, stops, retries, or resets a
|
|
7
|
+
budget. Actual result payload timestamps remain meaningful; envelope identities,
|
|
8
|
+
timestamps and usage do not contribute to the comparison.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import hashlib
|
|
14
|
+
import json
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from typing import Literal
|
|
17
|
+
|
|
18
|
+
from pydantic import JsonValue
|
|
19
|
+
|
|
20
|
+
from .model import ModelToolCall
|
|
21
|
+
from .ports import ToolResult
|
|
22
|
+
from .state import Contract
|
|
23
|
+
|
|
24
|
+
REPEATED_TOOL_THRESHOLD = 3
|
|
25
|
+
Messages = tuple[dict[str, JsonValue], ...]
|
|
26
|
+
_OBSERVATIONS = {
|
|
27
|
+
"tool_loop_observation",
|
|
28
|
+
"model_recovery_observation",
|
|
29
|
+
"verification_observation",
|
|
30
|
+
"continuation_observation",
|
|
31
|
+
"background_child_observation",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ToolLoopWarning(Contract):
|
|
36
|
+
reason: Literal["repeated_tool_no_progress"] = "repeated_tool_no_progress"
|
|
37
|
+
threshold: Literal[3] = REPEATED_TOOL_THRESHOLD
|
|
38
|
+
observed_count: int
|
|
39
|
+
signature: str
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ToolProgressFeedback(Contract):
|
|
43
|
+
messages: Messages
|
|
44
|
+
warning: ToolLoopWarning | None = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _canonical(value: object) -> str:
|
|
48
|
+
return json.dumps(
|
|
49
|
+
value, sort_keys=True, ensure_ascii=False, separators=(",", ":"), allow_nan=False
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _calls(message: dict) -> tuple[ModelToolCall, ...]:
|
|
54
|
+
parsed = []
|
|
55
|
+
for raw in message["tool_calls"]:
|
|
56
|
+
function = raw["function"]
|
|
57
|
+
arguments = function["arguments"]
|
|
58
|
+
parsed.append(
|
|
59
|
+
ModelToolCall(
|
|
60
|
+
call_id=raw["id"],
|
|
61
|
+
name=function["name"],
|
|
62
|
+
arguments=json.loads(arguments) if isinstance(arguments, str) else arguments,
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
if not parsed or len({c.call_id for c in parsed}) != len(parsed):
|
|
66
|
+
raise ValueError("invalid tool batch")
|
|
67
|
+
return tuple(parsed)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _observation(message: dict) -> str | None:
|
|
71
|
+
value = message.get("content")
|
|
72
|
+
blocks = []
|
|
73
|
+
if isinstance(value, list) and value and value[0].get("type") == "text":
|
|
74
|
+
blocks, value = value[1:], value[0].get("text")
|
|
75
|
+
if isinstance(value, str):
|
|
76
|
+
try:
|
|
77
|
+
value = json.loads(value)
|
|
78
|
+
except ValueError:
|
|
79
|
+
pass
|
|
80
|
+
if isinstance(value, dict) and "status" in value:
|
|
81
|
+
if value["status"] not in {"ok", "error"}:
|
|
82
|
+
return None # Missing, uncertain or superseded results do not prove repetition.
|
|
83
|
+
value = {"status": value["status"], "content": value.get("content")}
|
|
84
|
+
return _canonical({"result": value, "blocks": blocks})
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class _Progress:
|
|
89
|
+
signature: str = ""
|
|
90
|
+
count: int = 0
|
|
91
|
+
warned: bool = False
|
|
92
|
+
valid: bool = True
|
|
93
|
+
pending: tuple[ModelToolCall, ...] = ()
|
|
94
|
+
results: dict[str, str | None] = field(default_factory=dict)
|
|
95
|
+
last_error: bool = False
|
|
96
|
+
|
|
97
|
+
def reset(self) -> None:
|
|
98
|
+
self.signature, self.count, self.warned = "", 0, False
|
|
99
|
+
self.last_error = False
|
|
100
|
+
|
|
101
|
+
def record(self, call: ModelToolCall, observation: str | None) -> None:
|
|
102
|
+
if observation is None:
|
|
103
|
+
self.reset()
|
|
104
|
+
return
|
|
105
|
+
signature = hashlib.sha256(
|
|
106
|
+
_canonical([call.name, call.arguments, observation]).encode()
|
|
107
|
+
).hexdigest()
|
|
108
|
+
projected = json.loads(observation).get("result")
|
|
109
|
+
self.last_error = isinstance(projected, dict) and projected.get("status") == "error"
|
|
110
|
+
if signature == self.signature:
|
|
111
|
+
self.count += 1
|
|
112
|
+
else:
|
|
113
|
+
self.signature, self.count, self.warned = signature, 1, False
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _scan(messages: Messages) -> _Progress:
|
|
117
|
+
progress = _Progress()
|
|
118
|
+
try:
|
|
119
|
+
for message in messages:
|
|
120
|
+
role = message.get("role")
|
|
121
|
+
if role == "tool":
|
|
122
|
+
call_id = message.get("tool_call_id")
|
|
123
|
+
if (
|
|
124
|
+
call_id not in {c.call_id for c in progress.pending}
|
|
125
|
+
or call_id in progress.results
|
|
126
|
+
):
|
|
127
|
+
raise ValueError("orphan or duplicate tool result")
|
|
128
|
+
progress.results[call_id] = _observation(message)
|
|
129
|
+
if len(progress.results) == len(progress.pending):
|
|
130
|
+
for call in progress.pending:
|
|
131
|
+
progress.record(call, progress.results[call.call_id])
|
|
132
|
+
progress.pending, progress.results = (), {}
|
|
133
|
+
continue
|
|
134
|
+
if progress.pending:
|
|
135
|
+
raise ValueError("interleaved tool batch")
|
|
136
|
+
if role == "assistant" and message.get("tool_calls"):
|
|
137
|
+
progress.pending = _calls(message)
|
|
138
|
+
elif role == "user":
|
|
139
|
+
if message.get("kind") not in _OBSERVATIONS:
|
|
140
|
+
progress.reset()
|
|
141
|
+
elif (
|
|
142
|
+
message.get("kind") == "tool_loop_observation"
|
|
143
|
+
and message.get("tool_progress_signature") == progress.signature
|
|
144
|
+
and progress.count >= REPEATED_TOOL_THRESHOLD
|
|
145
|
+
):
|
|
146
|
+
progress.warned = True
|
|
147
|
+
except (KeyError, TypeError, ValueError, AttributeError):
|
|
148
|
+
progress.valid = False
|
|
149
|
+
return progress
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def repeated_error_streak(messages: Messages) -> int:
|
|
153
|
+
"""Count identical, completed tool errors since the last changed observation."""
|
|
154
|
+
progress = _scan(messages)
|
|
155
|
+
if not progress.valid or progress.pending or not progress.last_error:
|
|
156
|
+
return 0
|
|
157
|
+
return progress.count
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _append_result(messages: Messages, call: ModelToolCall, result: ToolResult) -> Messages:
|
|
161
|
+
progress = _scan(messages)
|
|
162
|
+
if (
|
|
163
|
+
not progress.valid
|
|
164
|
+
or call not in progress.pending
|
|
165
|
+
or call.call_id in progress.results
|
|
166
|
+
or result.status not in {"ok", "error"}
|
|
167
|
+
):
|
|
168
|
+
raise ValueError("tool_progress_invalid_pending_result")
|
|
169
|
+
content = json.dumps({"status": result.status, "content": result.content}, ensure_ascii=False)
|
|
170
|
+
message = {"role": "tool", "tool_call_id": call.call_id, "content": content}
|
|
171
|
+
if result.content_blocks:
|
|
172
|
+
message["content"] = [
|
|
173
|
+
{"type": "text", "text": content},
|
|
174
|
+
*(block.model_dump(mode="json") for block in result.content_blocks),
|
|
175
|
+
]
|
|
176
|
+
return (*messages, message)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def tool_progress_feedback(
|
|
180
|
+
messages: Messages,
|
|
181
|
+
*,
|
|
182
|
+
call: ModelToolCall | None = None,
|
|
183
|
+
result: ToolResult | None = None,
|
|
184
|
+
) -> ToolProgressFeedback:
|
|
185
|
+
"""Project at ``tools.completed`` after appending all batch receipts.
|
|
186
|
+
|
|
187
|
+
Prefer complete history as input. The optional pair supports projecting a
|
|
188
|
+
newly finished result for a matching declared call; it cannot create a tool
|
|
189
|
+
request. A still-pending or malformed batch produces no warning. The caller
|
|
190
|
+
commits the returned messages and may emit ``warning`` as diagnostic data.
|
|
191
|
+
This does not change the goal, acceptance, budgets or effect execution state.
|
|
192
|
+
"""
|
|
193
|
+
if (call is None) != (result is None):
|
|
194
|
+
raise ValueError("tool_progress_requires_call_and_result")
|
|
195
|
+
if call is not None:
|
|
196
|
+
messages = _append_result(messages, call, result)
|
|
197
|
+
progress = _scan(messages)
|
|
198
|
+
if (
|
|
199
|
+
not progress.valid
|
|
200
|
+
or progress.pending
|
|
201
|
+
or progress.warned
|
|
202
|
+
or progress.count < REPEATED_TOOL_THRESHOLD
|
|
203
|
+
):
|
|
204
|
+
return ToolProgressFeedback(messages=messages)
|
|
205
|
+
warning = ToolLoopWarning(observed_count=progress.count, signature=progress.signature)
|
|
206
|
+
observation = {
|
|
207
|
+
"role": "user",
|
|
208
|
+
"kind": "tool_loop_observation",
|
|
209
|
+
"trust": "untrusted",
|
|
210
|
+
"tool_progress_signature": progress.signature,
|
|
211
|
+
"content": _canonical(
|
|
212
|
+
{
|
|
213
|
+
"reason": warning.reason,
|
|
214
|
+
"threshold": warning.threshold,
|
|
215
|
+
"observed_count": warning.observed_count,
|
|
216
|
+
"observation": "Recent completed tool calls repeated the same request and result. "
|
|
217
|
+
"No changed observation was detected. Reassess the next action using existing "
|
|
218
|
+
"evidence. This diagnostic does not change the user's goal, authorize a tool, "
|
|
219
|
+
"or establish task completion.",
|
|
220
|
+
}
|
|
221
|
+
),
|
|
222
|
+
}
|
|
223
|
+
return ToolProgressFeedback(messages=(*messages, observation), warning=warning)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Host-pinned recovery methods, with no fallback to ordinary tool execution."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Collection
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from .ports import ToolPort, ToolRequest, ToolResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def query_sealed_tool_result(
|
|
12
|
+
port: ToolPort | None, request: ToolRequest, *, owned_names: Collection[str] = (),
|
|
13
|
+
method: Literal[
|
|
14
|
+
"reconcile", "recover_prepared", "resume_prepared", "resume_checkpoint"
|
|
15
|
+
] = "reconcile",
|
|
16
|
+
) -> ToolResult:
|
|
17
|
+
# A wrapper may forward queries for other host capabilities, but its own
|
|
18
|
+
# tools do not acquire replay authority merely by sharing that wrapper.
|
|
19
|
+
query = getattr(port, method, None)
|
|
20
|
+
if request.call.name in owned_names or not callable(query):
|
|
21
|
+
return ToolResult(
|
|
22
|
+
status="uncertain", content={"error_code": "tool_reconciliation_unavailable"}
|
|
23
|
+
)
|
|
24
|
+
result = await query(request.model_copy(deep=True))
|
|
25
|
+
return ToolResult.model_validate_json(result.model_dump_json())
|