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,976 @@
|
|
|
1
|
+
"""Host-owned request planning and compaction sealing; stable public entry points.
|
|
2
|
+
|
|
3
|
+
Projection, partition construction and immutable contracts live in focused
|
|
4
|
+
modules. The caller still owns model I/O, durable intents and Run budgets."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import hashlib as hashlib
|
|
9
|
+
import json as json
|
|
10
|
+
from typing import Callable as Callable
|
|
11
|
+
from typing import Literal as Literal
|
|
12
|
+
|
|
13
|
+
from pydantic import AliasChoices as AliasChoices
|
|
14
|
+
from pydantic import BaseModel as BaseModel
|
|
15
|
+
from pydantic import ConfigDict as ConfigDict
|
|
16
|
+
from pydantic import Field as Field
|
|
17
|
+
from pydantic import JsonValue as JsonValue
|
|
18
|
+
from pydantic import model_serializer as model_serializer
|
|
19
|
+
from pydantic import model_validator as model_validator
|
|
20
|
+
|
|
21
|
+
from .completion import TaskContract as TaskContract
|
|
22
|
+
from .context import CompactionEnvelope as CompactionEnvelope
|
|
23
|
+
from .context import CompactionProjection as CompactionProjection
|
|
24
|
+
from .context import CompactionRejected as CompactionRejected
|
|
25
|
+
from .context import ContextBudget as ContextBudget
|
|
26
|
+
from .context import ContextMessage as ContextMessage
|
|
27
|
+
from .context import ExecutionContinuityState as ExecutionContinuityState
|
|
28
|
+
from .context import _tool_groups as _tool_groups
|
|
29
|
+
from .context import continuity_digest as continuity_digest
|
|
30
|
+
from .context import validate_compaction as validate_compaction
|
|
31
|
+
from .context_artifact_page import artifact_page_observation as artifact_page_observation
|
|
32
|
+
from .context_artifact_page import complete_artifact_call_ids as complete_artifact_call_ids
|
|
33
|
+
from .context_compaction_projection import seal_compaction_projection
|
|
34
|
+
from .context_fresh_tools import fresh_tool_group_refs
|
|
35
|
+
from .context_history import ContextRuntimeError as ContextRuntimeError
|
|
36
|
+
from .context_history import _content_blocks as _content_blocks
|
|
37
|
+
from .context_history import _goal_message_index
|
|
38
|
+
from .context_history import _historical_message as _historical_message
|
|
39
|
+
from .context_history import _json as _json
|
|
40
|
+
from .context_history import _unambiguous_json_object as _unambiguous_json_object
|
|
41
|
+
from .context_history import compact_historical_protocol as compact_historical_protocol
|
|
42
|
+
from .context_history import summary_media_blocks as summary_media_blocks
|
|
43
|
+
from .context_history import text_only_tool_message as text_only_tool_message
|
|
44
|
+
from .context_partition import BatchPartition as BatchPartition
|
|
45
|
+
from .context_partition import SummaryPartitionState as SummaryPartitionState
|
|
46
|
+
from .context_partition import acknowledge as acknowledge
|
|
47
|
+
from .context_partition import bind_pending as bind_pending
|
|
48
|
+
from .context_partition import expected_remaining_refs as expected_remaining_refs
|
|
49
|
+
from .context_partition import fragment_view as fragment_view
|
|
50
|
+
from .context_partition import new_coverage as new_coverage
|
|
51
|
+
from .context_partition import raw_batch_entries as raw_batch_entries
|
|
52
|
+
from .context_partition import require_complete as require_complete
|
|
53
|
+
from .context_partition import source_manifest as source_manifest
|
|
54
|
+
from .context_partition import validate_coverage as validate_coverage
|
|
55
|
+
from .context_pruning import project_fresh_workspace_reads as project_fresh_workspace_reads
|
|
56
|
+
from .context_pruning import project_historical_tool_result as project_historical_tool_result
|
|
57
|
+
from .context_pruning import project_workspace_read_result as project_workspace_read_result
|
|
58
|
+
from .context_request_projection import ContextRequestProjection
|
|
59
|
+
from .context_runtime_contracts import (
|
|
60
|
+
READER_SUMMARY_POLICY_VERSION as READER_SUMMARY_POLICY_VERSION,
|
|
61
|
+
)
|
|
62
|
+
from .context_runtime_contracts import (
|
|
63
|
+
CompactionHistory as CompactionHistory,
|
|
64
|
+
)
|
|
65
|
+
from .context_runtime_contracts import (
|
|
66
|
+
CompactionPolicy as CompactionPolicy,
|
|
67
|
+
)
|
|
68
|
+
from .context_runtime_contracts import (
|
|
69
|
+
CompactionProjectionOverflow as CompactionProjectionOverflow,
|
|
70
|
+
)
|
|
71
|
+
from .context_runtime_contracts import (
|
|
72
|
+
CompactionRequest as CompactionRequest,
|
|
73
|
+
)
|
|
74
|
+
from .context_runtime_contracts import (
|
|
75
|
+
CompactionResult as CompactionResult,
|
|
76
|
+
)
|
|
77
|
+
from .context_runtime_contracts import (
|
|
78
|
+
ContextPlan as ContextPlan,
|
|
79
|
+
)
|
|
80
|
+
from .context_runtime_contracts import (
|
|
81
|
+
Messages as Messages,
|
|
82
|
+
)
|
|
83
|
+
from .context_runtime_contracts import (
|
|
84
|
+
PreparedContext as PreparedContext,
|
|
85
|
+
)
|
|
86
|
+
from .context_runtime_contracts import (
|
|
87
|
+
_compacted_messages as _compacted_messages,
|
|
88
|
+
)
|
|
89
|
+
from .context_runtime_contracts import (
|
|
90
|
+
_complete_source_entry as _complete_source_entry,
|
|
91
|
+
)
|
|
92
|
+
from .context_runtime_contracts import (
|
|
93
|
+
_Contract as _Contract,
|
|
94
|
+
)
|
|
95
|
+
from .context_runtime_contracts import (
|
|
96
|
+
_full_reader_quote as _full_reader_quote,
|
|
97
|
+
)
|
|
98
|
+
from .context_runtime_contracts import (
|
|
99
|
+
_model_continuity as _model_continuity,
|
|
100
|
+
)
|
|
101
|
+
from .context_runtime_contracts import (
|
|
102
|
+
_refs as _refs,
|
|
103
|
+
)
|
|
104
|
+
from .context_runtime_contracts import (
|
|
105
|
+
_resume as _resume,
|
|
106
|
+
)
|
|
107
|
+
from .context_runtime_contracts import (
|
|
108
|
+
_summary as _summary,
|
|
109
|
+
)
|
|
110
|
+
from .context_runtime_contracts import (
|
|
111
|
+
_summary_continuation as _summary_continuation,
|
|
112
|
+
)
|
|
113
|
+
from .context_runtime_contracts import (
|
|
114
|
+
_summary_units as _summary_units,
|
|
115
|
+
)
|
|
116
|
+
from .context_runtime_contracts import (
|
|
117
|
+
source_context_digest as source_context_digest,
|
|
118
|
+
)
|
|
119
|
+
from .context_search import complete_search_call_ids as complete_search_call_ids
|
|
120
|
+
from .context_search import complete_search_observation as complete_search_observation
|
|
121
|
+
from .context_source_fragments import SourceTextPart as SourceTextPart
|
|
122
|
+
from .context_source_fragments import source_part_view as source_part_view
|
|
123
|
+
from .context_source_fragments import source_text_carrier as source_text_carrier
|
|
124
|
+
from .context_summary_planning import ContextSummaryPlanning
|
|
125
|
+
from .model import ModelProfile as ModelProfile
|
|
126
|
+
from .model import ModelReplayMetadata as ModelReplayMetadata
|
|
127
|
+
from .model_replay import replay_binding_failure as replay_binding_failure
|
|
128
|
+
from .model_replay import replay_fields as replay_fields
|
|
129
|
+
from .ports import ToolDefinition as ToolDefinition
|
|
130
|
+
from .ports import digest as digest
|
|
131
|
+
from .tool_observation import history_observation_message as history_observation_message
|
|
132
|
+
from .tool_observation import model_observation_message as model_observation_message
|
|
133
|
+
from .tool_observation import model_observation_messages as model_observation_messages
|
|
134
|
+
from .turn_control import ModelTurnControl as ModelTurnControl
|
|
135
|
+
from .user_document import user_document_indexes
|
|
136
|
+
|
|
137
|
+
_MAX_SUMMARY_CHUNKS = 8
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class ContextPlanner(ContextRequestProjection, ContextSummaryPlanning):
|
|
141
|
+
def __init__(
|
|
142
|
+
self,
|
|
143
|
+
*,
|
|
144
|
+
count_tokens: Callable[[str], int],
|
|
145
|
+
tokenizer_id: str,
|
|
146
|
+
policy: CompactionPolicy | None = None,
|
|
147
|
+
count_message_tokens: Callable[[dict[str, JsonValue]], int] | None = None,
|
|
148
|
+
tool_media_projection_version: Literal["source-profile-tool-media/v1"] | None = None,
|
|
149
|
+
summary_budget_unit: Literal["tokens", "estimated tokens", "UTF-8 bytes"] = "tokens",
|
|
150
|
+
summary_budget_mode: Literal["strict", "context_bounded_estimate"] = "strict",
|
|
151
|
+
summary_completion_policy: Literal["bounded-committed-summary/v1"] | None = None,
|
|
152
|
+
subagent_continuity_policy: Literal["accounted_child_runs/v1"] | None = None,
|
|
153
|
+
source_progress_policy: Literal["receipt-source-progress/v2"] | None = None,
|
|
154
|
+
) -> None:
|
|
155
|
+
if (
|
|
156
|
+
not callable(count_tokens)
|
|
157
|
+
or not isinstance(tokenizer_id, str)
|
|
158
|
+
or not tokenizer_id.strip()
|
|
159
|
+
):
|
|
160
|
+
raise ValueError("a host token counter and tokenizer_id are required")
|
|
161
|
+
if count_message_tokens is not None and not callable(count_message_tokens):
|
|
162
|
+
raise ValueError("message token counter must be callable")
|
|
163
|
+
if summary_budget_unit not in {"tokens", "estimated tokens", "UTF-8 bytes"}:
|
|
164
|
+
raise ValueError("unsupported summary budget unit")
|
|
165
|
+
if summary_budget_mode not in {"strict", "context_bounded_estimate"} or (
|
|
166
|
+
summary_budget_mode == "context_bounded_estimate"
|
|
167
|
+
and summary_budget_unit != "estimated tokens"
|
|
168
|
+
):
|
|
169
|
+
raise ValueError("context-bounded summary admission requires an estimated counter")
|
|
170
|
+
if tool_media_projection_version not in {None, "source-profile-tool-media/v1"}:
|
|
171
|
+
raise ValueError("unsupported tool media projection version")
|
|
172
|
+
self.tool_media_projection_version = tool_media_projection_version
|
|
173
|
+
self.count_tokens = count_tokens
|
|
174
|
+
# Effective source projection versions the counter input, not only
|
|
175
|
+
# its arithmetic. Existing history and ContextDriver binding inherit it.
|
|
176
|
+
self.tokenizer_id = (
|
|
177
|
+
f"{tokenizer_id}|{tool_media_projection_version}"
|
|
178
|
+
if tool_media_projection_version
|
|
179
|
+
else tokenizer_id
|
|
180
|
+
)
|
|
181
|
+
# tokenizer_id versions BOTH counters, including image cost/framing for
|
|
182
|
+
# the pinned provider projection. The host owns that model-specific math.
|
|
183
|
+
self.count_message_tokens = count_message_tokens
|
|
184
|
+
self.summary_budget_unit = summary_budget_unit
|
|
185
|
+
self.summary_budget_mode = summary_budget_mode
|
|
186
|
+
if summary_completion_policy not in {None, "bounded-committed-summary/v1"}:
|
|
187
|
+
raise ValueError("unsupported summary completion policy")
|
|
188
|
+
self.summary_completion_policy = summary_completion_policy
|
|
189
|
+
if subagent_continuity_policy not in {None, "accounted_child_runs/v1"}:
|
|
190
|
+
raise ValueError("unsupported subagent continuity policy")
|
|
191
|
+
self.subagent_continuity_policy = subagent_continuity_policy
|
|
192
|
+
if source_progress_policy not in {None, "receipt-source-progress/v2"}:
|
|
193
|
+
raise ValueError("unsupported source progress policy")
|
|
194
|
+
self.source_progress_policy = source_progress_policy
|
|
195
|
+
self.policy = policy or CompactionPolicy()
|
|
196
|
+
|
|
197
|
+
def plan(
|
|
198
|
+
self,
|
|
199
|
+
*,
|
|
200
|
+
source_revision: int,
|
|
201
|
+
model_turn: int,
|
|
202
|
+
profile: ModelProfile,
|
|
203
|
+
instructions: str,
|
|
204
|
+
tools: tuple[ToolDefinition, ...],
|
|
205
|
+
context_tools: tuple[ToolDefinition, ...] | None = None,
|
|
206
|
+
messages: Messages,
|
|
207
|
+
continuity: ExecutionContinuityState,
|
|
208
|
+
contract: TaskContract,
|
|
209
|
+
history: CompactionHistory | None = None,
|
|
210
|
+
force_compaction: bool = False,
|
|
211
|
+
turn_control: ModelTurnControl | None = None,
|
|
212
|
+
allow_compaction: bool = True,
|
|
213
|
+
) -> ContextPlan:
|
|
214
|
+
try:
|
|
215
|
+
return self._plan(
|
|
216
|
+
source_revision=source_revision,
|
|
217
|
+
model_turn=model_turn,
|
|
218
|
+
profile=profile,
|
|
219
|
+
instructions=instructions,
|
|
220
|
+
tools=tools,
|
|
221
|
+
context_tools=tools if context_tools is None else context_tools,
|
|
222
|
+
messages=messages,
|
|
223
|
+
continuity=continuity,
|
|
224
|
+
contract=contract,
|
|
225
|
+
history=history or CompactionHistory(),
|
|
226
|
+
force_compaction=force_compaction,
|
|
227
|
+
turn_control=turn_control,
|
|
228
|
+
allow_compaction=allow_compaction,
|
|
229
|
+
)
|
|
230
|
+
except ContextRuntimeError as exc:
|
|
231
|
+
return ContextPlan(action="blocked", reason=str(exc))
|
|
232
|
+
except (CompactionRejected, ValueError, KeyError, TypeError):
|
|
233
|
+
return ContextPlan(action="blocked", reason="context_protocol_invalid")
|
|
234
|
+
|
|
235
|
+
def _active(
|
|
236
|
+
self,
|
|
237
|
+
messages: Messages,
|
|
238
|
+
continuity: ExecutionContinuityState,
|
|
239
|
+
history: CompactionHistory,
|
|
240
|
+
) -> tuple[tuple[str, ...], Messages, str]:
|
|
241
|
+
refs = _refs(messages)
|
|
242
|
+
if history.count:
|
|
243
|
+
if history.summary_completion_policy != self.summary_completion_policy:
|
|
244
|
+
raise ContextRuntimeError("context_summary_completion_policy_changed")
|
|
245
|
+
if history.tokenizer_id != self.tokenizer_id:
|
|
246
|
+
raise ContextRuntimeError("context_tokenizer_changed")
|
|
247
|
+
prefix = messages[: history.prefix_message_count]
|
|
248
|
+
if (
|
|
249
|
+
len(prefix) != history.prefix_message_count
|
|
250
|
+
or source_context_digest(prefix) != history.prefix_digest
|
|
251
|
+
or history.contract_digest != continuity.contract_digest
|
|
252
|
+
):
|
|
253
|
+
raise ContextRuntimeError("context_history_changed")
|
|
254
|
+
if (
|
|
255
|
+
not history.summary_text.strip()
|
|
256
|
+
or not set(history.retained_message_refs).issubset(
|
|
257
|
+
refs[: history.prefix_message_count]
|
|
258
|
+
)
|
|
259
|
+
or len(set(history.retained_message_refs)) != len(history.retained_message_refs)
|
|
260
|
+
):
|
|
261
|
+
raise ContextRuntimeError("context_history_invalid")
|
|
262
|
+
indexes = [
|
|
263
|
+
i
|
|
264
|
+
for i, ref in enumerate(refs)
|
|
265
|
+
if i >= history.prefix_message_count or ref in history.retained_message_refs
|
|
266
|
+
]
|
|
267
|
+
else:
|
|
268
|
+
indexes = list(range(len(messages)))
|
|
269
|
+
# A correction creates a new source receipt. Keep the old transcript
|
|
270
|
+
# and compaction prefix immutable, but do not present superseded data
|
|
271
|
+
# as the current goal's Context. Other history remains ordinary input.
|
|
272
|
+
indexes = [
|
|
273
|
+
i for i in indexes
|
|
274
|
+
if messages[i].get("kind") != "context_contribution"
|
|
275
|
+
or messages[i].get("goal_revision") == continuity.goal_revision
|
|
276
|
+
]
|
|
277
|
+
indexes = [
|
|
278
|
+
i for i in indexes
|
|
279
|
+
if messages[i].get("kind") != "context_contribution"
|
|
280
|
+
or messages[i].get("context_operation_key") is None
|
|
281
|
+
or messages[i].get("context_operation_key") == continuity.context_source_operation_key
|
|
282
|
+
]
|
|
283
|
+
active_refs = tuple(refs[i] for i in indexes)
|
|
284
|
+
active = tuple(messages[i] for i in indexes)
|
|
285
|
+
return active_refs, active, active_refs[_goal_message_index(active, continuity.goal)]
|
|
286
|
+
|
|
287
|
+
def _plan(
|
|
288
|
+
self,
|
|
289
|
+
*,
|
|
290
|
+
source_revision,
|
|
291
|
+
model_turn,
|
|
292
|
+
profile,
|
|
293
|
+
instructions,
|
|
294
|
+
tools,
|
|
295
|
+
context_tools,
|
|
296
|
+
messages,
|
|
297
|
+
continuity,
|
|
298
|
+
contract,
|
|
299
|
+
history,
|
|
300
|
+
force_compaction,
|
|
301
|
+
turn_control,
|
|
302
|
+
allow_compaction,
|
|
303
|
+
) -> ContextPlan:
|
|
304
|
+
if turn_control is not None:
|
|
305
|
+
turn_control.validate_tools(
|
|
306
|
+
tuple(tool.name for tool in tools),
|
|
307
|
+
stable_catalog=profile.tool_catalog_policy == "stable-task/v1",
|
|
308
|
+
)
|
|
309
|
+
required = tuple(item for item in contract.items if item.required)
|
|
310
|
+
if continuity.contract_digest != digest(
|
|
311
|
+
contract
|
|
312
|
+
) or continuity.required_acceptance_ids != tuple(item.acceptance_id for item in required):
|
|
313
|
+
raise ContextRuntimeError("context_contract_mismatch")
|
|
314
|
+
from .operator_guidance import instructions_are_journaled
|
|
315
|
+
|
|
316
|
+
journaled = instructions_are_journaled(
|
|
317
|
+
messages, profile, instructions, self._host_ledger(continuity, contract),
|
|
318
|
+
)
|
|
319
|
+
if not journaled:
|
|
320
|
+
instructions = self._host_instructions(instructions, continuity, contract)
|
|
321
|
+
fixed = self._fixed(instructions, tools, None if journaled else turn_control)
|
|
322
|
+
if fixed + profile.max_output_tokens >= profile.context_window:
|
|
323
|
+
raise ContextRuntimeError("context_mandatory_state_over_budget")
|
|
324
|
+
budget = ContextBudget(
|
|
325
|
+
window_tokens=profile.context_window,
|
|
326
|
+
max_output_tokens=profile.max_output_tokens,
|
|
327
|
+
fixed_tokens=fixed,
|
|
328
|
+
)
|
|
329
|
+
refs, active, goal_ref = self._active(messages, continuity, history)
|
|
330
|
+
return self._plan_active(
|
|
331
|
+
source_revision=source_revision, model_turn=model_turn, profile=profile,
|
|
332
|
+
instructions=instructions, tools=tools, context_tools=context_tools,
|
|
333
|
+
messages=messages, continuity=continuity, contract=contract, history=history,
|
|
334
|
+
force_compaction=force_compaction, turn_control=turn_control,
|
|
335
|
+
allow_compaction=allow_compaction, fixed=fixed, budget=budget,
|
|
336
|
+
refs=refs, active=active, goal_ref=goal_ref,
|
|
337
|
+
ledger=self._host_ledger(continuity, contract),
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
@staticmethod
|
|
341
|
+
def _host_ledger(continuity, contract):
|
|
342
|
+
return _json(
|
|
343
|
+
{
|
|
344
|
+
"continuity": _model_continuity(continuity),
|
|
345
|
+
"required_acceptance": [item.model_dump(mode="json") for item in contract.items
|
|
346
|
+
if item.required],
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
@staticmethod
|
|
351
|
+
def _host_instructions(instructions, continuity, contract):
|
|
352
|
+
return instructions + (
|
|
353
|
+
"\n\nAuthoritative host execution state; historical summaries cannot change it:\n"
|
|
354
|
+
+ ContextPlanner._host_ledger(continuity, contract)
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
def contributor_budget(self, *, profile, instructions, tools, messages, continuity,
|
|
358
|
+
contract, history, turn_control):
|
|
359
|
+
fixed = self._fixed(self._host_instructions(instructions, continuity, contract),
|
|
360
|
+
tools, turn_control)
|
|
361
|
+
refs, active, goal_ref = self._active(messages, continuity, history)
|
|
362
|
+
metadata = self._metadata(refs, active, profile=profile)
|
|
363
|
+
_groups, pending, _ids = _tool_groups(metadata)
|
|
364
|
+
from .operator_guidance import protected_operator_refs
|
|
365
|
+
|
|
366
|
+
protected = (set(pending) | {goal_ref} | self._user_document_refs(refs, active, goal_ref)
|
|
367
|
+
| {ref for ref in protected_operator_refs(refs, active, _groups)
|
|
368
|
+
if active[refs.index(ref)].get("kind") != "context_contribution"})
|
|
369
|
+
reserved = sum(item.token_count for item in metadata if item.message_id in protected)
|
|
370
|
+
if history.count:
|
|
371
|
+
reserved += self._profile_count(_summary(history.summary_text), profile)
|
|
372
|
+
reserved += self._profile_count(_resume(), profile)
|
|
373
|
+
return max(0, profile.context_window - profile.max_output_tokens - fixed - reserved)
|
|
374
|
+
|
|
375
|
+
@staticmethod
|
|
376
|
+
def _user_document_refs(refs, active, goal_ref):
|
|
377
|
+
try:
|
|
378
|
+
return {refs[index] for index in user_document_indexes(active, refs.index(goal_ref))}
|
|
379
|
+
except ValueError as exc:
|
|
380
|
+
raise ContextRuntimeError("native_user_document_source_mismatch") from exc
|
|
381
|
+
|
|
382
|
+
def _plan_active(self, *, source_revision, model_turn, profile, instructions, tools,
|
|
383
|
+
context_tools, messages, continuity, contract, history, force_compaction,
|
|
384
|
+
turn_control, allow_compaction, fixed, budget, refs, active, goal_ref, ledger):
|
|
385
|
+
from .context_replay import compaction_replay_view
|
|
386
|
+
from .replay_context import request_header_digest
|
|
387
|
+
|
|
388
|
+
header = request_header_digest(instructions, tools, profile)
|
|
389
|
+
|
|
390
|
+
if history.count and (
|
|
391
|
+
history.provider_replay_projection_policy != profile.provider_replay_projection_policy
|
|
392
|
+
):
|
|
393
|
+
raise ContextRuntimeError("context_provider_replay_policy_changed")
|
|
394
|
+
replay_view = compaction_replay_view(
|
|
395
|
+
active, refs, covered_refs=history.retained_message_refs, profile=profile,
|
|
396
|
+
root_prefix_digest=history.prefix_digest,
|
|
397
|
+
)
|
|
398
|
+
reader_names = frozenset(
|
|
399
|
+
tool.name
|
|
400
|
+
for tool in context_tools
|
|
401
|
+
if tool.read_only and tool.context_role == "workspace_read"
|
|
402
|
+
)
|
|
403
|
+
search_names = frozenset(
|
|
404
|
+
tool.name
|
|
405
|
+
for tool in context_tools
|
|
406
|
+
if tool.read_only and tool.context_role == "workspace_search"
|
|
407
|
+
)
|
|
408
|
+
artifact_reader_names = frozenset(
|
|
409
|
+
tool.name for tool in context_tools
|
|
410
|
+
if tool.read_only and tool.context_role == "artifact_read"
|
|
411
|
+
)
|
|
412
|
+
capture_reader_names = frozenset(
|
|
413
|
+
tool.name for tool in context_tools
|
|
414
|
+
if tool.name in reader_names and tool.result_archive_policy == "archived-model-view/v3"
|
|
415
|
+
) | artifact_reader_names
|
|
416
|
+
metadata = self._metadata(refs, active, counted_messages=replay_view, profile=profile)
|
|
417
|
+
groups, pending_refs, pending_ids = _tool_groups(metadata)
|
|
418
|
+
fresh_group = fresh_tool_group_refs(messages)
|
|
419
|
+
if not fresh_group.issubset(refs):
|
|
420
|
+
# A prior summary may already cover the original trailing group.
|
|
421
|
+
fresh_group = frozenset()
|
|
422
|
+
if pending_ids != frozenset(continuity.pending_tool_call_ids):
|
|
423
|
+
raise ContextRuntimeError("context_pending_tool_mismatch")
|
|
424
|
+
summary_limit = min(self.policy.summary_max_tokens, profile.max_output_tokens)
|
|
425
|
+
reserved_summary = self.summary_reservation(profile)
|
|
426
|
+
from .operator_guidance import protected_operator_refs
|
|
427
|
+
|
|
428
|
+
mandatory = (
|
|
429
|
+
set(pending_refs) | {goal_ref} | protected_operator_refs(refs, active, groups)
|
|
430
|
+
| self._user_document_refs(refs, active, goal_ref)
|
|
431
|
+
| {ref for ref, raw in zip(refs, active)
|
|
432
|
+
if raw.get("kind") == "context_contribution"
|
|
433
|
+
and raw.get("goal_revision") == continuity.goal_revision}
|
|
434
|
+
| {ref for ref, raw in zip(refs, active)
|
|
435
|
+
if raw.get("kind") == "background_child_observation"
|
|
436
|
+
and raw.get("child_run_id") in continuity.pending_subagent_refs}
|
|
437
|
+
)
|
|
438
|
+
hook_refs = {raw.get("hook_operation_key"): ref for ref, raw in zip(refs, active)
|
|
439
|
+
if raw.get("kind") == "hook_context"
|
|
440
|
+
and raw.get("hook_goal_revision") == continuity.goal_revision}
|
|
441
|
+
guidance_refs = {raw.get("input_id"): ref for ref, raw in zip(refs, active)
|
|
442
|
+
if raw.get("role") == "user" and raw.get("kind") == "user_guidance"
|
|
443
|
+
and raw.get("input_goal_revision") == continuity.goal_revision}
|
|
444
|
+
if not set(continuity.pending_guidance_ids).issubset(guidance_refs):
|
|
445
|
+
raise ContextRuntimeError("context_pending_guidance_missing")
|
|
446
|
+
mandatory |= {guidance_refs[key] for key in continuity.pending_guidance_ids}
|
|
447
|
+
if not set(continuity.pending_hook_operation_keys).issubset(hook_refs):
|
|
448
|
+
raise ContextRuntimeError("context_pending_hook_missing")
|
|
449
|
+
mandatory |= {hook_refs[key] for key in continuity.pending_hook_operation_keys}
|
|
450
|
+
protected_readers = frozenset()
|
|
451
|
+
if groups and self.policy.read_working_set_count and not force_compaction:
|
|
452
|
+
latest = groups[-1]
|
|
453
|
+
definitions = {tool.name: tool for tool in context_tools}
|
|
454
|
+
calls = [
|
|
455
|
+
call
|
|
456
|
+
for ref, raw in zip(refs, active)
|
|
457
|
+
if ref in latest
|
|
458
|
+
for call in raw.get("tool_calls", ())
|
|
459
|
+
]
|
|
460
|
+
group_cost = sum(m.token_count for m in metadata if m.message_id in latest)
|
|
461
|
+
if (
|
|
462
|
+
group_cost <= self.policy.read_working_set_max_tokens
|
|
463
|
+
and group_cost <= self.policy.read_working_set_total_max_tokens
|
|
464
|
+
and sum(m.token_count for m in metadata if m.message_id in latest | mandatory)
|
|
465
|
+
+ reserved_summary
|
|
466
|
+
<= budget.input_capacity
|
|
467
|
+
and all(
|
|
468
|
+
(definition := definitions.get(call["function"]["name"])) is not None
|
|
469
|
+
and (definition.read_only or definition.context_role == "task_planning")
|
|
470
|
+
for call in calls
|
|
471
|
+
)
|
|
472
|
+
):
|
|
473
|
+
# Compaction should reduce earlier history before clipping a
|
|
474
|
+
# latest, bounded complete source batch that already fits.
|
|
475
|
+
# A provider-reported overflow deliberately disables this.
|
|
476
|
+
protected_readers = frozenset(
|
|
477
|
+
call["id"] for call in calls if call["function"]["name"] in reader_names
|
|
478
|
+
)
|
|
479
|
+
read_view = self._read_view(replay_view, reader_names, protected_readers)
|
|
480
|
+
if read_view != active:
|
|
481
|
+
metadata = self._metadata(refs, active, counted_messages=read_view, profile=profile)
|
|
482
|
+
visible = (
|
|
483
|
+
_compacted_messages(history.summary_text, replay_view, continuity.goal)
|
|
484
|
+
if history.count
|
|
485
|
+
else replay_view
|
|
486
|
+
)
|
|
487
|
+
prepared = self._prepared(instructions, visible, fixed, turn_control,
|
|
488
|
+
profile=profile, goal=continuity.goal,
|
|
489
|
+
abandoned=history.abandoned_replay_digests,
|
|
490
|
+
replay_header_digest=header)
|
|
491
|
+
if (self.policy.enabled and self.policy.prune_tool_results and not force_compaction
|
|
492
|
+
and prepared.counted_input_tokens - budget.fixed_tokens
|
|
493
|
+
>= budget.input_capacity * self.policy.trigger_ratio):
|
|
494
|
+
pruned = self._prune_old_results(
|
|
495
|
+
prepared, refs=refs, active=replay_view, groups=groups, mandatory=mandatory,
|
|
496
|
+
metadata=metadata, continuity=continuity, history=history, tools=context_tools,
|
|
497
|
+
profile=profile, fixed=fixed, turn_control=turn_control,
|
|
498
|
+
)
|
|
499
|
+
if (pruned is not None and pruned.counted_input_tokens - budget.fixed_tokens
|
|
500
|
+
< budget.input_capacity * self.policy.trigger_ratio):
|
|
501
|
+
return ContextPlan(action="ready", reason="historical_tool_results_within_budget",
|
|
502
|
+
prepared=pruned)
|
|
503
|
+
if not self.policy.enabled:
|
|
504
|
+
if (force_compaction or prepared.counted_input_tokens + profile.max_output_tokens
|
|
505
|
+
> profile.context_window):
|
|
506
|
+
raise ContextRuntimeError("context_compaction_disabled")
|
|
507
|
+
return ContextPlan(
|
|
508
|
+
action="ready", reason="context_compaction_disabled", prepared=prepared
|
|
509
|
+
)
|
|
510
|
+
if not allow_compaction:
|
|
511
|
+
# A soft context target cannot spend a model call reserved for
|
|
512
|
+
# delivery. Keep the complete currently authorized projection;
|
|
513
|
+
# never seal a partial summary or drop evidence to make it fit.
|
|
514
|
+
if (force_compaction or prepared.counted_input_tokens + profile.max_output_tokens
|
|
515
|
+
> profile.context_window):
|
|
516
|
+
raise ContextRuntimeError("context_finalization_budget_unavailable")
|
|
517
|
+
return ContextPlan(
|
|
518
|
+
action="ready", reason="context_finalization_reserved", prepared=prepared
|
|
519
|
+
)
|
|
520
|
+
fresh_search_ids = (
|
|
521
|
+
complete_search_call_ids(
|
|
522
|
+
[raw for ref, raw in zip(refs, active) if ref in groups[-1]],
|
|
523
|
+
tool_names=search_names,
|
|
524
|
+
)
|
|
525
|
+
if groups
|
|
526
|
+
else frozenset()
|
|
527
|
+
)
|
|
528
|
+
fresh_artifact_ids = (
|
|
529
|
+
complete_artifact_call_ids(
|
|
530
|
+
[raw for ref, raw in zip(refs, active) if ref in groups[-1]],
|
|
531
|
+
tool_names=artifact_reader_names,
|
|
532
|
+
) if groups else frozenset()
|
|
533
|
+
)
|
|
534
|
+
if (
|
|
535
|
+
not force_compaction
|
|
536
|
+
and groups
|
|
537
|
+
and (fresh_group or refs[-1] in groups[-1])
|
|
538
|
+
and (
|
|
539
|
+
fresh_group
|
|
540
|
+
or fresh_search_ids
|
|
541
|
+
or fresh_artifact_ids
|
|
542
|
+
or any(
|
|
543
|
+
call["function"]["name"] in reader_names
|
|
544
|
+
for ref, raw in zip(refs, active)
|
|
545
|
+
if ref in groups[-1]
|
|
546
|
+
for call in raw.get("tool_calls", ())
|
|
547
|
+
)
|
|
548
|
+
)
|
|
549
|
+
and prepared.counted_input_tokens + profile.max_output_tokens <= profile.context_window
|
|
550
|
+
):
|
|
551
|
+
# The soft compaction target must not hide a just-returned source
|
|
552
|
+
# batch that fits the locked complete request. Provider overflow
|
|
553
|
+
# still takes the existing reduction path.
|
|
554
|
+
return ContextPlan(
|
|
555
|
+
action="ready",
|
|
556
|
+
reason=(
|
|
557
|
+
"fresh_search_complete_request_fits"
|
|
558
|
+
if fresh_search_ids
|
|
559
|
+
else "fresh_artifact_complete_request_fits"
|
|
560
|
+
if fresh_artifact_ids
|
|
561
|
+
else "fresh_reader_complete_request_fits"
|
|
562
|
+
if any(
|
|
563
|
+
call["function"]["name"] in reader_names
|
|
564
|
+
for ref, raw in zip(refs, active) if ref in groups[-1]
|
|
565
|
+
for call in raw.get("tool_calls", ())
|
|
566
|
+
)
|
|
567
|
+
else "fresh_tool_complete_request_fits"
|
|
568
|
+
),
|
|
569
|
+
prepared=prepared,
|
|
570
|
+
)
|
|
571
|
+
if (
|
|
572
|
+
not force_compaction
|
|
573
|
+
and prepared.counted_input_tokens - budget.fixed_tokens
|
|
574
|
+
< budget.input_capacity * self.policy.trigger_ratio
|
|
575
|
+
):
|
|
576
|
+
return ContextPlan(action="ready", reason="context_within_budget", prepared=prepared)
|
|
577
|
+
if not force_compaction and self.policy.fresh_read_max_chars is not None:
|
|
578
|
+
observed = self._read_view(visible, reader_names, protected_readers)
|
|
579
|
+
if observed != visible:
|
|
580
|
+
view = self._prepared(instructions, observed, fixed, turn_control,
|
|
581
|
+
profile=profile, goal=continuity.goal,
|
|
582
|
+
abandoned=history.abandoned_replay_digests,
|
|
583
|
+
replay_header_digest=header)
|
|
584
|
+
if view.counted_input_tokens + profile.max_output_tokens <= profile.context_window:
|
|
585
|
+
return ContextPlan(
|
|
586
|
+
action="ready",
|
|
587
|
+
reason="fresh_reader_observations_within_budget",
|
|
588
|
+
prepared=view,
|
|
589
|
+
)
|
|
590
|
+
# Growing history must not progressively starve the newest
|
|
591
|
+
# source observation. Reduce old history through compaction
|
|
592
|
+
# rather than shrinking all fresh windows down to 128 chars.
|
|
593
|
+
# The host's summary ceiling and the provider's output-token cap are
|
|
594
|
+
# different units. Reasoning tokens can consume the provider cap before
|
|
595
|
+
# any visible summary appears; enforce the host ceiling only when the
|
|
596
|
+
# visible summary is sealed. Only the actual hard request window may
|
|
597
|
+
# reduce a complete Reader quote's provider output cap.
|
|
598
|
+
mandatory_cost = sum(m.token_count for m in metadata if m.message_id in mandatory)
|
|
599
|
+
if mandatory_cost + reserved_summary > budget.input_capacity:
|
|
600
|
+
raise ContextRuntimeError("context_mandatory_state_over_budget")
|
|
601
|
+
retained = self._retain(
|
|
602
|
+
metadata,
|
|
603
|
+
groups,
|
|
604
|
+
pending_refs,
|
|
605
|
+
mandatory,
|
|
606
|
+
budget,
|
|
607
|
+
reserved_summary,
|
|
608
|
+
active=active,
|
|
609
|
+
continuity=continuity,
|
|
610
|
+
history=history,
|
|
611
|
+
tools=context_tools,
|
|
612
|
+
force_compaction=force_compaction,
|
|
613
|
+
fresh_group=fresh_group,
|
|
614
|
+
)
|
|
615
|
+
dropped = tuple(raw for ref, raw in zip(refs, active) if ref not in retained)
|
|
616
|
+
if not dropped:
|
|
617
|
+
if force_compaction:
|
|
618
|
+
raise ContextRuntimeError("context_overflow_no_reducible_history")
|
|
619
|
+
if prepared.counted_input_tokens + profile.max_output_tokens > profile.context_window:
|
|
620
|
+
raise ContextRuntimeError("context_mandatory_state_over_budget")
|
|
621
|
+
return ContextPlan(
|
|
622
|
+
action="ready", reason="context_no_reducible_history", prepared=prepared
|
|
623
|
+
)
|
|
624
|
+
if (
|
|
625
|
+
self.policy.max_compactions is not None
|
|
626
|
+
and history.total_compactions >= self.policy.max_compactions
|
|
627
|
+
):
|
|
628
|
+
raise ContextRuntimeError("context_compaction_limit")
|
|
629
|
+
observed_progress = history.count > 0 and (
|
|
630
|
+
continuity.observed_progress_revision > history.last_observed_progress_revision
|
|
631
|
+
or (
|
|
632
|
+
continuity.workspace_revision is not None
|
|
633
|
+
and continuity.workspace_revision != history.last_workspace_revision
|
|
634
|
+
)
|
|
635
|
+
)
|
|
636
|
+
if (
|
|
637
|
+
history.count
|
|
638
|
+
and not observed_progress
|
|
639
|
+
and history.stagnant_count >= self.policy.max_compactions_without_progress
|
|
640
|
+
):
|
|
641
|
+
raise ContextRuntimeError("context_compaction_no_observed_progress")
|
|
642
|
+
if (
|
|
643
|
+
history.total_compactions
|
|
644
|
+
and model_turn - history.last_model_turn < self.policy.min_model_turns_between
|
|
645
|
+
):
|
|
646
|
+
raise ContextRuntimeError("context_rapid_refill")
|
|
647
|
+
return self._request(
|
|
648
|
+
source_revision,
|
|
649
|
+
model_turn,
|
|
650
|
+
profile,
|
|
651
|
+
instructions,
|
|
652
|
+
messages,
|
|
653
|
+
continuity,
|
|
654
|
+
history,
|
|
655
|
+
metadata,
|
|
656
|
+
refs,
|
|
657
|
+
active,
|
|
658
|
+
retained,
|
|
659
|
+
dropped,
|
|
660
|
+
budget,
|
|
661
|
+
summary_limit,
|
|
662
|
+
ledger,
|
|
663
|
+
turn_control,
|
|
664
|
+
reader_names,
|
|
665
|
+
protected_readers,
|
|
666
|
+
search_names=search_names,
|
|
667
|
+
capture_reader_names=capture_reader_names,
|
|
668
|
+
artifact_reader_names=artifact_reader_names,
|
|
669
|
+
replay_header_digest=header,
|
|
670
|
+
fresh_group=fresh_group,
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
class CompactionController:
|
|
675
|
+
def __init__(self, planner: ContextPlanner) -> None:
|
|
676
|
+
self.planner = planner
|
|
677
|
+
|
|
678
|
+
def continue_summary(
|
|
679
|
+
self,
|
|
680
|
+
request: CompactionRequest,
|
|
681
|
+
fragment: str,
|
|
682
|
+
*,
|
|
683
|
+
current_revision: int,
|
|
684
|
+
current_continuity: ExecutionContinuityState,
|
|
685
|
+
current_messages: Messages,
|
|
686
|
+
provider_replay: ModelReplayMetadata | None = None,
|
|
687
|
+
) -> CompactionRequest:
|
|
688
|
+
self._validate_source(request, current_revision, current_continuity, current_messages)
|
|
689
|
+
if failure := replay_binding_failure(request.profile, provider_replay, required=True):
|
|
690
|
+
raise ContextRuntimeError(failure)
|
|
691
|
+
if request.summary_continuations >= request.profile.max_continuations:
|
|
692
|
+
raise ContextRuntimeError("compaction_summary_continuation_exhausted")
|
|
693
|
+
fragments = (*request.summary_fragments, fragment)
|
|
694
|
+
self._validate_summary(request, "".join(fragments))
|
|
695
|
+
messages = (
|
|
696
|
+
*request.summary_messages,
|
|
697
|
+
{"role": "assistant", "content": fragment, **replay_fields(provider_replay)},
|
|
698
|
+
_summary_continuation(),
|
|
699
|
+
)
|
|
700
|
+
counted = self.planner._fixed(request.summary_instructions, ()) + sum(
|
|
701
|
+
self.planner._count_message(message) for message in
|
|
702
|
+
self.planner._media_view(messages, request.profile, purpose="compaction")
|
|
703
|
+
)
|
|
704
|
+
output_limit = (
|
|
705
|
+
min(request.summary_output_tokens, request.profile.context_window - counted)
|
|
706
|
+
if request.full_reader_quote
|
|
707
|
+
else request.summary_output_tokens
|
|
708
|
+
)
|
|
709
|
+
if output_limit <= 0 or counted + output_limit > request.profile.context_window:
|
|
710
|
+
raise ContextRuntimeError("context_summary_continuation_over_budget")
|
|
711
|
+
return CompactionRequest.model_validate(
|
|
712
|
+
{
|
|
713
|
+
**request.model_dump(mode="json"),
|
|
714
|
+
"summary_messages": messages,
|
|
715
|
+
"summary_counted_input_tokens": counted,
|
|
716
|
+
"summary_output_tokens": output_limit,
|
|
717
|
+
"summary_fragments": fragments,
|
|
718
|
+
"summary_continuations": request.summary_continuations + 1,
|
|
719
|
+
}
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
def advance(
|
|
723
|
+
self,
|
|
724
|
+
request: CompactionRequest,
|
|
725
|
+
summary_text: str,
|
|
726
|
+
*,
|
|
727
|
+
current_revision: int,
|
|
728
|
+
current_continuity: ExecutionContinuityState,
|
|
729
|
+
current_messages: Messages,
|
|
730
|
+
) -> CompactionRequest | CompactionResult:
|
|
731
|
+
self._validate_source(request, current_revision, current_continuity, current_messages)
|
|
732
|
+
summary_text = "".join((*request.summary_fragments, summary_text))
|
|
733
|
+
self._validate_summary(request, summary_text)
|
|
734
|
+
request = self._acknowledge_partition(request, current_messages)
|
|
735
|
+
if not request.remaining_history_entries:
|
|
736
|
+
return self.seal(
|
|
737
|
+
request,
|
|
738
|
+
summary_text,
|
|
739
|
+
current_revision=current_revision,
|
|
740
|
+
current_continuity=current_continuity,
|
|
741
|
+
current_messages=current_messages,
|
|
742
|
+
)
|
|
743
|
+
chunk_limit = _MAX_SUMMARY_CHUNKS
|
|
744
|
+
if request.summary_partition and request.summary_partition.partitions:
|
|
745
|
+
manifest, raw = source_manifest(
|
|
746
|
+
current_messages, request.old_messages, request.retained_message_refs,
|
|
747
|
+
capture_reader_names=request.source_capture_reader_names,
|
|
748
|
+
fresh_tool_observation_policy=request.fresh_tool_observation_policy,
|
|
749
|
+
fresh_tool_message_refs=request.fresh_tool_message_refs,
|
|
750
|
+
fresh_text_fragment_policy=request.fresh_text_fragment_policy,
|
|
751
|
+
fresh_text_excluded_tool_names=request.source_reader_names,
|
|
752
|
+
)
|
|
753
|
+
if any(
|
|
754
|
+
call["function"]["name"] in request.source_reader_names
|
|
755
|
+
for partition in request.summary_partition.partitions
|
|
756
|
+
for call in raw[partition.assistant_ref].get("tool_calls", ())
|
|
757
|
+
) or (
|
|
758
|
+
request.fresh_text_fragment_policy is not None
|
|
759
|
+
and any(
|
|
760
|
+
ref in manifest.get("source_captures", {})
|
|
761
|
+
for partition in request.summary_partition.partitions
|
|
762
|
+
for ref in manifest["batches"][partition.assistant_ref]["receipt_refs"]
|
|
763
|
+
)
|
|
764
|
+
):
|
|
765
|
+
# A validated quote consumes an original ref or advances a
|
|
766
|
+
# captured text cursor. Both are finite; every request still
|
|
767
|
+
# consumes the unchanged Run model budget.
|
|
768
|
+
chunk_limit = max(chunk_limit, len(manifest["dropped"]) + sum(
|
|
769
|
+
capture["total_chars"]
|
|
770
|
+
for capture in manifest.get("source_captures", {}).values()
|
|
771
|
+
))
|
|
772
|
+
if request.chunk_index < 1 or request.chunk_index >= chunk_limit:
|
|
773
|
+
raise ContextRuntimeError("compaction_chunk_limit")
|
|
774
|
+
partition_state = request.summary_partition
|
|
775
|
+
if partition_state is None:
|
|
776
|
+
projected, counted, remaining = self.planner._next_chunk(
|
|
777
|
+
request.remaining_history_entries,
|
|
778
|
+
summary_text,
|
|
779
|
+
request.summary_instructions,
|
|
780
|
+
request.profile,
|
|
781
|
+
dict(zip(_refs(current_messages), current_messages)),
|
|
782
|
+
)
|
|
783
|
+
else:
|
|
784
|
+
manifest, source_messages = source_manifest(
|
|
785
|
+
current_messages, request.old_messages, request.retained_message_refs,
|
|
786
|
+
capture_reader_names=request.source_capture_reader_names,
|
|
787
|
+
fresh_tool_observation_policy=request.fresh_tool_observation_policy,
|
|
788
|
+
fresh_tool_message_refs=request.fresh_tool_message_refs,
|
|
789
|
+
fresh_text_fragment_policy=request.fresh_text_fragment_policy,
|
|
790
|
+
fresh_text_excluded_tool_names=request.source_reader_names,
|
|
791
|
+
)
|
|
792
|
+
projected, counted, remaining, partition_state = self.planner._next_covered_chunk(
|
|
793
|
+
request.remaining_history_entries,
|
|
794
|
+
summary_text,
|
|
795
|
+
request.summary_instructions,
|
|
796
|
+
request.profile,
|
|
797
|
+
source_messages,
|
|
798
|
+
partition_state,
|
|
799
|
+
manifest,
|
|
800
|
+
request.chunk_index + 1,
|
|
801
|
+
)
|
|
802
|
+
full_reader_quote = _full_reader_quote(projected, request.remaining_history_entries)
|
|
803
|
+
output_cap = self.planner._summary_output_cap(
|
|
804
|
+
counted, request.profile, full_reader_quote=full_reader_quote
|
|
805
|
+
)
|
|
806
|
+
next_request = CompactionRequest.model_validate(
|
|
807
|
+
{
|
|
808
|
+
**request.model_dump(mode="json"),
|
|
809
|
+
"summary_messages": projected,
|
|
810
|
+
"summary_counted_input_tokens": counted,
|
|
811
|
+
"remaining_history_entries": remaining,
|
|
812
|
+
"chunk_index": request.chunk_index + 1,
|
|
813
|
+
"summary_partition": partition_state,
|
|
814
|
+
"full_reader_quote": full_reader_quote,
|
|
815
|
+
"summary_output_tokens": output_cap,
|
|
816
|
+
"summary_fragments": (),
|
|
817
|
+
"summary_continuations": 0,
|
|
818
|
+
}
|
|
819
|
+
)
|
|
820
|
+
if next_request.fresh_tool_observation_policy is not None:
|
|
821
|
+
# Verify queued source before its next dispatch, not only after
|
|
822
|
+
# the provider responds. Rehashed, shortened remaining entries
|
|
823
|
+
# must never become an authorized fresh observation request.
|
|
824
|
+
self._validate_source(
|
|
825
|
+
next_request, current_revision, current_continuity, current_messages
|
|
826
|
+
)
|
|
827
|
+
return next_request
|
|
828
|
+
|
|
829
|
+
def _is_partition_quote(self, message):
|
|
830
|
+
if message.get("kind") == "summary_batch_fragment":
|
|
831
|
+
return True
|
|
832
|
+
content = message.get("content")
|
|
833
|
+
text = content[0].get("text") if isinstance(content, list) and content else content
|
|
834
|
+
try:
|
|
835
|
+
body = json.loads(text)
|
|
836
|
+
except (ValueError, TypeError):
|
|
837
|
+
return False
|
|
838
|
+
# Only the host's outer quote envelope; never scan nested tool text.
|
|
839
|
+
return isinstance(body, dict) and body.get("fragment") is not None
|
|
840
|
+
|
|
841
|
+
def _base_summary_messages(self, request):
|
|
842
|
+
return (
|
|
843
|
+
request.summary_messages[: -2 * request.summary_continuations]
|
|
844
|
+
if request.summary_continuations
|
|
845
|
+
else request.summary_messages
|
|
846
|
+
)
|
|
847
|
+
|
|
848
|
+
def _acknowledge_partition(self, request, messages):
|
|
849
|
+
state = request.summary_partition
|
|
850
|
+
if state is None or state.pending is None:
|
|
851
|
+
return request
|
|
852
|
+
manifest, raw = source_manifest(
|
|
853
|
+
messages, request.old_messages, request.retained_message_refs,
|
|
854
|
+
capture_reader_names=request.source_capture_reader_names,
|
|
855
|
+
fresh_tool_observation_policy=request.fresh_tool_observation_policy,
|
|
856
|
+
fresh_tool_message_refs=request.fresh_tool_message_refs,
|
|
857
|
+
fresh_text_fragment_policy=request.fresh_text_fragment_policy,
|
|
858
|
+
fresh_text_excluded_tool_names=request.source_reader_names,
|
|
859
|
+
)
|
|
860
|
+
state = acknowledge(
|
|
861
|
+
state,
|
|
862
|
+
manifest,
|
|
863
|
+
raw,
|
|
864
|
+
self._base_summary_messages(request),
|
|
865
|
+
request.chunk_index,
|
|
866
|
+
profile=request.profile if self.planner.tool_media_projection_version else None,
|
|
867
|
+
)
|
|
868
|
+
return request.model_copy(update={"summary_partition": state})
|
|
869
|
+
|
|
870
|
+
def _validate_source(
|
|
871
|
+
self,
|
|
872
|
+
request: CompactionRequest,
|
|
873
|
+
current_revision: int,
|
|
874
|
+
current_continuity: ExecutionContinuityState,
|
|
875
|
+
current_messages: Messages,
|
|
876
|
+
) -> None:
|
|
877
|
+
if current_continuity != request.continuity:
|
|
878
|
+
raise ContextRuntimeError("context_continuity_changed")
|
|
879
|
+
if (
|
|
880
|
+
type(current_revision) is not int
|
|
881
|
+
or current_revision < request.source_revision
|
|
882
|
+
or source_context_digest(current_messages) != request.source_context_digest
|
|
883
|
+
):
|
|
884
|
+
raise ContextRuntimeError("context_source_changed")
|
|
885
|
+
if request.tool_media_projection_version != self.planner.tool_media_projection_version:
|
|
886
|
+
raise ContextRuntimeError("context_media_projection_changed")
|
|
887
|
+
if request.tokenizer_id != self.planner.tokenizer_id:
|
|
888
|
+
raise ContextRuntimeError("context_tokenizer_changed")
|
|
889
|
+
if (request.summary_budget_mode or "strict") != self.planner.summary_budget_mode:
|
|
890
|
+
raise ContextRuntimeError("context_summary_policy_changed")
|
|
891
|
+
if request.summary_completion_policy != self.planner.summary_completion_policy:
|
|
892
|
+
raise ContextRuntimeError("context_summary_completion_policy_changed")
|
|
893
|
+
if request.fresh_tool_observation_policy is not None and (
|
|
894
|
+
request.summary_partition is None
|
|
895
|
+
or request.summary_partition_version != "quoted-history-coverage/v1"
|
|
896
|
+
):
|
|
897
|
+
raise ContextRuntimeError("compaction_partition_state_missing")
|
|
898
|
+
if (
|
|
899
|
+
request.source_reader_names
|
|
900
|
+
or request.full_reader_quote
|
|
901
|
+
or any(_complete_source_entry(e) for e in request.remaining_history_entries)
|
|
902
|
+
) and request.reader_summary_policy_version != READER_SUMMARY_POLICY_VERSION:
|
|
903
|
+
raise ContextRuntimeError("context_reader_policy_changed")
|
|
904
|
+
if request.summary_partition is None:
|
|
905
|
+
if any(
|
|
906
|
+
self._is_partition_quote(message)
|
|
907
|
+
for message in self._base_summary_messages(request)
|
|
908
|
+
):
|
|
909
|
+
raise ContextRuntimeError("compaction_partition_state_missing")
|
|
910
|
+
else:
|
|
911
|
+
manifest, raw = source_manifest(
|
|
912
|
+
current_messages, request.old_messages, request.retained_message_refs,
|
|
913
|
+
capture_reader_names=request.source_capture_reader_names,
|
|
914
|
+
fresh_tool_observation_policy=request.fresh_tool_observation_policy,
|
|
915
|
+
fresh_tool_message_refs=request.fresh_tool_message_refs,
|
|
916
|
+
fresh_text_fragment_policy=request.fresh_text_fragment_policy,
|
|
917
|
+
fresh_text_excluded_tool_names=request.source_reader_names,
|
|
918
|
+
)
|
|
919
|
+
state = request.summary_partition
|
|
920
|
+
validate_coverage(
|
|
921
|
+
state,
|
|
922
|
+
manifest,
|
|
923
|
+
messages=self._base_summary_messages(request) if state.pending else None,
|
|
924
|
+
chunk_index=request.chunk_index,
|
|
925
|
+
raw=raw,
|
|
926
|
+
profile=request.profile if self.planner.tool_media_projection_version else None,
|
|
927
|
+
)
|
|
928
|
+
if state.pending is None:
|
|
929
|
+
require_complete(state, manifest)
|
|
930
|
+
|
|
931
|
+
def _validate_summary(self, request: CompactionRequest, summary_text: str) -> None:
|
|
932
|
+
if not isinstance(summary_text, str) or not summary_text.strip():
|
|
933
|
+
raise ContextRuntimeError("context_summary_empty")
|
|
934
|
+
# Exact counters retain their strict summary-size contract. A declared
|
|
935
|
+
# host estimate is a reduction target, not provider output usage: the
|
|
936
|
+
# same provider-limited response can exceed that estimate slightly.
|
|
937
|
+
# Transient text is bounded here; continuation and sealing separately
|
|
938
|
+
# admit the complete projected request against the original window.
|
|
939
|
+
limit = (
|
|
940
|
+
request.budget.input_capacity
|
|
941
|
+
if request.summary_budget_mode == "context_bounded_estimate"
|
|
942
|
+
else request.summary_max_tokens
|
|
943
|
+
)
|
|
944
|
+
if self.planner._count(summary_text) > limit:
|
|
945
|
+
raise ContextRuntimeError("context_summary_budget_exceeded")
|
|
946
|
+
|
|
947
|
+
def seal(
|
|
948
|
+
self,
|
|
949
|
+
request: CompactionRequest,
|
|
950
|
+
summary_text: str,
|
|
951
|
+
*,
|
|
952
|
+
current_revision: int,
|
|
953
|
+
current_continuity: ExecutionContinuityState,
|
|
954
|
+
current_messages: Messages,
|
|
955
|
+
) -> CompactionResult:
|
|
956
|
+
self._validate_source(request, current_revision, current_continuity, current_messages)
|
|
957
|
+
self._validate_summary(request, summary_text)
|
|
958
|
+
if request.remaining_history_entries:
|
|
959
|
+
raise ContextRuntimeError("compaction_chunks_incomplete")
|
|
960
|
+
request = self._acknowledge_partition(request, current_messages)
|
|
961
|
+
if request.summary_partition is not None:
|
|
962
|
+
manifest, _ = source_manifest(
|
|
963
|
+
current_messages, request.old_messages, request.retained_message_refs,
|
|
964
|
+
capture_reader_names=request.source_capture_reader_names,
|
|
965
|
+
fresh_tool_observation_policy=request.fresh_tool_observation_policy,
|
|
966
|
+
fresh_tool_message_refs=request.fresh_tool_message_refs,
|
|
967
|
+
fresh_text_fragment_policy=request.fresh_text_fragment_policy,
|
|
968
|
+
fresh_text_excluded_tool_names=request.source_reader_names,
|
|
969
|
+
)
|
|
970
|
+
require_complete(request.summary_partition, manifest)
|
|
971
|
+
return self._seal_projection(request, summary_text, current_continuity, current_messages)
|
|
972
|
+
|
|
973
|
+
def _seal_projection(self, request, summary_text, current_continuity, current_messages):
|
|
974
|
+
return seal_compaction_projection(
|
|
975
|
+
self.planner, request, summary_text, current_continuity, current_messages
|
|
976
|
+
)
|