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,130 @@
|
|
|
1
|
+
"""Runtime-owned PostgreSQL event delivery, isolated from legacy consumers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
|
|
8
|
+
from sqlalchemy import text
|
|
9
|
+
|
|
10
|
+
from ksadk.a2a.task_event_outbox import (
|
|
11
|
+
A2ATaskEventBatch,
|
|
12
|
+
A2ATaskEventOutbox,
|
|
13
|
+
_batch_id,
|
|
14
|
+
_serialize_events,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OwnedPostgresA2ATaskEventOutbox(A2ATaskEventOutbox):
|
|
19
|
+
"""Replicas share their runtime's queue, never another workload's queue.
|
|
20
|
+
|
|
21
|
+
Separate tables are intentional: an older unscoped dispatcher must not
|
|
22
|
+
consume new owned batches during a rolling upgrade. Legacy rows are kept
|
|
23
|
+
untouched; their owner cannot safely be inferred from their event payload.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, engine, *, account_id: str, tenant_id: str, runtime_id: str):
|
|
27
|
+
identity = (account_id, tenant_id, runtime_id)
|
|
28
|
+
if any(not isinstance(value, str) or not value.strip() for value in identity):
|
|
29
|
+
raise ValueError("A2A_OUTBOX_OWNER_REQUIRED")
|
|
30
|
+
self._engine = engine
|
|
31
|
+
self._owner = hashlib.sha256(
|
|
32
|
+
json.dumps(identity, separators=(",", ":")).encode()
|
|
33
|
+
).hexdigest()
|
|
34
|
+
|
|
35
|
+
async def initialize(self):
|
|
36
|
+
async with self._engine.begin() as connection:
|
|
37
|
+
await connection.execute(text("""
|
|
38
|
+
CREATE TABLE IF NOT EXISTS ksadk_a2a_owned_task_event_outbox (
|
|
39
|
+
sequence BIGSERIAL PRIMARY KEY,
|
|
40
|
+
owner_key TEXT NOT NULL,
|
|
41
|
+
batch_id TEXT NOT NULL UNIQUE,
|
|
42
|
+
platform_task_id TEXT NOT NULL,
|
|
43
|
+
events_json TEXT NOT NULL,
|
|
44
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
45
|
+
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
46
|
+
last_error TEXT
|
|
47
|
+
)
|
|
48
|
+
"""))
|
|
49
|
+
await connection.execute(text("""
|
|
50
|
+
CREATE TABLE IF NOT EXISTS ksadk_a2a_owned_task_event_dead_letters (
|
|
51
|
+
sequence BIGINT NOT NULL,
|
|
52
|
+
owner_key TEXT NOT NULL,
|
|
53
|
+
batch_id TEXT PRIMARY KEY,
|
|
54
|
+
platform_task_id TEXT NOT NULL,
|
|
55
|
+
events_json TEXT NOT NULL,
|
|
56
|
+
created_at TIMESTAMPTZ NOT NULL,
|
|
57
|
+
attempt_count INTEGER NOT NULL,
|
|
58
|
+
last_error TEXT NOT NULL,
|
|
59
|
+
dead_lettered_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
60
|
+
)
|
|
61
|
+
"""))
|
|
62
|
+
await connection.execute(text("""
|
|
63
|
+
CREATE INDEX IF NOT EXISTS ix_ksadk_a2a_owned_outbox_owner_sequence
|
|
64
|
+
ON ksadk_a2a_owned_task_event_outbox(owner_key, sequence)
|
|
65
|
+
"""))
|
|
66
|
+
|
|
67
|
+
async def ensure_writable(self):
|
|
68
|
+
await self.initialize()
|
|
69
|
+
async with self._engine.begin() as connection:
|
|
70
|
+
await connection.execute(text(
|
|
71
|
+
"LOCK TABLE ksadk_a2a_owned_task_event_outbox IN ROW EXCLUSIVE MODE"
|
|
72
|
+
))
|
|
73
|
+
|
|
74
|
+
async def enqueue(self, *, platform_task_id, events):
|
|
75
|
+
payload = _serialize_events(events)
|
|
76
|
+
batch_id = _batch_id(self._owner + ":" + platform_task_id, payload)
|
|
77
|
+
async with self._engine.begin() as connection:
|
|
78
|
+
await connection.execute(text("""
|
|
79
|
+
INSERT INTO ksadk_a2a_owned_task_event_outbox(
|
|
80
|
+
owner_key, batch_id, platform_task_id, events_json
|
|
81
|
+
) VALUES (:owner, :batch, :task, :events)
|
|
82
|
+
ON CONFLICT(batch_id) DO NOTHING
|
|
83
|
+
"""), {"owner": self._owner, "batch": batch_id,
|
|
84
|
+
"task": platform_task_id, "events": payload})
|
|
85
|
+
return batch_id
|
|
86
|
+
|
|
87
|
+
async def pending(self, *, limit=100):
|
|
88
|
+
async with self._engine.connect() as connection:
|
|
89
|
+
result = await connection.execute(text("""
|
|
90
|
+
SELECT sequence, batch_id, platform_task_id, events_json, attempt_count
|
|
91
|
+
FROM ksadk_a2a_owned_task_event_outbox
|
|
92
|
+
WHERE owner_key = :owner ORDER BY sequence LIMIT :limit
|
|
93
|
+
"""), {"owner": self._owner, "limit": limit})
|
|
94
|
+
return [A2ATaskEventBatch(
|
|
95
|
+
sequence=int(row[0]), batch_id=str(row[1]), platform_task_id=str(row[2]),
|
|
96
|
+
events=list(json.loads(row[3])), attempt_count=int(row[4]),
|
|
97
|
+
) for row in result]
|
|
98
|
+
|
|
99
|
+
async def acknowledge(self, batch_id):
|
|
100
|
+
async with self._engine.begin() as connection:
|
|
101
|
+
await connection.execute(text("""
|
|
102
|
+
DELETE FROM ksadk_a2a_owned_task_event_outbox
|
|
103
|
+
WHERE owner_key = :owner AND batch_id = :batch
|
|
104
|
+
"""), {"owner": self._owner, "batch": batch_id})
|
|
105
|
+
|
|
106
|
+
async def record_failure(self, batch_id, error):
|
|
107
|
+
async with self._engine.begin() as connection:
|
|
108
|
+
await connection.execute(text("""
|
|
109
|
+
UPDATE ksadk_a2a_owned_task_event_outbox
|
|
110
|
+
SET attempt_count = attempt_count + 1, last_error = :error
|
|
111
|
+
WHERE owner_key = :owner AND batch_id = :batch
|
|
112
|
+
"""), {"owner": self._owner, "batch": batch_id, "error": error[:512]})
|
|
113
|
+
|
|
114
|
+
async def dead_letter(self, batch_id, error):
|
|
115
|
+
async with self._engine.begin() as connection:
|
|
116
|
+
params = {"owner": self._owner, "batch": batch_id, "error": error[:512]}
|
|
117
|
+
await connection.execute(text("""
|
|
118
|
+
INSERT INTO ksadk_a2a_owned_task_event_dead_letters(
|
|
119
|
+
sequence, owner_key, batch_id, platform_task_id, events_json,
|
|
120
|
+
created_at, attempt_count, last_error
|
|
121
|
+
) SELECT sequence, owner_key, batch_id, platform_task_id, events_json,
|
|
122
|
+
created_at, attempt_count, :error
|
|
123
|
+
FROM ksadk_a2a_owned_task_event_outbox
|
|
124
|
+
WHERE owner_key = :owner AND batch_id = :batch
|
|
125
|
+
ON CONFLICT(batch_id) DO NOTHING
|
|
126
|
+
"""), params)
|
|
127
|
+
await connection.execute(text("""
|
|
128
|
+
DELETE FROM ksadk_a2a_owned_task_event_outbox
|
|
129
|
+
WHERE owner_key = :owner AND batch_id = :batch
|
|
130
|
+
"""), {"owner": self._owner, "batch": batch_id})
|
ksadk/a2a/task_store.py
CHANGED
|
@@ -19,6 +19,8 @@ from a2a.server import models as _sdk_models
|
|
|
19
19
|
from a2a.server.context import ServerCallContext
|
|
20
20
|
from a2a.server.routes.common import DefaultServerCallContextBuilder
|
|
21
21
|
from a2a.server.tasks import DatabaseTaskStore
|
|
22
|
+
from a2a.types import Task, TaskState, TaskStatus
|
|
23
|
+
from sqlalchemy import update
|
|
22
24
|
from sqlalchemy.exc import SAWarning
|
|
23
25
|
from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
|
|
24
26
|
from starlette.requests import Request
|
|
@@ -75,6 +77,41 @@ class _KsADKDatabaseTaskStore(DatabaseTaskStore):
|
|
|
75
77
|
self.task_model = _task_model(table_name)
|
|
76
78
|
|
|
77
79
|
|
|
80
|
+
async def save_confirmed_cancellation(
|
|
81
|
+
self, task: Task, status: TaskStatus, context: ServerCallContext,
|
|
82
|
+
) -> Task | None:
|
|
83
|
+
"""Repair a lost cancel event without replacing a concurrently committed terminal."""
|
|
84
|
+
if status.state != TaskState.TASK_STATE_CANCELED:
|
|
85
|
+
raise ValueError("Only confirmed cancellation can use this repair")
|
|
86
|
+
return await self.save_confirmed_terminal(task, status, context)
|
|
87
|
+
|
|
88
|
+
async def save_confirmed_terminal(
|
|
89
|
+
self, task: Task, status: TaskStatus, context: ServerCallContext,
|
|
90
|
+
) -> Task | None:
|
|
91
|
+
"""Apply an authoritative terminal status without replacing a newer terminal."""
|
|
92
|
+
if status.state not in {TaskState.TASK_STATE_FAILED, TaskState.TASK_STATE_CANCELED,
|
|
93
|
+
TaskState.TASK_STATE_COMPLETED}:
|
|
94
|
+
raise ValueError("Only confirmed terminal states can use this repair")
|
|
95
|
+
await self._ensure_initialized()
|
|
96
|
+
owner = self.owner_resolver(context)
|
|
97
|
+
canceled = Task()
|
|
98
|
+
canceled.CopyFrom(task)
|
|
99
|
+
canceled.status.CopyFrom(status)
|
|
100
|
+
record = self._to_orm(canceled, owner)
|
|
101
|
+
# Guard inside UPDATE, rather than a separate read/check/write. Update only
|
|
102
|
+
# status fields so concurrent artifacts/history cannot be replaced by a cache.
|
|
103
|
+
active = ["TASK_STATE_SUBMITTED", "TASK_STATE_WORKING",
|
|
104
|
+
"TASK_STATE_INPUT_REQUIRED", "TASK_STATE_AUTH_REQUIRED"]
|
|
105
|
+
async with self.async_session_maker.begin() as session:
|
|
106
|
+
await session.execute(update(self.task_model).where(
|
|
107
|
+
self.task_model.id == task.id,
|
|
108
|
+
self.task_model.owner == owner,
|
|
109
|
+
self.task_model.protocol_version == "1.0",
|
|
110
|
+
self.task_model.status["state"].as_string().in_(active),
|
|
111
|
+
).values(status=record.status, last_updated=record.last_updated))
|
|
112
|
+
return await self.get(task.id, context)
|
|
113
|
+
|
|
114
|
+
|
|
78
115
|
def _first(state: dict[str, Any], *keys: str) -> Optional[str]:
|
|
79
116
|
for key in keys:
|
|
80
117
|
value = state.get(key)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"""Explicit public tool disclosure at the callee wire boundary."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Mapping
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from a2a.types import Part
|
|
10
|
+
from google.protobuf.json_format import ParseDict
|
|
11
|
+
from google.protobuf.struct_pb2 import Value
|
|
12
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
13
|
+
|
|
14
|
+
from ksadk.a2a.presentation import (
|
|
15
|
+
A2A_TOOL_ACTIVITY_EXTENSION_URI,
|
|
16
|
+
A2A_TOOL_ACTIVITY_MAX_EVENT_BYTES,
|
|
17
|
+
A2A_TOOL_ACTIVITY_MAX_INVOCATION_BYTES,
|
|
18
|
+
build_public_tool_activity,
|
|
19
|
+
)
|
|
20
|
+
from ksadk.events.canonical import ItemCompleted, ItemSnapshotReplaced, ItemStarted, ItemUpdated
|
|
21
|
+
from ksadk.events.content import ToolCallContent, ToolResultContent
|
|
22
|
+
from ksadk.events.identity import stable_item_id
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class PublicToolRule:
|
|
27
|
+
"""Only named top-level fields cross the boundary; everything else is private."""
|
|
28
|
+
|
|
29
|
+
name: str
|
|
30
|
+
arguments: frozenset[str] = frozenset()
|
|
31
|
+
results: frozenset[str] = frozenset()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class PublicToolActivityPolicy:
|
|
36
|
+
tools: Mapping[str, PublicToolRule] = field(default_factory=dict)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_json(cls, payload: str) -> PublicToolActivityPolicy:
|
|
40
|
+
"""Load a platform-owned declaration, never a request/model override."""
|
|
41
|
+
declaration = _PublicToolDeclaration.model_validate_json(payload)
|
|
42
|
+
return cls(
|
|
43
|
+
{
|
|
44
|
+
name: PublicToolRule(rule.name, frozenset(rule.arguments), frozenset(rule.results))
|
|
45
|
+
for name, rule in declaration.tools.items()
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class _PublicToolFields(BaseModel):
|
|
51
|
+
model_config = ConfigDict(extra="forbid", strict=True)
|
|
52
|
+
name: str = Field(pattern=r"^[A-Za-z_][A-Za-z0-9_.:-]{0,127}$")
|
|
53
|
+
arguments: list[str] = Field(default_factory=list, max_length=100)
|
|
54
|
+
results: list[str] = Field(default_factory=list, max_length=100)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class _PublicToolDeclaration(BaseModel):
|
|
58
|
+
model_config = ConfigDict(extra="forbid", strict=True)
|
|
59
|
+
tools: dict[str, _PublicToolFields] = Field(max_length=100)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class PublicToolActivityProducer:
|
|
63
|
+
def __init__(self, policy: PublicToolActivityPolicy) -> None:
|
|
64
|
+
self.policy = policy
|
|
65
|
+
self._calls: dict[tuple[str, str], PublicToolRule] = {}
|
|
66
|
+
self._bytes = 0
|
|
67
|
+
self._seen: set[str] = set()
|
|
68
|
+
self._budget_exhausted = False
|
|
69
|
+
|
|
70
|
+
async def _publish(
|
|
71
|
+
self,
|
|
72
|
+
*,
|
|
73
|
+
activity_payload: dict[str, Any],
|
|
74
|
+
public_item: str,
|
|
75
|
+
public_event: str,
|
|
76
|
+
updater: Any,
|
|
77
|
+
) -> None:
|
|
78
|
+
if public_event in self._seen or self._budget_exhausted:
|
|
79
|
+
return
|
|
80
|
+
activity = build_public_tool_activity(activity_payload)
|
|
81
|
+
size = len(activity.model_dump_json().encode())
|
|
82
|
+
# Reserve room for an explicit, sanitized truncation observation.
|
|
83
|
+
# Never consume the entire invocation budget and silently drop output.
|
|
84
|
+
exhausted = self._bytes + size > (
|
|
85
|
+
A2A_TOOL_ACTIVITY_MAX_INVOCATION_BYTES - A2A_TOOL_ACTIVITY_MAX_EVENT_BYTES
|
|
86
|
+
)
|
|
87
|
+
if exhausted:
|
|
88
|
+
activity = build_public_tool_activity(
|
|
89
|
+
{**activity_payload, "arguments": None, "result": None, "truncated": True}
|
|
90
|
+
)
|
|
91
|
+
size = len(activity.model_dump_json().encode())
|
|
92
|
+
terminal = activity.operation in {"completed", "failed"}
|
|
93
|
+
await updater.add_artifact(
|
|
94
|
+
artifact_id=public_item,
|
|
95
|
+
name="public-tool-activity",
|
|
96
|
+
parts=[
|
|
97
|
+
Part(
|
|
98
|
+
data=ParseDict(activity.model_dump(mode="json"), Value()),
|
|
99
|
+
metadata={"extension_uri": A2A_TOOL_ACTIVITY_EXTENSION_URI},
|
|
100
|
+
)
|
|
101
|
+
],
|
|
102
|
+
metadata={
|
|
103
|
+
"event_id": public_event,
|
|
104
|
+
"extension_uri": A2A_TOOL_ACTIVITY_EXTENSION_URI,
|
|
105
|
+
},
|
|
106
|
+
append=False,
|
|
107
|
+
last_chunk=terminal,
|
|
108
|
+
)
|
|
109
|
+
# A failed store/write is retryable with the same public event identity.
|
|
110
|
+
self._bytes += size
|
|
111
|
+
self._seen.add(public_event)
|
|
112
|
+
self._budget_exhausted = exhausted
|
|
113
|
+
|
|
114
|
+
async def emit(self, event: Any, updater: Any) -> None:
|
|
115
|
+
if not isinstance(event, (ItemStarted, ItemUpdated, ItemSnapshotReplaced, ItemCompleted)):
|
|
116
|
+
return
|
|
117
|
+
if event.item_kind not in {"tool_call", "tool_result"}:
|
|
118
|
+
return
|
|
119
|
+
snapshot = getattr(event, "snapshot", None) or getattr(event, "initial", None)
|
|
120
|
+
parts = snapshot.parts if snapshot is not None else (getattr(event, "update", None),)
|
|
121
|
+
for part in parts:
|
|
122
|
+
if isinstance(part, ToolCallContent):
|
|
123
|
+
rule = self.policy.tools.get(part.name)
|
|
124
|
+
if rule is None:
|
|
125
|
+
continue
|
|
126
|
+
self._calls[(event.scope_id, part.call_id)] = rule
|
|
127
|
+
elif isinstance(part, ToolResultContent):
|
|
128
|
+
rule = self._calls.get((event.scope_id, part.call_id))
|
|
129
|
+
if rule is None:
|
|
130
|
+
continue
|
|
131
|
+
else:
|
|
132
|
+
continue
|
|
133
|
+
public_item = stable_item_id("a2a-tool", event.scope_id, event.item_id)
|
|
134
|
+
public_call = stable_item_id("a2a-tool", event.scope_id, part.call_id)
|
|
135
|
+
is_call = isinstance(part, ToolCallContent)
|
|
136
|
+
is_error = isinstance(part, ToolResultContent) and part.is_error
|
|
137
|
+
complete = isinstance(event, ItemCompleted)
|
|
138
|
+
operation = "failed" if is_error else "completed" if complete else "updated"
|
|
139
|
+
common = {
|
|
140
|
+
"item_id": public_item,
|
|
141
|
+
"call_id": public_call,
|
|
142
|
+
"item_kind": "tool_call" if is_call else "tool_result",
|
|
143
|
+
"execution_status": (
|
|
144
|
+
"failed" if is_error else "completed" if complete and not is_call else "running"
|
|
145
|
+
),
|
|
146
|
+
"name": rule.name if is_call else None,
|
|
147
|
+
"arguments": self._select(part.arguments, rule.arguments) if is_call else None,
|
|
148
|
+
"result": None if is_call else self._select(part.result, rule.results),
|
|
149
|
+
"is_error": is_error,
|
|
150
|
+
}
|
|
151
|
+
if is_call and complete:
|
|
152
|
+
started_event = stable_item_id("a2a-tool", event.event_id, part.part_id, "started")
|
|
153
|
+
await self._publish(
|
|
154
|
+
activity_payload={
|
|
155
|
+
**common,
|
|
156
|
+
"event_id": started_event,
|
|
157
|
+
"operation": "started",
|
|
158
|
+
"execution_status": "running",
|
|
159
|
+
},
|
|
160
|
+
public_item=public_item,
|
|
161
|
+
public_event=started_event,
|
|
162
|
+
updater=updater,
|
|
163
|
+
)
|
|
164
|
+
public_event = stable_item_id("a2a-tool", event.event_id, part.part_id, operation)
|
|
165
|
+
await self._publish(
|
|
166
|
+
activity_payload={**common, "event_id": public_event, "operation": operation},
|
|
167
|
+
public_item=public_item,
|
|
168
|
+
public_event=public_event,
|
|
169
|
+
updater=updater,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
@staticmethod
|
|
173
|
+
def _select(value: Any, keys: frozenset[str]) -> dict[str, Any]:
|
|
174
|
+
if not isinstance(value, Mapping):
|
|
175
|
+
return {}
|
|
176
|
+
return {key: value[key] for key in keys if key in value}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Audience-specific projected workload-token loading and validation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import base64
|
|
6
|
+
import binascii
|
|
7
|
+
import errno
|
|
8
|
+
import json
|
|
9
|
+
import os
|
|
10
|
+
import stat
|
|
11
|
+
import time
|
|
12
|
+
from abc import ABC, abstractmethod
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
ENV_A2A_TOKEN_DIR = "KSADK_A2A_TOKEN_DIR"
|
|
16
|
+
|
|
17
|
+
DEFAULT_A2A_TOKEN_DIR = "/var/run/secrets/agentengine/a2a"
|
|
18
|
+
|
|
19
|
+
MAX_WORKLOAD_TOKEN_BYTES = 16 * 1024
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WorkloadTokenProvider(ABC):
|
|
23
|
+
"""Returns a short-lived workload token for one exact audience."""
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def get_token(self, audience: str) -> str:
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class FileWorkloadTokenProvider(WorkloadTokenProvider):
|
|
31
|
+
"""Reads audience-specific projected JWT files before every request."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, token_dir: str | os.PathLike[str] | None = None) -> None:
|
|
34
|
+
configured = token_dir or os.getenv(ENV_A2A_TOKEN_DIR) or DEFAULT_A2A_TOKEN_DIR
|
|
35
|
+
self._token_dir = Path(configured)
|
|
36
|
+
|
|
37
|
+
def get_token(self, audience: str) -> str:
|
|
38
|
+
if not audience or "/" in audience or audience in {".", ".."}:
|
|
39
|
+
raise ValueError(f"invalid workload token audience: {audience!r}")
|
|
40
|
+
path = self._token_dir / f"{audience}.jwt"
|
|
41
|
+
if path.is_symlink():
|
|
42
|
+
# AtomicWriter rotates ..data atomically. Only accept its exact key
|
|
43
|
+
# layout, and open the resolved generation without following links.
|
|
44
|
+
if os.readlink(path) != f"..data/{path.name}":
|
|
45
|
+
raise RuntimeError(f"invalid workload token symlink for {audience!r}")
|
|
46
|
+
try:
|
|
47
|
+
volume = self._token_dir.resolve(strict=True)
|
|
48
|
+
relative = path.resolve(strict=True).relative_to(volume)
|
|
49
|
+
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
|
50
|
+
directory = os.open(volume, flags | os.O_DIRECTORY)
|
|
51
|
+
try:
|
|
52
|
+
for component in relative.parts[:-1]:
|
|
53
|
+
child = os.open(component, flags | os.O_DIRECTORY, dir_fd=directory)
|
|
54
|
+
os.close(directory)
|
|
55
|
+
directory = child
|
|
56
|
+
descriptor = os.open(relative.name, flags | os.O_NONBLOCK, dir_fd=directory)
|
|
57
|
+
finally:
|
|
58
|
+
os.close(directory)
|
|
59
|
+
except (OSError, ValueError, RuntimeError) as exc:
|
|
60
|
+
raise RuntimeError(f"unsafe workload token projection for {audience!r}") from exc
|
|
61
|
+
else:
|
|
62
|
+
descriptor = self._open_regular_token(path, audience)
|
|
63
|
+
return self._read_token(descriptor, path, audience)
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _open_regular_token(path: Path, audience: str) -> int:
|
|
67
|
+
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
|
|
68
|
+
try:
|
|
69
|
+
return os.open(path, flags | os.O_NONBLOCK)
|
|
70
|
+
except OSError as exc:
|
|
71
|
+
if exc.errno == errno.ELOOP:
|
|
72
|
+
raise RuntimeError(
|
|
73
|
+
f"workload token for audience {audience!r} must not be a symlink: {path}"
|
|
74
|
+
) from exc
|
|
75
|
+
raise RuntimeError(f"missing workload token for audience {audience!r}: {path}") from exc
|
|
76
|
+
|
|
77
|
+
def _read_token(self, descriptor: int, path: Path, audience: str) -> str:
|
|
78
|
+
try:
|
|
79
|
+
token_stat = os.fstat(descriptor)
|
|
80
|
+
if not stat.S_ISREG(token_stat.st_mode):
|
|
81
|
+
raise RuntimeError(
|
|
82
|
+
f"workload token for audience {audience!r} is not a regular file: {path}"
|
|
83
|
+
)
|
|
84
|
+
if token_stat.st_size > MAX_WORKLOAD_TOKEN_BYTES:
|
|
85
|
+
raise RuntimeError(
|
|
86
|
+
f"workload token for audience {audience!r} exceeds 16 KiB: {path}"
|
|
87
|
+
)
|
|
88
|
+
# Kubernetes adds group-read for a configured pod fsGroup. Keep
|
|
89
|
+
# credentials read-only and never permit access by other users.
|
|
90
|
+
if stat.S_IMODE(token_stat.st_mode) not in {0o400, 0o440}:
|
|
91
|
+
raise RuntimeError(
|
|
92
|
+
f"workload token for audience {audience!r} must have mode 0400 or 0440: {path}"
|
|
93
|
+
)
|
|
94
|
+
with os.fdopen(descriptor, "rb", closefd=False) as token_file:
|
|
95
|
+
raw_token = token_file.read(MAX_WORKLOAD_TOKEN_BYTES + 1)
|
|
96
|
+
if len(raw_token) > MAX_WORKLOAD_TOKEN_BYTES:
|
|
97
|
+
raise RuntimeError(
|
|
98
|
+
f"workload token for audience {audience!r} exceeds 16 KiB: {path}"
|
|
99
|
+
)
|
|
100
|
+
token = raw_token.decode("ascii").strip()
|
|
101
|
+
except UnicodeError as exc:
|
|
102
|
+
raise RuntimeError(
|
|
103
|
+
f"workload token for audience {audience!r} must be ASCII: {path}"
|
|
104
|
+
) from exc
|
|
105
|
+
finally:
|
|
106
|
+
os.close(descriptor)
|
|
107
|
+
if not token:
|
|
108
|
+
raise RuntimeError(f"empty workload token for audience {audience!r}: {path}")
|
|
109
|
+
self._validate_expiry(token, audience=audience, path=path)
|
|
110
|
+
return token
|
|
111
|
+
|
|
112
|
+
@staticmethod
|
|
113
|
+
def _validate_expiry(token: str, *, audience: str, path: Path) -> None:
|
|
114
|
+
parts = token.split(".")
|
|
115
|
+
if len(parts) != 3:
|
|
116
|
+
raise RuntimeError(f"workload token for audience {audience!r} is not a JWT: {path}")
|
|
117
|
+
try:
|
|
118
|
+
payload_segment = parts[1] + "=" * (-len(parts[1]) % 4)
|
|
119
|
+
payload = json.loads(base64.urlsafe_b64decode(payload_segment).decode("utf-8"))
|
|
120
|
+
expires_at = int(payload["exp"])
|
|
121
|
+
except (binascii.Error, KeyError, TypeError, ValueError, json.JSONDecodeError) as exc:
|
|
122
|
+
raise RuntimeError(
|
|
123
|
+
f"workload token for audience {audience!r} has no valid exp claim: {path}"
|
|
124
|
+
) from exc
|
|
125
|
+
token_audience = payload.get("aud")
|
|
126
|
+
accepted_audiences = (
|
|
127
|
+
{str(item) for item in token_audience}
|
|
128
|
+
if isinstance(token_audience, list)
|
|
129
|
+
else {str(token_audience)}
|
|
130
|
+
)
|
|
131
|
+
if audience not in accepted_audiences:
|
|
132
|
+
raise RuntimeError(f"workload token audience mismatch for {audience!r}: {path}")
|
|
133
|
+
if expires_at <= int(time.time()):
|
|
134
|
+
raise RuntimeError(f"workload token for audience {audience!r} is expired: {path}")
|