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
ksadk/sessions/in_memory.py
CHANGED
|
@@ -3,10 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import bisect
|
|
5
5
|
import copy
|
|
6
|
+
import json
|
|
6
7
|
import time
|
|
7
|
-
from typing import AsyncIterator, Optional
|
|
8
|
+
from typing import Any, AsyncIterator, Literal, Optional
|
|
8
9
|
|
|
9
10
|
from ksadk.ids import new_session_id
|
|
11
|
+
from ksadk.sessions.errors import HistoryProjectionBudgetExceeded
|
|
12
|
+
from ksadk.sessions._checkpoint_resume_audit import CheckpointResumeAudit
|
|
10
13
|
from ksadk.sessions.base import (
|
|
11
14
|
CANONICAL_EVENT_STORAGE_CAPABILITIES,
|
|
12
15
|
BaseSessionService,
|
|
@@ -15,9 +18,14 @@ from ksadk.sessions.base import (
|
|
|
15
18
|
SessionEvent,
|
|
16
19
|
SessionEventQuery,
|
|
17
20
|
SessionState,
|
|
21
|
+
ToolReceiptClaim,
|
|
22
|
+
checkpoint_creation_identity,
|
|
23
|
+
checkpoint_resume_identity,
|
|
18
24
|
generate_id,
|
|
19
25
|
)
|
|
20
26
|
|
|
27
|
+
from ksadk.sessions._in_memory_query import _InMemoryQueryMixin
|
|
28
|
+
|
|
21
29
|
|
|
22
30
|
class _CheckpointSnapshotView:
|
|
23
31
|
"""Compatibility view over task-scoped checkpoint snapshots."""
|
|
@@ -30,7 +38,7 @@ class _CheckpointSnapshotView:
|
|
|
30
38
|
return self._snapshots.get(task) if task is not None else None
|
|
31
39
|
|
|
32
40
|
|
|
33
|
-
class InMemorySessionService(BaseSessionService):
|
|
41
|
+
class InMemorySessionService(_InMemoryQueryMixin, BaseSessionService):
|
|
34
42
|
storage_capabilities = CANONICAL_EVENT_STORAGE_CAPABILITIES
|
|
35
43
|
|
|
36
44
|
def __init__(self):
|
|
@@ -38,6 +46,7 @@ class InMemorySessionService(BaseSessionService):
|
|
|
38
46
|
self._events_by_id: dict[str, SessionEvent] = {}
|
|
39
47
|
self._events_by_invocation: dict[tuple[str, str], list[SessionEvent]] = {}
|
|
40
48
|
self._states: dict[tuple[str, str, str, str], SessionState] = {}
|
|
49
|
+
self._tool_receipts: dict[tuple[str, str], ToolReceiptClaim] = {}
|
|
41
50
|
self._event_order: list[tuple[float, str, int, str, int, SessionEvent]] = []
|
|
42
51
|
self._event_generation = 0
|
|
43
52
|
self._checkpoint_snapshot_by_task: dict[asyncio.Task[object], int] = {}
|
|
@@ -76,14 +85,149 @@ class InMemorySessionService(BaseSessionService):
|
|
|
76
85
|
session = self._sessions.get(session_id)
|
|
77
86
|
return copy.deepcopy(session) if session else None
|
|
78
87
|
|
|
88
|
+
async def get_session_event_ids(self, session_id: str) -> set[str]:
|
|
89
|
+
"""Recovery membership check without copying event payloads."""
|
|
90
|
+
async with self._lock:
|
|
91
|
+
session = self._sessions.get(session_id)
|
|
92
|
+
return {event.id for event in session.events} if session else set()
|
|
93
|
+
|
|
94
|
+
async def align_session_created_at(self, session_id: str, created_at: float) -> None:
|
|
95
|
+
"""Keep a clean recovery mirror on the durable session incarnation."""
|
|
96
|
+
async with self._lock:
|
|
97
|
+
session = self._sessions.get(session_id)
|
|
98
|
+
if session is not None:
|
|
99
|
+
session.created_at = created_at
|
|
100
|
+
|
|
101
|
+
async def get_adk_session_snapshot(
|
|
102
|
+
self, session_id: str, expected_session: Session | None = None
|
|
103
|
+
) -> Optional[Session]:
|
|
104
|
+
async with self._lock:
|
|
105
|
+
session = self._sessions.get(session_id)
|
|
106
|
+
if expected_session is not None and (
|
|
107
|
+
session is None or session.agent_id != expected_session.agent_id
|
|
108
|
+
or session.user_id != expected_session.user_id
|
|
109
|
+
or session.created_at != expected_session.created_at
|
|
110
|
+
):
|
|
111
|
+
from ksadk.sessions.errors import HistoryReloadRequired
|
|
112
|
+
|
|
113
|
+
raise HistoryReloadRequired("Session changed during legacy read")
|
|
114
|
+
return copy.deepcopy(session) if session else None
|
|
115
|
+
|
|
116
|
+
async def get_event_by_id_if_session_matches(
|
|
117
|
+
self, session_id: str, event_id: str, expected_session: Session
|
|
118
|
+
) -> Optional[SessionEvent]:
|
|
119
|
+
async with self._lock:
|
|
120
|
+
session = self._sessions.get(session_id)
|
|
121
|
+
if (session is None or session.agent_id != expected_session.agent_id
|
|
122
|
+
or session.user_id != expected_session.user_id
|
|
123
|
+
or session.created_at != expected_session.created_at):
|
|
124
|
+
from ksadk.sessions.errors import HistoryReloadRequired
|
|
125
|
+
|
|
126
|
+
raise HistoryReloadRequired("Session changed during legacy import")
|
|
127
|
+
event = self._events_by_id.get(event_id)
|
|
128
|
+
return copy.deepcopy(event) if event is not None and event.session_id == session_id else None
|
|
129
|
+
|
|
79
130
|
async def get_session_metadata(self, session_id: str) -> Optional[Session]:
|
|
80
131
|
async with self._lock:
|
|
81
132
|
session = self._sessions.get(session_id)
|
|
82
133
|
if session is None:
|
|
83
134
|
return None
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
135
|
+
return self._session_metadata(session)
|
|
136
|
+
|
|
137
|
+
async def get_session_header(self, session_id: str) -> Optional[Session]:
|
|
138
|
+
async with self._lock:
|
|
139
|
+
session = self._sessions.get(session_id)
|
|
140
|
+
if session is None:
|
|
141
|
+
return None
|
|
142
|
+
return Session(
|
|
143
|
+
id=session.id, agent_id=session.agent_id, user_id=session.user_id,
|
|
144
|
+
created_at=session.created_at, updated_at=session.updated_at,
|
|
145
|
+
version=session.version,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
async def ensure_session_header(
|
|
149
|
+
self, agent_id: str, user_id: str, session_id: str
|
|
150
|
+
) -> Session:
|
|
151
|
+
async with self._lock:
|
|
152
|
+
session = self._sessions.get(session_id)
|
|
153
|
+
if session is None:
|
|
154
|
+
session = Session(id=session_id, agent_id=agent_id, user_id=user_id)
|
|
155
|
+
self._sessions[session_id] = session
|
|
156
|
+
self._states[self._state_key("session", agent_id, user_id, session_id)] = (
|
|
157
|
+
SessionState(scope="session", agent_id=agent_id,
|
|
158
|
+
user_id=user_id, session_id=session_id)
|
|
159
|
+
)
|
|
160
|
+
return Session(
|
|
161
|
+
id=session.id, agent_id=session.agent_id, user_id=session.user_id,
|
|
162
|
+
created_at=session.created_at, updated_at=session.updated_at,
|
|
163
|
+
version=session.version,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
async def get_session_summary_events(self, session_id: str) -> list[SessionEvent]:
|
|
167
|
+
"""Copy prompt endpoints and the exact active/latest invocation fact."""
|
|
168
|
+
from ksadk.conversations.run_status import RUN_STATUS_ACTIVE, RUN_STATUS_TERMINAL
|
|
169
|
+
|
|
170
|
+
canonical_status = {
|
|
171
|
+
"run.started": "in_progress", "run.progress": "in_progress",
|
|
172
|
+
"run.interrupted": "interrupted", "run.completed": "completed",
|
|
173
|
+
"run.failed": "failed", "run.canceled": "cancelled",
|
|
174
|
+
}
|
|
175
|
+
lifecycle_types = {"run_status", *canonical_status}
|
|
176
|
+
|
|
177
|
+
def run_id(event: SessionEvent) -> str:
|
|
178
|
+
metadata = event.metadata or {}
|
|
179
|
+
return str(metadata.get("run_id") or metadata.get("invocation_id")
|
|
180
|
+
or event.invocation_id or "").strip()
|
|
181
|
+
|
|
182
|
+
def status(event: SessionEvent) -> str:
|
|
183
|
+
metadata = event.metadata or {}
|
|
184
|
+
content = event.content or {}
|
|
185
|
+
payload = content.get("payload")
|
|
186
|
+
return str(metadata.get("status") or metadata.get("run_status")
|
|
187
|
+
or content.get("status")
|
|
188
|
+
or (payload.get("status") if isinstance(payload, dict) else "")
|
|
189
|
+
or canonical_status.get(event.event_type, "")).strip()
|
|
190
|
+
|
|
191
|
+
async with self._lock:
|
|
192
|
+
session = self._sessions.get(session_id)
|
|
193
|
+
if session is None:
|
|
194
|
+
return []
|
|
195
|
+
events = session.events
|
|
196
|
+
first = next((e for e in events if e.event_type == "user_message"), None)
|
|
197
|
+
last = next((e for e in reversed(events) if e.event_type == "user_message"), None)
|
|
198
|
+
latest: dict[str, SessionEvent] = {}
|
|
199
|
+
for event in reversed(events):
|
|
200
|
+
if event.event_type in lifecycle_types:
|
|
201
|
+
latest.setdefault(run_id(event), event)
|
|
202
|
+
chosen = next((e for e in latest.values() if status(e) in RUN_STATUS_ACTIVE), None)
|
|
203
|
+
if chosen is None:
|
|
204
|
+
chosen = next((e for e in latest.values()
|
|
205
|
+
if status(e) not in RUN_STATUS_TERMINAL), None)
|
|
206
|
+
if chosen is None:
|
|
207
|
+
chosen = next(iter(latest.values()), None)
|
|
208
|
+
selected = {e.id: copy.deepcopy(e) for e in (first, last) if e is not None}
|
|
209
|
+
if chosen is not None:
|
|
210
|
+
chosen_run_id = run_id(chosen)
|
|
211
|
+
classification = next((e.metadata for e in reversed(events)
|
|
212
|
+
if e.event_type in lifecycle_types
|
|
213
|
+
and run_id(e) == chosen_run_id
|
|
214
|
+
and ((e.metadata or {}).get("run_mode") not in (None, "unknown")
|
|
215
|
+
or (e.metadata or {}).get("run_trigger") not in (None, "unknown"))), {})
|
|
216
|
+
selected[chosen.id] = SessionEvent(
|
|
217
|
+
id=chosen.id, session_id=session_id, author=chosen.author,
|
|
218
|
+
event_type=chosen.event_type, timestamp=chosen.timestamp,
|
|
219
|
+
seq_id=chosen.seq_id, invocation_id=chosen_run_id,
|
|
220
|
+
content={"status": status(chosen)},
|
|
221
|
+
metadata={"run_id": chosen_run_id, "status": status(chosen),
|
|
222
|
+
"run_mode": classification.get("run_mode", "unknown"),
|
|
223
|
+
"run_trigger": classification.get("run_trigger", "unknown")},
|
|
224
|
+
)
|
|
225
|
+
return sorted(selected.values(), key=lambda e: e.seq_id)
|
|
226
|
+
|
|
227
|
+
async def get_max_seq_id(self, session_id: str) -> int:
|
|
228
|
+
async with self._lock:
|
|
229
|
+
session = self._sessions.get(session_id)
|
|
230
|
+
return int(session.events[-1].seq_id) if session and session.events else 0
|
|
87
231
|
|
|
88
232
|
async def list_sessions(
|
|
89
233
|
self,
|
|
@@ -94,7 +238,7 @@ class InMemorySessionService(BaseSessionService):
|
|
|
94
238
|
) -> list[Session]:
|
|
95
239
|
async with self._lock:
|
|
96
240
|
sessions = [
|
|
97
|
-
|
|
241
|
+
self._session_metadata(session)
|
|
98
242
|
for session in self._sessions.values()
|
|
99
243
|
if session.agent_id == agent_id and (user_id is None or session.user_id == user_id)
|
|
100
244
|
]
|
|
@@ -134,9 +278,15 @@ class InMemorySessionService(BaseSessionService):
|
|
|
134
278
|
async def delete_session(self, session_id: str) -> bool:
|
|
135
279
|
async with self._checkpoint_scan_lock:
|
|
136
280
|
async with self._lock:
|
|
137
|
-
session = self._sessions.
|
|
281
|
+
session = self._sessions.get(session_id)
|
|
138
282
|
if not session:
|
|
139
283
|
return False
|
|
284
|
+
if any(
|
|
285
|
+
key[0] == session_id and claim.state == "unknown"
|
|
286
|
+
for key, claim in self._tool_receipts.items()
|
|
287
|
+
):
|
|
288
|
+
raise ValueError("session has durable tool receipt claims")
|
|
289
|
+
self._sessions.pop(session_id, None)
|
|
140
290
|
for event in session.events:
|
|
141
291
|
self._events_by_id.pop(event.id, None)
|
|
142
292
|
if event.invocation_id is not None:
|
|
@@ -148,6 +298,8 @@ class InMemorySessionService(BaseSessionService):
|
|
|
148
298
|
),
|
|
149
299
|
None,
|
|
150
300
|
)
|
|
301
|
+
for key in [key for key in self._tool_receipts if key[0] == session_id]:
|
|
302
|
+
self._tool_receipts.pop(key, None)
|
|
151
303
|
return True
|
|
152
304
|
|
|
153
305
|
async def update_session_metadata(
|
|
@@ -175,13 +327,31 @@ class InMemorySessionService(BaseSessionService):
|
|
|
175
327
|
if last_prompt is not None:
|
|
176
328
|
session.last_prompt = last_prompt
|
|
177
329
|
session.updated_at = time.time()
|
|
178
|
-
return
|
|
330
|
+
return self._session_metadata(session)
|
|
179
331
|
|
|
180
332
|
async def append_event(self, session_id: str, event: SessionEvent) -> SessionEvent:
|
|
333
|
+
return await self._append_event_with_expected(session_id, event, None)
|
|
334
|
+
|
|
335
|
+
async def append_event_if_session_matches(
|
|
336
|
+
self, session_id: str, event: SessionEvent, expected_session: Session
|
|
337
|
+
) -> SessionEvent:
|
|
338
|
+
return await self._append_event_with_expected(session_id, event, expected_session)
|
|
339
|
+
|
|
340
|
+
async def _append_event_with_expected(
|
|
341
|
+
self, session_id: str, event: SessionEvent, expected_session: Session | None
|
|
342
|
+
) -> SessionEvent:
|
|
181
343
|
async with self._lock:
|
|
182
344
|
session = self._sessions.get(session_id)
|
|
183
345
|
if not session:
|
|
184
346
|
raise ValueError(f"Session {session_id} not found")
|
|
347
|
+
if expected_session is not None and (
|
|
348
|
+
session.agent_id != expected_session.agent_id
|
|
349
|
+
or session.user_id != expected_session.user_id
|
|
350
|
+
or session.created_at != expected_session.created_at
|
|
351
|
+
):
|
|
352
|
+
from ksadk.sessions.errors import HistoryReloadRequired
|
|
353
|
+
|
|
354
|
+
raise HistoryReloadRequired("Session changed during legacy import")
|
|
185
355
|
|
|
186
356
|
# Match the durable Local/Postgres physical primary-key contract.
|
|
187
357
|
# Canonical RuntimeEvent storage relies on a deterministic
|
|
@@ -238,6 +408,97 @@ class InMemorySessionService(BaseSessionService):
|
|
|
238
408
|
|
|
239
409
|
return copy.deepcopy(stored)
|
|
240
410
|
|
|
411
|
+
async def claim_tool_receipt(
|
|
412
|
+
self,
|
|
413
|
+
session_id: str,
|
|
414
|
+
*,
|
|
415
|
+
idempotency_key: str,
|
|
416
|
+
tool_name: str,
|
|
417
|
+
arguments_digest: str,
|
|
418
|
+
claim_id: str,
|
|
419
|
+
) -> ToolReceiptClaim:
|
|
420
|
+
async with self._lock:
|
|
421
|
+
if session_id not in self._sessions:
|
|
422
|
+
raise ValueError(f"Session {session_id} not found")
|
|
423
|
+
key = (session_id, idempotency_key)
|
|
424
|
+
existing = self._tool_receipts.get(key)
|
|
425
|
+
if existing is not None:
|
|
426
|
+
if (
|
|
427
|
+
existing.tool_name != tool_name
|
|
428
|
+
or existing.arguments_digest != arguments_digest
|
|
429
|
+
):
|
|
430
|
+
raise ValueError("tool receipt idempotency key conflict")
|
|
431
|
+
if existing.state not in {"unknown", "completed", "failed"}:
|
|
432
|
+
raise ValueError("tool receipt state is invalid")
|
|
433
|
+
return ToolReceiptClaim(
|
|
434
|
+
session_id=existing.session_id,
|
|
435
|
+
idempotency_key=existing.idempotency_key,
|
|
436
|
+
tool_name=existing.tool_name,
|
|
437
|
+
arguments_digest=existing.arguments_digest,
|
|
438
|
+
state=existing.state,
|
|
439
|
+
claim_id=existing.claim_id,
|
|
440
|
+
output=copy.deepcopy(existing.output),
|
|
441
|
+
acquired=False,
|
|
442
|
+
)
|
|
443
|
+
claim = ToolReceiptClaim(
|
|
444
|
+
session_id=session_id,
|
|
445
|
+
idempotency_key=idempotency_key,
|
|
446
|
+
tool_name=tool_name,
|
|
447
|
+
arguments_digest=arguments_digest,
|
|
448
|
+
state="unknown",
|
|
449
|
+
claim_id=claim_id,
|
|
450
|
+
acquired=True,
|
|
451
|
+
)
|
|
452
|
+
self._tool_receipts[key] = claim
|
|
453
|
+
return copy.deepcopy(claim)
|
|
454
|
+
|
|
455
|
+
async def settle_tool_receipt(
|
|
456
|
+
self,
|
|
457
|
+
session_id: str,
|
|
458
|
+
*,
|
|
459
|
+
idempotency_key: str,
|
|
460
|
+
tool_name: str,
|
|
461
|
+
arguments_digest: str,
|
|
462
|
+
claim_id: str,
|
|
463
|
+
state: Literal["completed", "failed"],
|
|
464
|
+
output: Any,
|
|
465
|
+
) -> ToolReceiptClaim:
|
|
466
|
+
async with self._lock:
|
|
467
|
+
key = (session_id, idempotency_key)
|
|
468
|
+
existing = self._tool_receipts.get(key)
|
|
469
|
+
if existing is None:
|
|
470
|
+
raise ValueError("tool receipt claim not found")
|
|
471
|
+
if (
|
|
472
|
+
existing.tool_name != tool_name
|
|
473
|
+
or existing.arguments_digest != arguments_digest
|
|
474
|
+
):
|
|
475
|
+
raise ValueError("tool receipt idempotency key conflict")
|
|
476
|
+
if existing.claim_id != claim_id:
|
|
477
|
+
return copy.deepcopy(existing)
|
|
478
|
+
if existing.state != "unknown":
|
|
479
|
+
if existing.state != state or existing.output != output:
|
|
480
|
+
raise ValueError("tool receipt terminal result conflict")
|
|
481
|
+
return copy.deepcopy(existing)
|
|
482
|
+
settled = ToolReceiptClaim(
|
|
483
|
+
session_id=session_id,
|
|
484
|
+
idempotency_key=idempotency_key,
|
|
485
|
+
tool_name=tool_name,
|
|
486
|
+
arguments_digest=arguments_digest,
|
|
487
|
+
state=state,
|
|
488
|
+
claim_id=claim_id,
|
|
489
|
+
output=copy.deepcopy(output),
|
|
490
|
+
acquired=False,
|
|
491
|
+
)
|
|
492
|
+
self._tool_receipts[key] = settled
|
|
493
|
+
return copy.deepcopy(settled)
|
|
494
|
+
|
|
495
|
+
async def get_tool_receipt_claim(
|
|
496
|
+
self, session_id: str, *, idempotency_key: str
|
|
497
|
+
) -> ToolReceiptClaim | None:
|
|
498
|
+
async with self._lock:
|
|
499
|
+
claim = self._tool_receipts.get((session_id, idempotency_key))
|
|
500
|
+
return copy.deepcopy(claim) if claim is not None else None
|
|
501
|
+
|
|
241
502
|
async def get_event_by_id(self, session_id: str, event_id: str) -> Optional[SessionEvent]:
|
|
242
503
|
async with self._lock:
|
|
243
504
|
event = self._events_by_id.get(event_id)
|
|
@@ -293,6 +554,8 @@ class InMemorySessionService(BaseSessionService):
|
|
|
293
554
|
session = self._sessions.get(session_id)
|
|
294
555
|
if not session:
|
|
295
556
|
return 0
|
|
557
|
+
if after_seq_id is None and before_seq_id is None:
|
|
558
|
+
return len(session.events)
|
|
296
559
|
events = list(session.events)
|
|
297
560
|
if after_seq_id is not None:
|
|
298
561
|
events = [event for event in events if event.seq_id > after_seq_id]
|
|
@@ -308,11 +571,31 @@ class InMemorySessionService(BaseSessionService):
|
|
|
308
571
|
if session_id in self._sessions
|
|
309
572
|
]
|
|
310
573
|
|
|
574
|
+
async def get_session_ids_by_ids(
|
|
575
|
+
self, session_ids: list[str], agent_id: str | None = None,
|
|
576
|
+
) -> list[str]:
|
|
577
|
+
async with self._lock:
|
|
578
|
+
return [sid for sid in session_ids if (session := self._sessions.get(sid))
|
|
579
|
+
is not None and (agent_id is None or session.agent_id == agent_id)]
|
|
580
|
+
|
|
581
|
+
async def list_session_ids(
|
|
582
|
+
self, agent_id: str | None = None, user_id: str | None = None,
|
|
583
|
+
) -> list[str]:
|
|
584
|
+
async with self._lock:
|
|
585
|
+
return [sid for sid, session in self._sessions.items()
|
|
586
|
+
if (agent_id is None or session.agent_id == agent_id)
|
|
587
|
+
and (user_id is None or session.user_id == user_id)]
|
|
588
|
+
|
|
311
589
|
@staticmethod
|
|
312
590
|
def _session_metadata(session: Session) -> Session:
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
591
|
+
return Session(
|
|
592
|
+
id=session.id, agent_id=session.agent_id, user_id=session.user_id,
|
|
593
|
+
title=session.title, title_source=session.title_source,
|
|
594
|
+
summary=session.summary, first_prompt=session.first_prompt,
|
|
595
|
+
last_prompt=session.last_prompt, state=copy.deepcopy(session.state),
|
|
596
|
+
created_at=session.created_at, updated_at=session.updated_at,
|
|
597
|
+
version=session.version,
|
|
598
|
+
)
|
|
316
599
|
|
|
317
600
|
async def query_events(self, query: SessionEventQuery) -> list[SessionEvent]:
|
|
318
601
|
return await self._query_events(query, count_only=False)
|
|
@@ -320,91 +603,6 @@ class InMemorySessionService(BaseSessionService):
|
|
|
320
603
|
async def count_event_query(self, query: SessionEventQuery) -> int:
|
|
321
604
|
return int(await self._query_events(query, count_only=True))
|
|
322
605
|
|
|
323
|
-
async def _query_events(
|
|
324
|
-
self, query: SessionEventQuery, *, count_only: bool
|
|
325
|
-
) -> list[SessionEvent] | int:
|
|
326
|
-
async with self._lock:
|
|
327
|
-
selected_ids = (
|
|
328
|
-
list(dict.fromkeys(query.session_ids))
|
|
329
|
-
if query.session_ids is not None
|
|
330
|
-
else list(self._sessions)
|
|
331
|
-
)
|
|
332
|
-
allowed_types = set(query.event_types or [])
|
|
333
|
-
allowed_checkpoint_ids = set(query.checkpoint_ids or [])
|
|
334
|
-
events = [
|
|
335
|
-
event
|
|
336
|
-
for session_id in selected_ids
|
|
337
|
-
for session in [self._sessions.get(session_id)]
|
|
338
|
-
if session is not None
|
|
339
|
-
and (query.agent_id is None or session.agent_id == query.agent_id)
|
|
340
|
-
for event in session.events
|
|
341
|
-
if (query.after_seq_id is None or event.seq_id > query.after_seq_id)
|
|
342
|
-
and (query.before_seq_id is None or event.seq_id < query.before_seq_id)
|
|
343
|
-
and (not allowed_types or event.event_type in allowed_types)
|
|
344
|
-
and (query.invocation_id is None or event.invocation_id == query.invocation_id)
|
|
345
|
-
and (
|
|
346
|
-
query.run_id is None
|
|
347
|
-
or str((event.metadata or {}).get("run_id") or "") == query.run_id
|
|
348
|
-
or (
|
|
349
|
-
event.event_type == "continuation.created"
|
|
350
|
-
and str(
|
|
351
|
-
((event.content or {}).get("runtime_event") or {}).get(
|
|
352
|
-
"run_id", ""
|
|
353
|
-
)
|
|
354
|
-
or ""
|
|
355
|
-
)
|
|
356
|
-
== query.run_id
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
and (
|
|
360
|
-
query.checkpoint_id is None
|
|
361
|
-
or str((event.metadata or {}).get("checkpoint_id") or "")
|
|
362
|
-
== query.checkpoint_id
|
|
363
|
-
or (
|
|
364
|
-
event.event_type == "continuation.created"
|
|
365
|
-
and str(
|
|
366
|
-
((event.content or {}).get("runtime_event") or {}).get(
|
|
367
|
-
"continuation_id", ""
|
|
368
|
-
)
|
|
369
|
-
or ""
|
|
370
|
-
)
|
|
371
|
-
== query.checkpoint_id
|
|
372
|
-
)
|
|
373
|
-
)
|
|
374
|
-
and (
|
|
375
|
-
not allowed_checkpoint_ids
|
|
376
|
-
or str((event.metadata or {}).get("checkpoint_id") or "")
|
|
377
|
-
in allowed_checkpoint_ids
|
|
378
|
-
or (
|
|
379
|
-
event.event_type == "continuation.created"
|
|
380
|
-
and str(
|
|
381
|
-
((event.content or {}).get("runtime_event") or {}).get(
|
|
382
|
-
"continuation_id", ""
|
|
383
|
-
)
|
|
384
|
-
or ""
|
|
385
|
-
)
|
|
386
|
-
in allowed_checkpoint_ids
|
|
387
|
-
)
|
|
388
|
-
)
|
|
389
|
-
]
|
|
390
|
-
if count_only:
|
|
391
|
-
return len(events)
|
|
392
|
-
if query.order_by_seq:
|
|
393
|
-
events.sort(key=lambda event: (event.session_id, event.seq_id, event.id))
|
|
394
|
-
else:
|
|
395
|
-
events.sort(
|
|
396
|
-
key=lambda event: (
|
|
397
|
-
event.timestamp,
|
|
398
|
-
event.session_id,
|
|
399
|
-
event.seq_id,
|
|
400
|
-
event.id,
|
|
401
|
-
)
|
|
402
|
-
)
|
|
403
|
-
if query.from_start:
|
|
404
|
-
return copy.deepcopy(events[query.offset : query.offset + query.limit])
|
|
405
|
-
end = max(len(events) - query.offset, 0)
|
|
406
|
-
return copy.deepcopy(events[max(end - query.limit, 0) : end])
|
|
407
|
-
|
|
408
606
|
async def get_checkpoint_lookup_stats(
|
|
409
607
|
self, session_id: str, run_id: str, checkpoint_id: str
|
|
410
608
|
) -> dict[str, object]:
|
|
@@ -412,27 +610,33 @@ class InMemorySessionService(BaseSessionService):
|
|
|
412
610
|
session = self._sessions.get(session_id)
|
|
413
611
|
candidate = None
|
|
414
612
|
max_seq_id = 0
|
|
415
|
-
|
|
613
|
+
resume_audit = CheckpointResumeAudit()
|
|
416
614
|
last_resumed_at = None
|
|
417
615
|
for event in session.events if session else []:
|
|
418
616
|
metadata = event.metadata or {}
|
|
419
|
-
if str(metadata.get("run_id") or "") != run_id:
|
|
420
|
-
continue
|
|
421
617
|
if event.event_type == "run_checkpoint":
|
|
618
|
+
if str(metadata.get("run_id") or "") != run_id:
|
|
619
|
+
continue
|
|
422
620
|
max_seq_id = max(max_seq_id, int(event.seq_id or 0))
|
|
423
621
|
if str(metadata.get("checkpoint_id") or "") == checkpoint_id and (
|
|
424
622
|
candidate is None or event.seq_id > candidate.seq_id
|
|
425
623
|
):
|
|
426
624
|
candidate = copy.deepcopy(event)
|
|
427
|
-
elif event
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
625
|
+
elif (creation := checkpoint_creation_identity(event)) is not None:
|
|
626
|
+
if creation == (run_id, checkpoint_id):
|
|
627
|
+
max_seq_id = max(max_seq_id, int(event.seq_id or 0))
|
|
628
|
+
if candidate is None or event.seq_id > candidate.seq_id:
|
|
629
|
+
candidate = copy.deepcopy(event)
|
|
630
|
+
else:
|
|
631
|
+
identity = checkpoint_resume_identity(event)
|
|
632
|
+
if identity is None or identity[:2] != (run_id, checkpoint_id):
|
|
633
|
+
continue
|
|
634
|
+
resume_audit.record(event, identity)
|
|
635
|
+
last_resumed_at = resume_audit["last_resumed_at"]
|
|
432
636
|
return {
|
|
433
637
|
"candidate": candidate,
|
|
434
638
|
"max_seq_id": max_seq_id,
|
|
435
|
-
"resume_count": resume_count,
|
|
639
|
+
"resume_count": resume_audit["resume_count"],
|
|
436
640
|
"last_resumed_at": last_resumed_at,
|
|
437
641
|
}
|
|
438
642
|
|
|
@@ -509,13 +713,51 @@ class InMemorySessionService(BaseSessionService):
|
|
|
509
713
|
if task is not None:
|
|
510
714
|
self._checkpoint_snapshot_by_task.pop(task, None)
|
|
511
715
|
|
|
716
|
+
async def iter_resume_related_event_pages(
|
|
717
|
+
self, session_id: str, *, page_size: int = 256,
|
|
718
|
+
expected_session: Session | None = None,
|
|
719
|
+
) -> AsyncIterator[list[SessionEvent]]:
|
|
720
|
+
async with self._lock:
|
|
721
|
+
session = self._sessions.get(session_id)
|
|
722
|
+
if expected_session is not None:
|
|
723
|
+
from ksadk.sessions.errors import HistoryReloadRequired
|
|
724
|
+
|
|
725
|
+
if (session is None or session.agent_id != expected_session.agent_id
|
|
726
|
+
or session.user_id != expected_session.user_id
|
|
727
|
+
or session.created_at != expected_session.created_at):
|
|
728
|
+
raise HistoryReloadRequired("Checkpoint session changed during lookup")
|
|
729
|
+
events = session.events if session is not None else []
|
|
730
|
+
fixed_length = len(events)
|
|
731
|
+
index = 0
|
|
732
|
+
count = 0
|
|
733
|
+
size = 0
|
|
734
|
+
while index < fixed_length:
|
|
735
|
+
async with self._lock:
|
|
736
|
+
page: list[SessionEvent] = []
|
|
737
|
+
while index < fixed_length and len(page) < page_size:
|
|
738
|
+
event = events[index]
|
|
739
|
+
index += 1
|
|
740
|
+
if event.event_type not in {
|
|
741
|
+
"run_checkpoint", "run_resume", "runtime_resume", "continuation.created", "continuation.resumed"
|
|
742
|
+
}:
|
|
743
|
+
continue
|
|
744
|
+
count += 1
|
|
745
|
+
size += len(json.dumps(event.to_dict(), ensure_ascii=False).encode())
|
|
746
|
+
if count > 8192 or size > 16 * 1024 * 1024:
|
|
747
|
+
raise HistoryProjectionBudgetExceeded(
|
|
748
|
+
"Checkpoint lookup exceeds 8192 related events or 16 MiB"
|
|
749
|
+
)
|
|
750
|
+
page.append(copy.deepcopy(event))
|
|
751
|
+
if page:
|
|
752
|
+
yield page
|
|
753
|
+
|
|
512
754
|
async def get_checkpoint_stats(
|
|
513
755
|
self, keys: list[tuple[str, str, str]]
|
|
514
756
|
) -> dict[str, object]:
|
|
515
757
|
if len(keys) > 50:
|
|
516
758
|
raise ValueError("checkpoint stats batch cannot exceed 50 keys")
|
|
517
759
|
unique_keys = list(dict.fromkeys(keys))
|
|
518
|
-
audits = {key:
|
|
760
|
+
audits = {key: CheckpointResumeAudit() for key in unique_keys}
|
|
519
761
|
run_keys = {(session_id, run_id) for session_id, run_id, _ in unique_keys}
|
|
520
762
|
latest_seq_ids = {key: 0 for key in run_keys}
|
|
521
763
|
async with self._lock:
|
|
@@ -527,22 +769,29 @@ class InMemorySessionService(BaseSessionService):
|
|
|
527
769
|
if snapshot_generation is not None and generation > snapshot_generation:
|
|
528
770
|
continue
|
|
529
771
|
metadata = event.metadata or {}
|
|
530
|
-
|
|
772
|
+
identity = checkpoint_resume_identity(event)
|
|
773
|
+
creation = checkpoint_creation_identity(event)
|
|
774
|
+
run_id = str(metadata.get("run_id") or "") or (
|
|
775
|
+
identity[0]
|
|
776
|
+
if identity is not None
|
|
777
|
+
else (creation[0] if creation is not None else "")
|
|
778
|
+
)
|
|
531
779
|
run_key = (session_id, run_id)
|
|
532
780
|
if run_key not in run_keys:
|
|
533
781
|
continue
|
|
782
|
+
if creation is not None:
|
|
783
|
+
latest_seq_ids[(session_id, creation[0])] = max(
|
|
784
|
+
latest_seq_ids[(session_id, creation[0])], int(event.seq_id or 0)
|
|
785
|
+
)
|
|
534
786
|
if event.event_type == "run_checkpoint":
|
|
535
787
|
latest_seq_ids[run_key] = max(
|
|
536
788
|
latest_seq_ids[run_key], int(event.seq_id or 0)
|
|
537
789
|
)
|
|
538
|
-
elif
|
|
539
|
-
key = (session_id,
|
|
790
|
+
elif identity is not None:
|
|
791
|
+
key = (session_id, identity[0], identity[1])
|
|
540
792
|
if key in audits:
|
|
541
793
|
audit = audits[key]
|
|
542
|
-
audit
|
|
543
|
-
audit["last_resumed_at"] = max(
|
|
544
|
-
audit["last_resumed_at"] or event.timestamp, event.timestamp
|
|
545
|
-
)
|
|
794
|
+
audit.record(event, identity)
|
|
546
795
|
return {"audits": audits, "latest_seq_ids": latest_seq_ids}
|
|
547
796
|
|
|
548
797
|
async def get_events_for_agent(
|
|
@@ -601,6 +850,20 @@ class InMemorySessionService(BaseSessionService):
|
|
|
601
850
|
)
|
|
602
851
|
return copy.deepcopy(state) if state else None
|
|
603
852
|
|
|
853
|
+
async def mirror_state_snapshot(self, state: SessionState) -> None:
|
|
854
|
+
"""Replace a clean durable state mirror without replaying history."""
|
|
855
|
+
async with self._lock:
|
|
856
|
+
snapshot = copy.deepcopy(state)
|
|
857
|
+
key = self._state_key(
|
|
858
|
+
snapshot.scope, snapshot.agent_id, snapshot.user_id, snapshot.session_id,
|
|
859
|
+
)
|
|
860
|
+
if snapshot.scope == "session" and snapshot.session_id in self._sessions:
|
|
861
|
+
session = self._sessions[snapshot.session_id]
|
|
862
|
+
session.state = copy.deepcopy(snapshot.state)
|
|
863
|
+
session.version = snapshot.version
|
|
864
|
+
session.updated_at = snapshot.updated_at
|
|
865
|
+
self._states[key] = snapshot
|
|
866
|
+
|
|
604
867
|
async def update_state(
|
|
605
868
|
self,
|
|
606
869
|
*,
|