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/a2a/executor.py
CHANGED
|
@@ -11,9 +11,13 @@ wire 对象在 a2a-sdk 1.1.0 是 protobuf(``a2a_pb2``);文本用 ``Part(text=...
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
from ksadk.a2a.inbound_kernel import ManagedKernelRequestError
|
|
15
|
+
|
|
14
16
|
import inspect
|
|
15
17
|
import json
|
|
16
18
|
import logging
|
|
19
|
+
import os
|
|
20
|
+
import time
|
|
17
21
|
from typing import Any, Literal
|
|
18
22
|
|
|
19
23
|
from a2a.server.agent_execution import AgentExecutor, RequestContext
|
|
@@ -23,18 +27,23 @@ from a2a.types import Part, Task, TaskState, TaskStatus
|
|
|
23
27
|
from a2a.utils.errors import TaskNotCancelableError
|
|
24
28
|
|
|
25
29
|
from ksadk.a2a.resume_store import A2AResumePayloadKind
|
|
30
|
+
from ksadk.a2a.tool_activity import PublicToolActivityPolicy, PublicToolActivityProducer
|
|
26
31
|
from ksadk.events.canonical import (
|
|
32
|
+
ApprovalRequest,
|
|
27
33
|
ContinuationCreated,
|
|
28
34
|
EventEnvelope,
|
|
29
35
|
InteractionRequested,
|
|
30
36
|
ItemCompleted,
|
|
37
|
+
ItemSnapshotReplaced,
|
|
31
38
|
ItemUpdated,
|
|
32
39
|
RunCanceled,
|
|
40
|
+
RunCompleted,
|
|
33
41
|
RunFailed,
|
|
34
42
|
RunInterrupted,
|
|
35
|
-
|
|
43
|
+
StructuredInputRequest,
|
|
36
44
|
)
|
|
37
45
|
from ksadk.events.content import TextContent
|
|
46
|
+
from ksadk.events.identity import stable_item_id
|
|
38
47
|
from ksadk.runtime import CancelResult, RunHandle
|
|
39
48
|
|
|
40
49
|
logger = logging.getLogger(__name__)
|
|
@@ -61,15 +70,19 @@ def _thought_part(text: str) -> Part:
|
|
|
61
70
|
|
|
62
71
|
|
|
63
72
|
class _ArtifactStreamEmitter:
|
|
64
|
-
"""
|
|
73
|
+
"""Bound text update volume while retaining the final artifact chunk."""
|
|
74
|
+
|
|
75
|
+
FLUSH_INTERVAL_SECONDS = 0.5
|
|
76
|
+
MAX_PENDING_CHARS = 512
|
|
65
77
|
|
|
66
|
-
def __init__(self, updater: TaskUpdater, task_id: str) -> None:
|
|
78
|
+
def __init__(self, updater: TaskUpdater, task_id: str, *, clock=None) -> None:
|
|
67
79
|
self._updater = updater
|
|
68
80
|
self._task_id = task_id
|
|
69
|
-
self.
|
|
70
|
-
self.
|
|
71
|
-
self.
|
|
72
|
-
self.
|
|
81
|
+
self._clock = clock or time.monotonic
|
|
82
|
+
self._emitted: dict[tuple[_ArtifactKind, tuple[str, str]], int] = {}
|
|
83
|
+
self._pending: tuple[_ArtifactKind, str, bool, tuple[str, str], float] | None = None
|
|
84
|
+
self.source_updates = 0
|
|
85
|
+
self.wire_updates = 0
|
|
73
86
|
|
|
74
87
|
async def push(
|
|
75
88
|
self,
|
|
@@ -77,47 +90,57 @@ class _ArtifactStreamEmitter:
|
|
|
77
90
|
text: str,
|
|
78
91
|
*,
|
|
79
92
|
replace_snapshot: bool = False,
|
|
93
|
+
identity: tuple[str, str],
|
|
80
94
|
) -> None:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await self._emit(self._pending, last_chunk=switched)
|
|
84
|
-
if self._active_kind != kind:
|
|
85
|
-
self._segments[kind] += 1
|
|
86
|
-
self._active_kind = kind
|
|
87
|
-
self._pending = (kind, text, replace_snapshot, self._segments[kind])
|
|
88
|
-
|
|
89
|
-
async def close(self) -> None:
|
|
95
|
+
self.source_updates += 1
|
|
96
|
+
now = self._clock()
|
|
90
97
|
if self._pending is None:
|
|
98
|
+
self._pending = (kind, text, replace_snapshot, identity, now)
|
|
91
99
|
return
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
pending_kind, pending_text, pending_replace, pending_identity, started = self._pending
|
|
101
|
+
switched = (pending_kind, pending_identity) != (kind, identity)
|
|
102
|
+
first_visible = (pending_kind, pending_identity) not in self._emitted
|
|
103
|
+
if (
|
|
104
|
+
switched
|
|
105
|
+
or first_visible
|
|
106
|
+
or pending_replace
|
|
107
|
+
or replace_snapshot
|
|
108
|
+
or len(pending_text) + len(text) >= self.MAX_PENDING_CHARS
|
|
109
|
+
or now - started >= self.FLUSH_INTERVAL_SECONDS
|
|
110
|
+
):
|
|
111
|
+
await self._flush_pending(last_chunk=switched)
|
|
112
|
+
self._pending = (kind, text, replace_snapshot, identity, now)
|
|
113
|
+
else:
|
|
114
|
+
self._pending = (kind, pending_text + text, False, identity, started)
|
|
115
|
+
|
|
116
|
+
async def close(self) -> None:
|
|
117
|
+
await self._flush_pending(last_chunk=True)
|
|
118
|
+
|
|
119
|
+
async def _flush_pending(self, *, last_chunk: bool = False) -> None:
|
|
120
|
+
pending, self._pending = self._pending, None
|
|
121
|
+
if pending is not None:
|
|
122
|
+
kind, text, replace_snapshot, identity, _ = pending
|
|
123
|
+
await self._emit(kind, text, replace_snapshot, identity, last_chunk=last_chunk)
|
|
94
124
|
|
|
95
125
|
async def _emit(
|
|
96
126
|
self,
|
|
97
|
-
|
|
127
|
+
kind: _ArtifactKind,
|
|
128
|
+
text: str,
|
|
129
|
+
replace_snapshot: bool,
|
|
130
|
+
identity: tuple[str, str],
|
|
98
131
|
*,
|
|
99
132
|
last_chunk: bool,
|
|
100
133
|
) -> None:
|
|
101
|
-
|
|
102
|
-
key = (kind, segment)
|
|
134
|
+
key = (kind, identity)
|
|
103
135
|
self._emitted[key] = self._emitted.get(key, 0) + 1
|
|
104
136
|
is_reasoning = kind == "thinking"
|
|
105
|
-
|
|
106
|
-
f"{self._task_id}-reasoning"
|
|
107
|
-
if is_reasoning
|
|
108
|
-
else f"{self._task_id}-response"
|
|
109
|
-
)
|
|
110
|
-
artifact_id = base_id if segment == 1 else f"{base_id}-{segment}"
|
|
137
|
+
artifact_id = stable_item_id("a2a-output", self._task_id, *identity, kind)
|
|
111
138
|
part = (
|
|
112
139
|
_thought_part(text)
|
|
113
140
|
if is_reasoning
|
|
114
141
|
else Part(
|
|
115
142
|
text=text,
|
|
116
|
-
metadata=(
|
|
117
|
-
dict(_OUTPUT_SNAPSHOT_METADATA)
|
|
118
|
-
if replace_snapshot
|
|
119
|
-
else None
|
|
120
|
-
),
|
|
143
|
+
metadata=(dict(_OUTPUT_SNAPSHOT_METADATA) if replace_snapshot else None),
|
|
121
144
|
)
|
|
122
145
|
)
|
|
123
146
|
await self._updater.add_artifact(
|
|
@@ -127,6 +150,7 @@ class _ArtifactStreamEmitter:
|
|
|
127
150
|
append=False if replace_snapshot else self._emitted[key] > 1,
|
|
128
151
|
last_chunk=last_chunk,
|
|
129
152
|
)
|
|
153
|
+
self.wire_updates += 1
|
|
130
154
|
|
|
131
155
|
|
|
132
156
|
async def _enqueue_initial_task(context: RequestContext, event_queue: EventQueue) -> None:
|
|
@@ -173,8 +197,7 @@ def _require_resume_capability(task_adapter: Any) -> None:
|
|
|
173
197
|
from ksadk.kernel.errors import UnsupportedControlError
|
|
174
198
|
|
|
175
199
|
raise UnsupportedControlError(
|
|
176
|
-
"runtime capability matrix declares resume unsupported: "
|
|
177
|
-
f"{matrix.resume.reason}"
|
|
200
|
+
f"runtime capability matrix declares resume unsupported: {matrix.resume.reason}"
|
|
178
201
|
)
|
|
179
202
|
|
|
180
203
|
|
|
@@ -189,13 +212,20 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
189
212
|
self,
|
|
190
213
|
task_adapter: Any,
|
|
191
214
|
include_reasoning: bool = False,
|
|
215
|
+
public_tool_policy: PublicToolActivityPolicy | None = None,
|
|
192
216
|
) -> None:
|
|
193
217
|
if task_adapter is None:
|
|
194
218
|
raise TypeError("task_adapter is required")
|
|
195
219
|
self.task_adapter = task_adapter
|
|
196
220
|
self.include_reasoning = include_reasoning
|
|
221
|
+
self.public_tool_policy = public_tool_policy or PublicToolActivityPolicy()
|
|
197
222
|
|
|
198
223
|
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
224
|
+
select = getattr(self.task_adapter, "for_context", None)
|
|
225
|
+
if callable(select):
|
|
226
|
+
selected = select(context)
|
|
227
|
+
if selected is not self.task_adapter:
|
|
228
|
+
return await A2ARuntimeExecutor(selected, self.include_reasoning, self.public_tool_policy).execute(context, event_queue)
|
|
199
229
|
current_task = getattr(context, "current_task", None)
|
|
200
230
|
durable_context_id = str(
|
|
201
231
|
getattr(current_task, "context_id", "") or context.context_id or "unknown-context"
|
|
@@ -213,6 +243,11 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
213
243
|
from ksadk.kernel.ingress import kernel_route_active
|
|
214
244
|
|
|
215
245
|
if kernel_route_active() and not is_resume:
|
|
246
|
+
# The A2A SDK requires the initial Task before any status update.
|
|
247
|
+
# Kernel execution reports progress through TaskUpdater just like
|
|
248
|
+
# the legacy adapter path, so it must establish the same wire
|
|
249
|
+
# lifecycle first or clients discard working/completed updates.
|
|
250
|
+
await _enqueue_initial_task(context, event_queue)
|
|
216
251
|
await self._kernel_execute(context, updater)
|
|
217
252
|
return
|
|
218
253
|
|
|
@@ -242,31 +277,34 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
242
277
|
await _enqueue_initial_task(context, event_queue)
|
|
243
278
|
# start_work 不透传 metadata;直接 update_status 以带 ADK v2 扩展标记
|
|
244
279
|
# (RemoteA2aAgent 读 task/status metadata 决定走 v2 全增量 handler)。
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
280
|
+
server_admitted = bool(getattr(self.task_adapter, "server_admitted", False))
|
|
281
|
+
if not server_admitted:
|
|
282
|
+
await updater.update_status(
|
|
283
|
+
TaskState.TASK_STATE_WORKING,
|
|
284
|
+
metadata=dict(ADK_V2_INTEGRATION_METADATA),
|
|
285
|
+
)
|
|
249
286
|
if is_resume:
|
|
250
287
|
handle = await self.task_adapter.resume_task(
|
|
251
288
|
context.task_id or "",
|
|
252
289
|
context,
|
|
253
290
|
answer=interaction_response,
|
|
254
291
|
)
|
|
255
|
-
|
|
292
|
+
if server_admitted:
|
|
293
|
+
await updater.update_status(TaskState.TASK_STATE_WORKING, metadata=dict(ADK_V2_INTEGRATION_METADATA))
|
|
294
|
+
await self._run_runtime(context, updater, handle)
|
|
256
295
|
else:
|
|
257
296
|
handle = await self.task_adapter.start_task(
|
|
258
297
|
task_id=str(context.task_id or ""),
|
|
259
298
|
context=context,
|
|
260
299
|
input_data=context.get_user_input(),
|
|
261
300
|
)
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
#
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
await updater.complete(message=completion_message)
|
|
301
|
+
if server_admitted:
|
|
302
|
+
await updater.update_status(TaskState.TASK_STATE_WORKING, metadata=dict(ADK_V2_INTEGRATION_METADATA))
|
|
303
|
+
await self._run_runtime(context, updater, handle)
|
|
304
|
+
# Every output is already a durable, identity-bearing Task artifact.
|
|
305
|
+
# A fresh status Message would introduce a third output identity for
|
|
306
|
+
# the same answer. Complete the Task without copying artifact text.
|
|
307
|
+
await updater.complete()
|
|
270
308
|
await self._forget_task(context, handle)
|
|
271
309
|
except _InputRequired:
|
|
272
310
|
# runner 请求输入:task 已停在 input-required(附 resume token),不 complete。
|
|
@@ -274,6 +312,10 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
274
312
|
except _RunCanceled:
|
|
275
313
|
logger.info("A2A task %s 已由 runtime 取消", context.task_id)
|
|
276
314
|
await self._forget_task(context, handle)
|
|
315
|
+
except ManagedKernelRequestError:
|
|
316
|
+
# In particular, a lost admission reply must not erase an existing
|
|
317
|
+
# input-required task or declare an accepted remote execution failed.
|
|
318
|
+
raise
|
|
277
319
|
except Exception as exc: # noqa: BLE001
|
|
278
320
|
logger.error("A2A task execution failed (%s)", type(exc).__name__)
|
|
279
321
|
await updater.failed(
|
|
@@ -290,8 +332,8 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
290
332
|
from ksadk.kernel import ingress as _kernel_ingress
|
|
291
333
|
|
|
292
334
|
task_id = str(context.task_id or "")
|
|
293
|
-
session_id = str(context.context_id or task_id)
|
|
294
335
|
try:
|
|
336
|
+
session_id = await self._prepare_kernel_session(context, task_id=task_id)
|
|
295
337
|
trusted = _kernel_ingress.trusted_context(
|
|
296
338
|
source_kind="a2a",
|
|
297
339
|
source_ref=task_id,
|
|
@@ -332,20 +374,73 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
332
374
|
elif kind == "completed":
|
|
333
375
|
output_text = value or output_text
|
|
334
376
|
completion = (
|
|
335
|
-
updater.new_agent_message(parts=[Part(text=output_text)])
|
|
336
|
-
if output_text
|
|
337
|
-
else None
|
|
377
|
+
updater.new_agent_message(parts=[Part(text=output_text)]) if output_text else None
|
|
338
378
|
)
|
|
339
379
|
await updater.complete(message=completion)
|
|
340
380
|
except Exception as exc: # noqa: BLE001
|
|
341
381
|
logger.error("A2A kernel ingress failed (%s)", type(exc).__name__)
|
|
342
382
|
await updater.failed(
|
|
343
|
-
message=updater.new_agent_message(
|
|
344
|
-
parts=[Part(text="A2A task execution failed")]
|
|
345
|
-
)
|
|
383
|
+
message=updater.new_agent_message(parts=[Part(text="A2A task execution failed")])
|
|
346
384
|
)
|
|
347
385
|
|
|
386
|
+
async def _prepare_kernel_session(self, context: RequestContext, *, task_id: str) -> str:
|
|
387
|
+
"""Resolve the durable A2A context and create its shared-log session.
|
|
388
|
+
|
|
389
|
+
The legacy RuntimeAdapter path calls ``prepare_context`` from
|
|
390
|
+
``start_task``. Kernel routing bypasses ``start_task``, so it must do
|
|
391
|
+
the same verified external-context mapping before constructing the
|
|
392
|
+
command. The command admission and worker then write to this exact
|
|
393
|
+
session in the Kernel-bound service.
|
|
394
|
+
"""
|
|
395
|
+
|
|
396
|
+
session_id = ""
|
|
397
|
+
prepare_context = getattr(self.task_adapter, "prepare_context", None)
|
|
398
|
+
if callable(prepare_context):
|
|
399
|
+
prepared = prepare_context(context)
|
|
400
|
+
if inspect.isawaitable(prepared):
|
|
401
|
+
prepared = await prepared
|
|
402
|
+
session_id = str(prepared or "")
|
|
403
|
+
if not session_id:
|
|
404
|
+
session_id = str(context.context_id or task_id)
|
|
405
|
+
if not session_id:
|
|
406
|
+
raise RuntimeError("A2A_SESSION_ID_REQUIRED")
|
|
407
|
+
|
|
408
|
+
from ksadk.kernel.bootstrap import get_agent_kernel_runtime
|
|
409
|
+
from ksadk.sessions import resolve_session_service
|
|
410
|
+
|
|
411
|
+
runtime = get_agent_kernel_runtime()
|
|
412
|
+
runtime_config = getattr(runtime, "config", None)
|
|
413
|
+
service = getattr(runtime_config, "session_service", None)
|
|
414
|
+
if service is None:
|
|
415
|
+
service = resolve_session_service()
|
|
416
|
+
|
|
417
|
+
agent_id = (
|
|
418
|
+
os.environ.get("KSADK_A2A_AGENT_ID", "").strip()
|
|
419
|
+
or str(getattr(runtime_config, "agent_instance_id", "") or "").strip()
|
|
420
|
+
or os.environ.get("AGENT_INSTANCE_ID", "").strip()
|
|
421
|
+
)
|
|
422
|
+
if not agent_id:
|
|
423
|
+
raise RuntimeError("A2A_AGENT_ID_REQUIRED")
|
|
424
|
+
trusted_tenant = getattr(self.task_adapter, "_trusted_tenant", None)
|
|
425
|
+
user_id = (
|
|
426
|
+
str(trusted_tenant(context) or "").strip()
|
|
427
|
+
if callable(trusted_tenant)
|
|
428
|
+
else str(getattr(getattr(context, "call_context", None), "tenant", "") or "").strip()
|
|
429
|
+
) or "anonymous"
|
|
430
|
+
|
|
431
|
+
existing = await service.get_session_metadata(session_id)
|
|
432
|
+
if existing is None:
|
|
433
|
+
existing = await service.create_session(agent_id, user_id, session_id=session_id)
|
|
434
|
+
if str(getattr(existing, "agent_id", "") or "") != agent_id:
|
|
435
|
+
raise RuntimeError("A2A_SESSION_AGENT_CONFLICT")
|
|
436
|
+
return session_id
|
|
437
|
+
|
|
348
438
|
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
439
|
+
select = getattr(self.task_adapter, "for_context", None)
|
|
440
|
+
if callable(select):
|
|
441
|
+
selected = select(context)
|
|
442
|
+
if selected is not self.task_adapter:
|
|
443
|
+
return await A2ARuntimeExecutor(selected, self.include_reasoning, self.public_tool_policy).cancel(context, event_queue)
|
|
349
444
|
# §7.4:cancel 统一由 adapter 提供。有 RuntimeAdapter → 尊重其 CancelResult,
|
|
350
445
|
# 只有底层真取消(CANCELLED)才把协议 Task 置 canceled;其余状态如实抛
|
|
351
446
|
# TaskNotCancelableError 拒绝,不伪造终态。无 adapter 时底层状态未知,
|
|
@@ -369,9 +464,18 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
369
464
|
raise TaskNotCancelableError(
|
|
370
465
|
message=f"underlying runtime cancel did not apply: {result_value}"
|
|
371
466
|
)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
467
|
+
message = updater.new_agent_message(parts=[Part(text="Request canceled")])
|
|
468
|
+
await updater.cancel(message=message)
|
|
469
|
+
from ksadk.a2a.kernel_task_adapter import ManagedKernelA2ATaskAdapter
|
|
470
|
+
from ksadk.a2a.protocol_errors import _CONFIRMED_KERNEL_CANCEL
|
|
471
|
+
|
|
472
|
+
if (isinstance(self.task_adapter, ManagedKernelA2ATaskAdapter)
|
|
473
|
+
and result == CancelResult.INTERRUPTED_ACTIVE_TURN):
|
|
474
|
+
# This adapter returns only after observing a canonical cancelled fact.
|
|
475
|
+
# Preserve its acknowledgement if the upstream producer closed the queue.
|
|
476
|
+
status = TaskStatus(state=TaskState.TASK_STATE_CANCELED, message=message)
|
|
477
|
+
status.timestamp.GetCurrentTime()
|
|
478
|
+
context.call_context.state[_CONFIRMED_KERNEL_CANCEL] = (context.task_id, status)
|
|
375
479
|
clear_resume_state = getattr(self.task_adapter, "clear_resume_state", None)
|
|
376
480
|
if callable(clear_resume_state):
|
|
377
481
|
result = clear_resume_state(context.task_id or "", context)
|
|
@@ -384,17 +488,29 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
384
488
|
updater: TaskUpdater,
|
|
385
489
|
handle: RunHandle,
|
|
386
490
|
) -> str:
|
|
387
|
-
|
|
491
|
+
stream_started = time.perf_counter()
|
|
492
|
+
run_completed_at: float | None = None
|
|
493
|
+
output_items: dict[tuple[str, str], dict[str, str]] = {}
|
|
494
|
+
output_refs = None
|
|
388
495
|
artifacts = _ArtifactStreamEmitter(updater, str(context.task_id))
|
|
496
|
+
tools = PublicToolActivityProducer(self.public_tool_policy)
|
|
389
497
|
input_required = False
|
|
390
498
|
input_prompt = "Input required"
|
|
391
499
|
checkpoint_id: str | None = None
|
|
392
500
|
call_id: str | None = None
|
|
501
|
+
input_schema: dict[str, Any] | None = None
|
|
502
|
+
interaction_metadata: dict[str, Any] | None = None
|
|
393
503
|
payload_kind: A2AResumePayloadKind = "hitl_answer"
|
|
394
504
|
|
|
395
505
|
async for event in self.task_adapter.stream_task(handle):
|
|
396
506
|
if not isinstance(event, EventEnvelope):
|
|
397
507
|
raise TypeError("RuntimeAdapter.stream must yield RuntimeEvent")
|
|
508
|
+
if getattr(event, "item_kind", None) in {"tool_call", "tool_result"}:
|
|
509
|
+
await artifacts.close()
|
|
510
|
+
await tools.emit(event, updater)
|
|
511
|
+
if isinstance(event, RunCompleted):
|
|
512
|
+
output_refs = event.output_refs
|
|
513
|
+
run_completed_at = time.perf_counter()
|
|
398
514
|
if isinstance(event, RunFailed):
|
|
399
515
|
raise RuntimeError(self._coerce_text(event.error.message))
|
|
400
516
|
if isinstance(event, RunCanceled):
|
|
@@ -406,16 +522,26 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
406
522
|
raise _RunCanceled()
|
|
407
523
|
if isinstance(event, InteractionRequested):
|
|
408
524
|
input_required = True
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
525
|
+
if isinstance(event.request, ApprovalRequest):
|
|
526
|
+
from ksadk.a2a.interaction_wire import approval_metadata
|
|
527
|
+
|
|
528
|
+
interaction_metadata = approval_metadata(event.request)
|
|
529
|
+
payload_kind = "approval_decision"
|
|
530
|
+
call_id = str(event.request.call_id or event.interaction_id or "") or None
|
|
531
|
+
detail = event.request.detail
|
|
532
|
+
if isinstance(detail, dict):
|
|
533
|
+
input_prompt = self._coerce_text(
|
|
534
|
+
detail.get("prompt") or detail.get("message") or input_prompt
|
|
535
|
+
)
|
|
536
|
+
elif isinstance(event.request, StructuredInputRequest):
|
|
537
|
+
interaction_metadata = None
|
|
538
|
+
payload_kind = "hitl_answer"
|
|
539
|
+
call_id = str(event.interaction_id or "") or None
|
|
540
|
+
input_schema = dict(event.request.schema_)
|
|
541
|
+
input_prompt = self._coerce_text(event.request.prompt or input_prompt)
|
|
542
|
+
native_run_id = str(event.source.native_run_id or "").strip()
|
|
543
|
+
if native_run_id:
|
|
544
|
+
checkpoint_id = native_run_id
|
|
419
545
|
continue
|
|
420
546
|
if isinstance(event, ContinuationCreated):
|
|
421
547
|
checkpoint_id = event.continuation_id
|
|
@@ -434,44 +560,76 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
434
560
|
if not text:
|
|
435
561
|
continue
|
|
436
562
|
await artifacts.push(
|
|
437
|
-
"thinking",
|
|
563
|
+
"thinking",
|
|
564
|
+
text,
|
|
565
|
+
replace_snapshot=(event.op == "replace"),
|
|
566
|
+
identity=(event.scope_id, event.item_id),
|
|
438
567
|
)
|
|
439
568
|
continue
|
|
440
569
|
if event.item_kind == "message":
|
|
441
570
|
if not isinstance(event.update, TextContent):
|
|
442
571
|
continue
|
|
443
572
|
text = event.update.text
|
|
444
|
-
if not text:
|
|
573
|
+
if not text and event.op != "replace":
|
|
445
574
|
continue
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
575
|
+
key = (event.scope_id, event.item_id)
|
|
576
|
+
parts = output_items.setdefault(key, {})
|
|
577
|
+
part_id = event.update.part_id
|
|
578
|
+
parts[part_id] = (
|
|
579
|
+
text if event.op == "replace" else parts.get(part_id, "") + text
|
|
580
|
+
)
|
|
581
|
+
replace_snapshot = event.op == "replace" or next(reversed(parts)) != part_id
|
|
582
|
+
await artifacts.push(
|
|
583
|
+
"text",
|
|
584
|
+
"".join(parts.values()) if replace_snapshot else text,
|
|
585
|
+
replace_snapshot=replace_snapshot,
|
|
586
|
+
identity=key,
|
|
587
|
+
)
|
|
452
588
|
continue
|
|
453
589
|
continue
|
|
454
|
-
if isinstance(event, ItemCompleted):
|
|
590
|
+
if isinstance(event, (ItemCompleted, ItemSnapshotReplaced)):
|
|
455
591
|
if event.item_kind == "reasoning":
|
|
456
592
|
if not self.include_reasoning:
|
|
457
593
|
continue
|
|
458
594
|
text = self._snapshot_text(event)
|
|
459
595
|
if not text:
|
|
460
596
|
continue
|
|
461
|
-
await artifacts.push(
|
|
597
|
+
await artifacts.push(
|
|
598
|
+
"thinking",
|
|
599
|
+
text,
|
|
600
|
+
replace_snapshot=True,
|
|
601
|
+
identity=(event.scope_id, event.item_id),
|
|
602
|
+
)
|
|
462
603
|
continue
|
|
463
604
|
if event.item_kind == "message":
|
|
464
|
-
|
|
465
|
-
|
|
605
|
+
key = (event.scope_id, event.item_id)
|
|
606
|
+
parts = {
|
|
607
|
+
part.part_id: part.text
|
|
608
|
+
for part in event.snapshot.parts
|
|
609
|
+
if isinstance(part, TextContent)
|
|
610
|
+
}
|
|
611
|
+
if not parts and key not in output_items:
|
|
466
612
|
continue
|
|
467
|
-
|
|
468
|
-
await artifacts.push(
|
|
613
|
+
output_items[key] = parts
|
|
614
|
+
await artifacts.push(
|
|
615
|
+
"text", "".join(parts.values()), replace_snapshot=True, identity=key
|
|
616
|
+
)
|
|
469
617
|
continue
|
|
470
618
|
continue
|
|
471
619
|
if self._cancel_was_accepted(context, handle):
|
|
472
620
|
await artifacts.close()
|
|
473
621
|
raise _RunCanceled()
|
|
474
622
|
await artifacts.close()
|
|
623
|
+
logger.info(
|
|
624
|
+
"A2A artifact timing task=%s source_updates=%d wire_updates=%d "
|
|
625
|
+
"elapsed_ms=%.1f post_run_terminal_ms=%.1f",
|
|
626
|
+
context.task_id,
|
|
627
|
+
artifacts.source_updates,
|
|
628
|
+
artifacts.wire_updates,
|
|
629
|
+
(time.perf_counter() - stream_started) * 1000,
|
|
630
|
+
((time.perf_counter() - run_completed_at) * 1000)
|
|
631
|
+
if run_completed_at is not None else 0.0,
|
|
632
|
+
)
|
|
475
633
|
if input_required:
|
|
476
634
|
await self.task_adapter.persist_resume_state(
|
|
477
635
|
task_id=str(context.task_id or ""),
|
|
@@ -481,13 +639,27 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
481
639
|
call_id=call_id,
|
|
482
640
|
payload_kind=payload_kind,
|
|
483
641
|
)
|
|
642
|
+
message_metadata = (
|
|
643
|
+
interaction_metadata
|
|
644
|
+
if interaction_metadata is not None
|
|
645
|
+
else ({"input_schema": input_schema} if input_schema is not None else None)
|
|
646
|
+
)
|
|
484
647
|
await updater.update_status(
|
|
485
648
|
TaskState.TASK_STATE_INPUT_REQUIRED,
|
|
486
|
-
message=updater.new_agent_message(
|
|
649
|
+
message=updater.new_agent_message(
|
|
650
|
+
parts=[Part(text=input_prompt)], metadata=message_metadata
|
|
651
|
+
),
|
|
487
652
|
metadata=dict(ADK_V2_INTEGRATION_METADATA),
|
|
488
653
|
)
|
|
489
654
|
raise _InputRequired()
|
|
490
|
-
|
|
655
|
+
if output_refs:
|
|
656
|
+
return "".join(
|
|
657
|
+
output_items.get((ref.scope_id, ref.item_id), {}).get(ref.part_id, "")
|
|
658
|
+
if ref.part_id is not None
|
|
659
|
+
else "".join(output_items.get((ref.scope_id, ref.item_id), {}).values())
|
|
660
|
+
for ref in output_refs
|
|
661
|
+
)
|
|
662
|
+
return "".join(text for parts in output_items.values() for text in parts.values())
|
|
491
663
|
|
|
492
664
|
def _cancel_was_accepted(self, context: RequestContext, handle: RunHandle) -> bool:
|
|
493
665
|
was_cancel_accepted = getattr(self.task_adapter, "was_cancel_accepted", None)
|
|
@@ -504,7 +676,7 @@ class A2ARuntimeExecutor(AgentExecutor):
|
|
|
504
676
|
await result
|
|
505
677
|
|
|
506
678
|
@staticmethod
|
|
507
|
-
def _snapshot_text(event: ItemCompleted) -> str:
|
|
679
|
+
def _snapshot_text(event: ItemCompleted | ItemSnapshotReplaced) -> str:
|
|
508
680
|
"""Extract text from the first TextContent part of an ItemCompleted snapshot."""
|
|
509
681
|
if not event.snapshot.parts:
|
|
510
682
|
return ""
|
ksadk/a2a/exposure.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Compile remote declarations to one conflict-free consumer call surface."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
9
|
+
from typing_extensions import Self
|
|
10
|
+
|
|
11
|
+
from ksadk.a2a.ids import require_a2a_resource_id
|
|
12
|
+
from ksadk.a2a.invocation_types import RemoteAgentSpec
|
|
13
|
+
|
|
14
|
+
ResolvedExposure = Literal["native", "expert_tool", "dynamic_tool"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InvocationExposureEntry(BaseModel):
|
|
18
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
19
|
+
spec: RemoteAgentSpec
|
|
20
|
+
exposure: ResolvedExposure
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class InvocationExposurePlan(BaseModel):
|
|
24
|
+
"""A deterministic local projection, never an authorization token."""
|
|
25
|
+
|
|
26
|
+
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
27
|
+
consumer_id: str
|
|
28
|
+
framework: str
|
|
29
|
+
entries: tuple[InvocationExposureEntry, ...]
|
|
30
|
+
|
|
31
|
+
@model_validator(mode="after")
|
|
32
|
+
def _validate_plan(self) -> Self:
|
|
33
|
+
if not self.consumer_id.strip() or self.consumer_id != self.consumer_id.strip():
|
|
34
|
+
raise ValueError("consumer_id must be non-blank")
|
|
35
|
+
if not self.framework.strip() or self.framework != self.framework.strip():
|
|
36
|
+
raise ValueError("framework must be a non-blank canonical name")
|
|
37
|
+
targets: set[str] = set()
|
|
38
|
+
names: set[str] = set()
|
|
39
|
+
bindings: set[str] = set()
|
|
40
|
+
for entry in self.entries:
|
|
41
|
+
spec = RemoteAgentSpec.model_validate(entry.spec.model_dump())
|
|
42
|
+
if spec.target_agent_id in targets:
|
|
43
|
+
raise ValueError("A2A_EXPOSURE_CONFLICT")
|
|
44
|
+
if spec.local_name in names:
|
|
45
|
+
raise ValueError("A2A_LOCAL_NAME_CONFLICT")
|
|
46
|
+
if spec.binding_id in bindings:
|
|
47
|
+
raise ValueError("A2A_BINDING_ID_CONFLICT")
|
|
48
|
+
targets.add(spec.target_agent_id)
|
|
49
|
+
names.add(spec.local_name)
|
|
50
|
+
bindings.add(spec.binding_id)
|
|
51
|
+
if entry.exposure != _resolve_exposure(spec, self.framework):
|
|
52
|
+
raise ValueError("A2A_EXPOSURE_STRATEGY_MISMATCH")
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def assert_generic_target_allowed(self, target_agent_id: str) -> None:
|
|
56
|
+
require_a2a_resource_id(target_agent_id, "a2a-agent-", field_name="target_agent_id")
|
|
57
|
+
if any(
|
|
58
|
+
entry.spec.target_agent_id == target_agent_id and entry.exposure != "dynamic_tool"
|
|
59
|
+
for entry in self.entries
|
|
60
|
+
):
|
|
61
|
+
raise ValueError("A2A_EXPOSURE_CONFLICT")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _resolve_exposure(spec: RemoteAgentSpec, framework: str) -> ResolvedExposure:
|
|
65
|
+
if spec.expected_version_id is None:
|
|
66
|
+
raise ValueError("A2A_VERSION_PIN_REQUIRED")
|
|
67
|
+
if spec.exposure == "tool":
|
|
68
|
+
return "dynamic_tool"
|
|
69
|
+
if framework in {"adk", "langgraph"}:
|
|
70
|
+
return "native"
|
|
71
|
+
if spec.exposure == "native":
|
|
72
|
+
raise ValueError("A2A_NATIVE_UNSUPPORTED")
|
|
73
|
+
return "expert_tool" if framework == "codex" else "dynamic_tool"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def compile_exposure_plan(
|
|
77
|
+
specs: Sequence[RemoteAgentSpec],
|
|
78
|
+
*,
|
|
79
|
+
framework: str,
|
|
80
|
+
consumer_id: str,
|
|
81
|
+
) -> InvocationExposurePlan:
|
|
82
|
+
if not isinstance(framework, str) or not framework.strip() or framework != framework.strip():
|
|
83
|
+
raise ValueError("framework must be a non-blank canonical name")
|
|
84
|
+
if (
|
|
85
|
+
not isinstance(consumer_id, str)
|
|
86
|
+
or not consumer_id.strip()
|
|
87
|
+
or consumer_id != consumer_id.strip()
|
|
88
|
+
):
|
|
89
|
+
raise ValueError("consumer_id must be non-blank")
|
|
90
|
+
entries = []
|
|
91
|
+
for declaration in specs:
|
|
92
|
+
spec = RemoteAgentSpec.model_validate(declaration.model_dump())
|
|
93
|
+
entries.append(
|
|
94
|
+
InvocationExposureEntry(
|
|
95
|
+
spec=spec,
|
|
96
|
+
exposure=_resolve_exposure(spec, framework),
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
return InvocationExposurePlan(
|
|
100
|
+
consumer_id=consumer_id,
|
|
101
|
+
framework=framework,
|
|
102
|
+
entries=tuple(sorted(entries, key=lambda entry: entry.spec.local_name)),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
__all__ = ["InvocationExposureEntry", "InvocationExposurePlan", "compile_exposure_plan"]
|