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,172 @@
|
|
|
1
|
+
"""Optional host-bound capacity for a returned artifact character page.
|
|
2
|
+
|
|
3
|
+
Selection runs in the effect adapter before sealing. It never mutates storage,
|
|
4
|
+
receipts, permissions, or the model's declared call arguments.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import re
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import Callable
|
|
13
|
+
|
|
14
|
+
from ksadk.harness.native.ports import RunConfiguration, ToolDefinition, ToolRequest, ToolResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ArtifactPageCapacityError(ValueError):
|
|
18
|
+
"""A valid host binding cannot fit this declared source group."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, message, *, source_group_size=None, page_limits=()):
|
|
21
|
+
super().__init__(message)
|
|
22
|
+
self.source_group_size = source_group_size
|
|
23
|
+
self.page_limits = tuple(page_limits)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def capacity_error_content(error: ArtifactPageCapacityError | None = None):
|
|
27
|
+
if error is not None and error.source_group_size is not None:
|
|
28
|
+
limits = set(error.page_limits)
|
|
29
|
+
host_only = limits == {"host_payload_bytes"}
|
|
30
|
+
content = {"code": "artifact_page_budget_unavailable",
|
|
31
|
+
"capacity_scope": ("host_tool_result_payload" if host_only
|
|
32
|
+
else "original_declared_source_call_group")}
|
|
33
|
+
if limits:
|
|
34
|
+
content["page_limits"] = sorted(limits)
|
|
35
|
+
if error.source_group_size > 1 and not host_only:
|
|
36
|
+
content["next_read_shape"] = "fewer_sources_per_call_group"
|
|
37
|
+
return content
|
|
38
|
+
# Compatibility for old policies with no declared-group binding.
|
|
39
|
+
return {"code": "artifact_page_budget_unavailable",
|
|
40
|
+
"capacity_scope": "original_declared_source_call_group",
|
|
41
|
+
"next_read_shape": "fewer_sources_per_call_group"}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class ArtifactPageBudget:
|
|
46
|
+
max_units: int
|
|
47
|
+
max_result_units: int
|
|
48
|
+
count_units: Callable[[str], int]
|
|
49
|
+
max_payload_bytes: int | None = None
|
|
50
|
+
source_group_size: int | None = None
|
|
51
|
+
count_result_message: Callable[[dict], int] | None = None
|
|
52
|
+
admit_result: Callable[[ToolResult], bool] | None = None
|
|
53
|
+
|
|
54
|
+
def __post_init__(self):
|
|
55
|
+
if not callable(self.count_units):
|
|
56
|
+
raise ValueError("artifact_page_counter_unavailable")
|
|
57
|
+
if self.count_result_message is not None and not callable(self.count_result_message):
|
|
58
|
+
raise ValueError("artifact_page_message_counter_invalid")
|
|
59
|
+
if self.admit_result is not None and not callable(self.admit_result):
|
|
60
|
+
raise ValueError("artifact_page_admission_invalid")
|
|
61
|
+
if self.max_payload_bytes is not None and (
|
|
62
|
+
type(self.max_payload_bytes) is not int or self.max_payload_bytes < 1024
|
|
63
|
+
):
|
|
64
|
+
raise ValueError("artifact_page_payload_limit_invalid")
|
|
65
|
+
if self.source_group_size is not None and (
|
|
66
|
+
type(self.source_group_size) is not int or self.source_group_size < 1
|
|
67
|
+
or self.max_payload_bytes is None
|
|
68
|
+
):
|
|
69
|
+
raise ValueError("artifact_page_feedback_binding_invalid")
|
|
70
|
+
invalid = tuple(label for n, label in (
|
|
71
|
+
(self.max_units, "source_group_units"), (self.max_result_units, "result_group_units")
|
|
72
|
+
) if type(n) is not int or n < 1)
|
|
73
|
+
if invalid:
|
|
74
|
+
raise ArtifactPageCapacityError(
|
|
75
|
+
"artifact_page_budget_unavailable", source_group_size=self.source_group_size,
|
|
76
|
+
page_limits=invalid,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def _cost(self, text):
|
|
80
|
+
cost = self.count_units(text)
|
|
81
|
+
if type(cost) is not int or cost < 0 or (text and cost == 0):
|
|
82
|
+
raise ValueError("artifact_page_counter_invalid")
|
|
83
|
+
return cost
|
|
84
|
+
|
|
85
|
+
def _exceeded_limits(self, page: dict, *, check_admission=True) -> tuple[str, ...]:
|
|
86
|
+
# Tool JSON is itself quoted as message text. Charge real escaped
|
|
87
|
+
# source, locator and cursor metadata, not just a character count.
|
|
88
|
+
envelope = json.dumps({"status": "ok", "content": page}, ensure_ascii=False)
|
|
89
|
+
# ArtifactRead returns no content blocks. Include their empty framing
|
|
90
|
+
# nevertheless: outer result governance measures this complete payload,
|
|
91
|
+
# not just the source characters or the model-facing envelope above.
|
|
92
|
+
exceeded = []
|
|
93
|
+
if self._cost(page["content"]) > self.max_units:
|
|
94
|
+
exceeded.append("source_group_units")
|
|
95
|
+
result_cost = (self.count_result_message(page) if self.count_result_message is not None
|
|
96
|
+
else self._cost(json.dumps(envelope, ensure_ascii=False)))
|
|
97
|
+
if type(result_cost) is not int or result_cost < 1:
|
|
98
|
+
raise ValueError("artifact_page_counter_invalid")
|
|
99
|
+
if result_cost > self.max_result_units:
|
|
100
|
+
exceeded.append("result_group_units")
|
|
101
|
+
if self.max_payload_bytes is not None:
|
|
102
|
+
payload = json.dumps(
|
|
103
|
+
{"status": "ok", "content": page, "content_blocks": []},
|
|
104
|
+
ensure_ascii=False, sort_keys=True, separators=(",", ":"),
|
|
105
|
+
)
|
|
106
|
+
if len(payload.encode("utf-8")) > self.max_payload_bytes:
|
|
107
|
+
exceeded.append("host_payload_bytes")
|
|
108
|
+
if (check_admission and self.admit_result is not None
|
|
109
|
+
and self.admit_result(ToolResult(status="ok", content=page)) is not True):
|
|
110
|
+
exceeded.append("next_request_units")
|
|
111
|
+
return tuple(exceeded)
|
|
112
|
+
|
|
113
|
+
def fits(self, page: dict, *, check_admission=True) -> bool:
|
|
114
|
+
return not self._exceeded_limits(page, check_admission=check_admission)
|
|
115
|
+
|
|
116
|
+
def unavailable(self, page: dict, *, check_admission=True) -> ArtifactPageCapacityError:
|
|
117
|
+
return ArtifactPageCapacityError(
|
|
118
|
+
"artifact_page_budget_unavailable", source_group_size=self.source_group_size,
|
|
119
|
+
page_limits=self._exceeded_limits(page, check_admission=check_admission),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def select(self, page: dict) -> dict:
|
|
123
|
+
exceeded = set(self._exceeded_limits(page))
|
|
124
|
+
if not exceeded:
|
|
125
|
+
return dict(page)
|
|
126
|
+
text, offset = page["content"], page["offset_chars"]
|
|
127
|
+
|
|
128
|
+
def prefix(length):
|
|
129
|
+
value = {**page, "content": text[:length], "next_offset_chars": offset + length,
|
|
130
|
+
"complete": page["complete"] and length == len(text)}
|
|
131
|
+
if self.source_group_size is not None:
|
|
132
|
+
value["page_limits"] = sorted(exceeded)
|
|
133
|
+
if self.source_group_size > 1 and exceeded.difference({"host_payload_bytes"}):
|
|
134
|
+
value["next_read_shape"] = "fewer_sources_per_call_group"
|
|
135
|
+
return value
|
|
136
|
+
|
|
137
|
+
while True:
|
|
138
|
+
low, high = 0, len(text)
|
|
139
|
+
while low < high:
|
|
140
|
+
middle = (low + high + 1) // 2
|
|
141
|
+
if self.fits(prefix(middle)):
|
|
142
|
+
low = middle
|
|
143
|
+
else:
|
|
144
|
+
high = middle - 1
|
|
145
|
+
if not low or not self.fits(prefix(low)):
|
|
146
|
+
raise self.unavailable(prefix(min(1, len(text))))
|
|
147
|
+
# Feedback is part of both budgets before sealing. Its framing
|
|
148
|
+
# can activate another constraint; include that cause and repack.
|
|
149
|
+
# The cause set only grows and has at most four members.
|
|
150
|
+
more = set(self._exceeded_limits(prefix(low + 1))) if low < len(text) else set()
|
|
151
|
+
if self.source_group_size is None or more.issubset(exceeded):
|
|
152
|
+
return prefix(low)
|
|
153
|
+
exceeded.update(more)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclass(frozen=True)
|
|
157
|
+
class ArtifactPagePolicy:
|
|
158
|
+
digest: str
|
|
159
|
+
resolve: Callable[[ToolRequest, tuple[ToolDefinition, ...]], ArtifactPageBudget]
|
|
160
|
+
bind_configuration: Callable[[RunConfiguration], ArtifactPagePolicy] | None = None
|
|
161
|
+
|
|
162
|
+
def __post_init__(self):
|
|
163
|
+
if (not isinstance(self.digest, str)
|
|
164
|
+
or not re.fullmatch(r"sha256:[0-9a-f]{64}", self.digest)):
|
|
165
|
+
raise ValueError("artifact_page_policy_identity_invalid")
|
|
166
|
+
if not callable(self.resolve):
|
|
167
|
+
raise ValueError("artifact_page_policy_unavailable")
|
|
168
|
+
if self.bind_configuration is not None and not callable(self.bind_configuration):
|
|
169
|
+
raise ValueError("artifact_page_configuration_binding_invalid")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
__all__ = ["ArtifactPageBudget", "ArtifactPageCapacityError", "ArtifactPagePolicy"]
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"""Bounded literal search of a Run's already earned artifact references.
|
|
2
|
+
|
|
3
|
+
This is the scoped equivalent of searching persisted tool output. It neither
|
|
4
|
+
opens workspace paths nor interprets task semantics or verifies delivery.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import hashlib
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
from ksadk.harness.native.artifact_search_contract import (
|
|
13
|
+
ARTIFACT_SEARCH_DEFINITION as ARTIFACT_SEARCH_DEFINITION,
|
|
14
|
+
)
|
|
15
|
+
from ksadk.harness.native.artifact_search_contract import (
|
|
16
|
+
ARTIFACT_SEARCH_NAME as ARTIFACT_SEARCH_NAME,
|
|
17
|
+
)
|
|
18
|
+
from ksadk.harness.native.ports import (
|
|
19
|
+
ArtifactPort,
|
|
20
|
+
ArtifactReadRequest,
|
|
21
|
+
ToolPort,
|
|
22
|
+
ToolRequest,
|
|
23
|
+
ToolResult,
|
|
24
|
+
)
|
|
25
|
+
from ksadk.harness.native.tool_recovery import query_sealed_tool_result
|
|
26
|
+
from ksadk.tools.captured_source_artifact import CAPTURED_SOURCE_MIME, decode_captured_source
|
|
27
|
+
|
|
28
|
+
from .native_search_budget import search_definition
|
|
29
|
+
|
|
30
|
+
_MAX_SCAN_BYTES = 1024 * 1024
|
|
31
|
+
_MAX_EXCERPT_CHARS = 8192
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _argument_error(args):
|
|
35
|
+
"""Diagnose only public schema constraints, never argument values or keys."""
|
|
36
|
+
def failure(field, constraint, expected, *, items=False):
|
|
37
|
+
return {
|
|
38
|
+
"code": "invalid_artifact_search",
|
|
39
|
+
"constraint": constraint,
|
|
40
|
+
"schema_path": (
|
|
41
|
+
f"/properties/{field}" + ("/items" if items else "") + f"/{constraint}"
|
|
42
|
+
if field and constraint != "required" else f"/{constraint}"
|
|
43
|
+
),
|
|
44
|
+
**({"field": field} if field else {}),
|
|
45
|
+
("expected_type" if constraint == "type" else constraint): expected,
|
|
46
|
+
"instruction": "Correct arguments against this tool schema before retrying.",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if set(args).difference({"uris", "query", "max_matches", "context_chars"}):
|
|
50
|
+
return failure(None, "additionalProperties", False)
|
|
51
|
+
for field in ("uris", "query"):
|
|
52
|
+
if field not in args:
|
|
53
|
+
return failure(field, "required", True)
|
|
54
|
+
uris, query = args["uris"], args["query"]
|
|
55
|
+
if not isinstance(uris, list):
|
|
56
|
+
return failure("uris", "type", "array")
|
|
57
|
+
if not 1 <= len(uris) <= 8:
|
|
58
|
+
return failure("uris", "minItems", 1) if not uris else failure("uris", "maxItems", 8)
|
|
59
|
+
for uri in uris:
|
|
60
|
+
if not isinstance(uri, str):
|
|
61
|
+
return failure("uris", "type", "string", items=True)
|
|
62
|
+
if not uri:
|
|
63
|
+
return failure("uris", "minLength", 1, items=True)
|
|
64
|
+
if len(set(uris)) != len(uris):
|
|
65
|
+
return failure("uris", "uniqueItems", True)
|
|
66
|
+
if not isinstance(query, str):
|
|
67
|
+
return failure("query", "type", "string")
|
|
68
|
+
if not 1 <= len(query) <= 1024:
|
|
69
|
+
return (
|
|
70
|
+
failure("query", "minLength", 1)
|
|
71
|
+
if not query else failure("query", "maxLength", 1024)
|
|
72
|
+
)
|
|
73
|
+
for field, default, low, high in (("max_matches", 16, 1, 16), ("context_chars", 120, 0, 256)):
|
|
74
|
+
value = args.get(field, default)
|
|
75
|
+
if type(value) is not int:
|
|
76
|
+
return failure(field, "type", "integer")
|
|
77
|
+
if value < low:
|
|
78
|
+
return failure(field, "minimum", low)
|
|
79
|
+
if value > high:
|
|
80
|
+
return failure(field, "maximum", high)
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _source(text, mime_type=None):
|
|
85
|
+
"""Decode a known source carrier; its metadata remains untrusted tool data."""
|
|
86
|
+
if mime_type == CAPTURED_SOURCE_MIME:
|
|
87
|
+
source = decode_captured_source(text)
|
|
88
|
+
if source is not None:
|
|
89
|
+
body, path, span = source
|
|
90
|
+
return body, path, span["start"]
|
|
91
|
+
return text, None, None
|
|
92
|
+
try:
|
|
93
|
+
raw = json.loads(text)["content"]
|
|
94
|
+
carrier = raw["requested_source"]
|
|
95
|
+
path, span, body = carrier["path"], carrier["read_range"], carrier["content"]
|
|
96
|
+
if (
|
|
97
|
+
raw.get("ok") is True
|
|
98
|
+
and raw.get("path") == path
|
|
99
|
+
and isinstance(path, str)
|
|
100
|
+
and isinstance(body, str)
|
|
101
|
+
and body
|
|
102
|
+
and isinstance(span, dict)
|
|
103
|
+
and set(span) == {"start", "end"}
|
|
104
|
+
and all(type(v) is int for v in span.values())
|
|
105
|
+
and 1 <= span["start"] <= span["end"]
|
|
106
|
+
and len(body.splitlines()) == span["end"] - span["start"] + 1
|
|
107
|
+
):
|
|
108
|
+
return body, path, span["start"]
|
|
109
|
+
except (ValueError, TypeError, KeyError, AttributeError):
|
|
110
|
+
pass
|
|
111
|
+
return text, None, None
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class NativeArtifactSearchPort:
|
|
115
|
+
def __init__(self, delegate: ToolPort, artifacts: ArtifactPort, *,
|
|
116
|
+
search_policy=None, definitions=()):
|
|
117
|
+
self.delegate, self.artifacts = delegate, artifacts
|
|
118
|
+
self.search_policy, self.definitions = search_policy, definitions
|
|
119
|
+
|
|
120
|
+
async def _query(self, request, method):
|
|
121
|
+
return await query_sealed_tool_result(
|
|
122
|
+
self.delegate,
|
|
123
|
+
request,
|
|
124
|
+
owned_names=(ARTIFACT_SEARCH_NAME,),
|
|
125
|
+
method=method,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
async def reconcile(self, request):
|
|
129
|
+
return await self._query(request, "reconcile")
|
|
130
|
+
|
|
131
|
+
async def recover_prepared(self, request):
|
|
132
|
+
return await self._query(request, "recover_prepared")
|
|
133
|
+
|
|
134
|
+
async def resume_prepared(self, request):
|
|
135
|
+
return await self._query(request, "resume_prepared")
|
|
136
|
+
|
|
137
|
+
async def resume_checkpoint(self, request):
|
|
138
|
+
return await self._query(request, "resume_checkpoint")
|
|
139
|
+
|
|
140
|
+
async def execute(self, request: ToolRequest) -> ToolResult:
|
|
141
|
+
if request.call.name != ARTIFACT_SEARCH_NAME:
|
|
142
|
+
return await self.delegate.execute(request)
|
|
143
|
+
if request.definition != search_definition(self.search_policy):
|
|
144
|
+
return ToolResult(status="error", content={"code": "invalid_artifact_search"})
|
|
145
|
+
args = request.call.arguments
|
|
146
|
+
error = _argument_error(args)
|
|
147
|
+
if error is not None:
|
|
148
|
+
return ToolResult(status="error", content=error)
|
|
149
|
+
uris, query = args.get("uris"), args.get("query")
|
|
150
|
+
limit, context = args.get("max_matches", 16), args.get("context_chars", 120)
|
|
151
|
+
allowed = {ref.uri: ref for ref in request.available_artifacts}
|
|
152
|
+
if any(uri not in allowed for uri in uris):
|
|
153
|
+
return ToolResult(status="error", content={"code": "artifact_not_available"})
|
|
154
|
+
budget = None
|
|
155
|
+
if self.search_policy is not None:
|
|
156
|
+
try:
|
|
157
|
+
budget = self.search_policy.resolve(request, self.definitions)
|
|
158
|
+
except ValueError:
|
|
159
|
+
return ToolResult(
|
|
160
|
+
status="error", content={"code": "artifact_search_capacity_unavailable"},
|
|
161
|
+
)
|
|
162
|
+
results, fingerprints, remaining, characters = [], [], limit, _MAX_EXCERPT_CHARS
|
|
163
|
+
for uri in uris:
|
|
164
|
+
ref = allowed[uri]
|
|
165
|
+
if ref.size_bytes > _MAX_SCAN_BYTES:
|
|
166
|
+
results.append({"uri": uri, "complete": False, "code": "artifact_search_too_large"})
|
|
167
|
+
continue
|
|
168
|
+
try:
|
|
169
|
+
chunks, offset = [], 0
|
|
170
|
+
while True:
|
|
171
|
+
page = await self.artifacts.read(
|
|
172
|
+
ArtifactReadRequest(
|
|
173
|
+
scope=request.scope,
|
|
174
|
+
run_id=request.run_id,
|
|
175
|
+
ref=ref,
|
|
176
|
+
offset_chars=offset,
|
|
177
|
+
limit_chars=32000,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
if (
|
|
181
|
+
page.ref != ref
|
|
182
|
+
or page.offset_chars != offset
|
|
183
|
+
or page.next_offset_chars != offset + len(page.content)
|
|
184
|
+
or len(page.content) > 32000
|
|
185
|
+
or (not page.complete and not page.content)
|
|
186
|
+
):
|
|
187
|
+
raise ValueError("artifact page mismatch")
|
|
188
|
+
chunks.append(page.content)
|
|
189
|
+
offset = page.next_offset_chars
|
|
190
|
+
if offset > _MAX_SCAN_BYTES:
|
|
191
|
+
raise ValueError("artifact scan limit")
|
|
192
|
+
if page.complete:
|
|
193
|
+
break
|
|
194
|
+
text = "".join(chunks)
|
|
195
|
+
encoded = text.encode("utf-8")
|
|
196
|
+
if len(encoded) != ref.size_bytes or (
|
|
197
|
+
"sha256:" + hashlib.sha256(encoded).hexdigest() != ref.content_hash
|
|
198
|
+
):
|
|
199
|
+
raise ValueError("artifact content mismatch")
|
|
200
|
+
except Exception:
|
|
201
|
+
results.append({"uri": uri, "complete": False, "code": "artifact_search_failed"})
|
|
202
|
+
continue
|
|
203
|
+
body, path, start = _source(text, ref.mime_type)
|
|
204
|
+
matches, cursor = [], 0
|
|
205
|
+
while (found := body.find(query, cursor)) >= 0 and remaining and characters:
|
|
206
|
+
excerpt = body[max(0, found - context) : found + len(query) + context]
|
|
207
|
+
clipped = len(excerpt) > characters
|
|
208
|
+
excerpt = excerpt[:characters]
|
|
209
|
+
matches.append(
|
|
210
|
+
{
|
|
211
|
+
"offset_chars": found,
|
|
212
|
+
"excerpt": excerpt,
|
|
213
|
+
"excerpt_truncated": clipped,
|
|
214
|
+
**({"source_line": start + body.count("\n", 0, found)} if start else {}),
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
remaining -= 1
|
|
218
|
+
characters -= len(excerpt)
|
|
219
|
+
cursor = found + len(query)
|
|
220
|
+
complete = body.find(query, cursor) < 0 and not any(
|
|
221
|
+
m["excerpt_truncated"] for m in matches
|
|
222
|
+
)
|
|
223
|
+
item = {
|
|
224
|
+
"uri": uri,
|
|
225
|
+
"matches": matches,
|
|
226
|
+
"complete": complete,
|
|
227
|
+
"coordinate_space": "captured_source" if path else "artifact",
|
|
228
|
+
}
|
|
229
|
+
if path:
|
|
230
|
+
item["source_path"] = path
|
|
231
|
+
results.append(item)
|
|
232
|
+
fingerprints.append([ref.content_hash, query, matches, complete])
|
|
233
|
+
result = ToolResult(
|
|
234
|
+
status="ok",
|
|
235
|
+
content={
|
|
236
|
+
"observation_type": "scoped-artifact-search/v1",
|
|
237
|
+
"query": query,
|
|
238
|
+
"results": results,
|
|
239
|
+
"complete": all(r["complete"] for r in results),
|
|
240
|
+
},
|
|
241
|
+
progress_observation_digest="sha256:"
|
|
242
|
+
+ hashlib.sha256(
|
|
243
|
+
json.dumps(fingerprints, ensure_ascii=False, sort_keys=True).encode()
|
|
244
|
+
).hexdigest()
|
|
245
|
+
if fingerprints
|
|
246
|
+
else None,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
return budget.select(result) if budget is not None else result
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Host-bound, before-seal Search result selection. No artifact mutation."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
from copy import deepcopy
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Callable
|
|
8
|
+
|
|
9
|
+
from ksadk.harness.native.artifact_search_contract import ARTIFACT_SEARCH_DEFINITION
|
|
10
|
+
from ksadk.harness.native.ports import ToolResult
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def digest(value):
|
|
14
|
+
return (
|
|
15
|
+
"sha256:"
|
|
16
|
+
+ hashlib.sha256(json.dumps(value, sort_keys=True, ensure_ascii=False).encode()).hexdigest()
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def search_definition(policy):
|
|
21
|
+
return (
|
|
22
|
+
ARTIFACT_SEARCH_DEFINITION
|
|
23
|
+
if policy is None
|
|
24
|
+
else ARTIFACT_SEARCH_DEFINITION.model_copy(
|
|
25
|
+
update={
|
|
26
|
+
"feedback_profile_digest": digest(
|
|
27
|
+
{
|
|
28
|
+
"search": ARTIFACT_SEARCH_DEFINITION.feedback_profile_digest,
|
|
29
|
+
"capacity": policy.digest,
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class ArtifactSearchPolicy:
|
|
39
|
+
digest: str
|
|
40
|
+
resolve: Callable
|
|
41
|
+
bind_configuration: Callable | None = None
|
|
42
|
+
|
|
43
|
+
def __post_init__(self):
|
|
44
|
+
if (
|
|
45
|
+
not isinstance(self.digest, str)
|
|
46
|
+
or len(self.digest) != 71
|
|
47
|
+
or not self.digest.startswith("sha256:")
|
|
48
|
+
or any(c not in "0123456789abcdef" for c in self.digest[7:])
|
|
49
|
+
or not callable(self.resolve)
|
|
50
|
+
or (self.bind_configuration is not None and not callable(self.bind_configuration))
|
|
51
|
+
):
|
|
52
|
+
raise ValueError("artifact_search_policy_invalid")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True)
|
|
56
|
+
class ArtifactSearchBudget:
|
|
57
|
+
result_message_units: int
|
|
58
|
+
count_result_message: Callable
|
|
59
|
+
max_payload_bytes: int
|
|
60
|
+
|
|
61
|
+
def __post_init__(self):
|
|
62
|
+
if (
|
|
63
|
+
type(self.result_message_units) is not int
|
|
64
|
+
or not callable(self.count_result_message)
|
|
65
|
+
or type(self.max_payload_bytes) is not int
|
|
66
|
+
or not 1024 <= self.max_payload_bytes <= 4 * 1024 * 1024
|
|
67
|
+
):
|
|
68
|
+
raise ValueError("artifact_search_capacity_invalid")
|
|
69
|
+
|
|
70
|
+
def fits(self, result):
|
|
71
|
+
return (
|
|
72
|
+
self.count_result_message(result) <= self.result_message_units
|
|
73
|
+
and len(
|
|
74
|
+
json.dumps(
|
|
75
|
+
{"status": result.status, "content": result.content, "content_blocks": []},
|
|
76
|
+
ensure_ascii=False,
|
|
77
|
+
).encode()
|
|
78
|
+
)
|
|
79
|
+
<= self.max_payload_bytes
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def select(self, result):
|
|
83
|
+
if self.fits(result):
|
|
84
|
+
return result
|
|
85
|
+
content = deepcopy(result.content)
|
|
86
|
+
content["complete"] = False
|
|
87
|
+
content["capacity_limited"] = True
|
|
88
|
+
content["continuation"] = (
|
|
89
|
+
"Complete original bytes remain at these earned URIs (ArtifactRead)."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def candidate():
|
|
93
|
+
content["complete"] = all(row["complete"] for row in content["results"])
|
|
94
|
+
return result.model_copy(
|
|
95
|
+
update={
|
|
96
|
+
"content": deepcopy(content),
|
|
97
|
+
"progress_observation_digest": digest(content),
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Keep the longest tested original excerpt prefix that fits. Each
|
|
102
|
+
# candidate is measured in full; tokenizer costs need not be monotonic.
|
|
103
|
+
# No excerpt is reconstructed or attributed to a different match.
|
|
104
|
+
originals = [
|
|
105
|
+
[m.get("excerpt", "") for m in row.get("matches", ())]
|
|
106
|
+
for row in result.content["results"]
|
|
107
|
+
]
|
|
108
|
+
maximum = max((len(text) for row in originals for text in row), default=0)
|
|
109
|
+
lengths = []
|
|
110
|
+
size = maximum // 2
|
|
111
|
+
while size:
|
|
112
|
+
lengths.append(size)
|
|
113
|
+
size //= 2
|
|
114
|
+
for size in (*lengths, 0):
|
|
115
|
+
for row, texts in zip(content["results"], originals):
|
|
116
|
+
for match, text in zip(row.get("matches", ()), texts):
|
|
117
|
+
if len(text) > size:
|
|
118
|
+
match["excerpt"] = text[:size]
|
|
119
|
+
match["excerpt_truncated"] = True
|
|
120
|
+
row["complete"] = False
|
|
121
|
+
value = candidate()
|
|
122
|
+
if self.fits(value):
|
|
123
|
+
return value
|
|
124
|
+
# Drop only visible matches, retaining each original URI and coordinate
|
|
125
|
+
# system. Empty+complete=false is not a statement that no match exists.
|
|
126
|
+
for row in reversed(content["results"]):
|
|
127
|
+
while row.get("matches"):
|
|
128
|
+
row["matches"].pop()
|
|
129
|
+
row["complete"] = False
|
|
130
|
+
value = candidate()
|
|
131
|
+
if self.fits(value):
|
|
132
|
+
return value
|
|
133
|
+
# The error makes no fit/coverage claim and may leave Context blocked.
|
|
134
|
+
return ToolResult(status="error", content={"code": "artifact_search_capacity_unavailable"})
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Scoped Native adapter over the existing local ArtifactStore."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
|
|
7
|
+
from ksadk.harness.artifact_store import ArtifactStore
|
|
8
|
+
from ksadk.harness.native.adapters import _snapshot
|
|
9
|
+
from ksadk.harness.native.ports import (
|
|
10
|
+
ArtifactReadRequest,
|
|
11
|
+
ArtifactReadResult,
|
|
12
|
+
ArtifactRef,
|
|
13
|
+
ArtifactWriteRequest,
|
|
14
|
+
)
|
|
15
|
+
from ksadk.harness.native.state import RunScope
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NativeArtifactStorePort:
|
|
19
|
+
"""Bind one local store to an authenticated scope without a second ledger."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, store: ArtifactStore, *, scope: RunScope) -> None:
|
|
22
|
+
if not isinstance(store, ArtifactStore):
|
|
23
|
+
raise ValueError("native artifact adapter requires ArtifactStore")
|
|
24
|
+
self._store = store
|
|
25
|
+
self._scope = _snapshot(scope)
|
|
26
|
+
self._scope_key = hashlib.sha256(self._scope.model_dump_json().encode()).hexdigest()[:24]
|
|
27
|
+
|
|
28
|
+
def _run_key(self, run_id: str) -> str:
|
|
29
|
+
digest = hashlib.sha256(run_id.encode()).hexdigest()[:32]
|
|
30
|
+
return f"{self._scope_key}-{digest}"
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def _ref(record) -> ArtifactRef:
|
|
34
|
+
return ArtifactRef(
|
|
35
|
+
uri=record.uri,
|
|
36
|
+
content_hash=record.content_hash,
|
|
37
|
+
size_bytes=record.bytes,
|
|
38
|
+
mime_type=record.mime,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
async def usage_bytes(self, scope: RunScope, run_id: str) -> int:
|
|
42
|
+
"""Count this Run's durable artifacts, including writes before a crash."""
|
|
43
|
+
if _snapshot(scope) != self._scope:
|
|
44
|
+
raise ValueError("artifact scope mismatch")
|
|
45
|
+
return sum(record.bytes for record in self._store.list(self._run_key(run_id)))
|
|
46
|
+
|
|
47
|
+
async def write(self, request: ArtifactWriteRequest) -> ArtifactRef:
|
|
48
|
+
sealed = _snapshot(request)
|
|
49
|
+
if sealed.scope != self._scope:
|
|
50
|
+
raise ValueError("artifact scope mismatch")
|
|
51
|
+
run_key = self._run_key(sealed.run_id)
|
|
52
|
+
identity = hashlib.sha256(
|
|
53
|
+
f"{sealed.operation_key}\0{sealed.tool_call_id}".encode()
|
|
54
|
+
).hexdigest()[:48]
|
|
55
|
+
name = f"tool-result-{identity}"
|
|
56
|
+
encoded = sealed.content.encode("utf-8")
|
|
57
|
+
existing = self._store.latest(run_key, name)
|
|
58
|
+
if existing is not None:
|
|
59
|
+
ref = self._ref(existing)
|
|
60
|
+
if (
|
|
61
|
+
ref.content_hash != "sha256:" + hashlib.sha256(encoded).hexdigest()
|
|
62
|
+
or ref.size_bytes != len(encoded)
|
|
63
|
+
or ref.mime_type != sealed.mime_type
|
|
64
|
+
or self._store.read(existing) != encoded
|
|
65
|
+
):
|
|
66
|
+
raise ValueError("artifact operation identity conflict")
|
|
67
|
+
return ref
|
|
68
|
+
record = self._store.save(
|
|
69
|
+
run_id=run_key,
|
|
70
|
+
name=name,
|
|
71
|
+
content=encoded,
|
|
72
|
+
mime=sealed.mime_type,
|
|
73
|
+
)
|
|
74
|
+
return self._ref(record)
|
|
75
|
+
|
|
76
|
+
async def read(self, request: ArtifactReadRequest) -> ArtifactReadResult:
|
|
77
|
+
sealed = _snapshot(request)
|
|
78
|
+
if sealed.scope != self._scope:
|
|
79
|
+
raise ValueError("artifact scope mismatch")
|
|
80
|
+
# Current-turn writes use a scope-prefixed run key. Inherited refs are
|
|
81
|
+
# allowed only when
|
|
82
|
+
# the runtime placed their exact typed ref in available_artifacts; this
|
|
83
|
+
# adapter still requires the same authenticated scope prefix.
|
|
84
|
+
prefix = f"artifact://{self._scope_key}-"
|
|
85
|
+
if not sealed.ref.uri.startswith(prefix):
|
|
86
|
+
raise ValueError("artifact reference is outside the bound scope")
|
|
87
|
+
records = [
|
|
88
|
+
record
|
|
89
|
+
for record in self._store.list(
|
|
90
|
+
sealed.ref.uri[len("artifact://") :].split("/", 1)[0]
|
|
91
|
+
)
|
|
92
|
+
if record.uri == sealed.ref.uri
|
|
93
|
+
]
|
|
94
|
+
if len(records) != 1 or self._ref(records[0]) != sealed.ref:
|
|
95
|
+
raise ValueError("artifact reference is unknown or changed")
|
|
96
|
+
encoded = self._store.read(records[0])
|
|
97
|
+
if len(encoded) != sealed.ref.size_bytes or (
|
|
98
|
+
"sha256:" + hashlib.sha256(encoded).hexdigest() != sealed.ref.content_hash
|
|
99
|
+
):
|
|
100
|
+
raise ValueError("artifact content integrity mismatch")
|
|
101
|
+
text = encoded.decode("utf-8")
|
|
102
|
+
if sealed.offset_chars > len(text):
|
|
103
|
+
raise ValueError("artifact offset is beyond content")
|
|
104
|
+
content = text[sealed.offset_chars : sealed.offset_chars + sealed.limit_chars]
|
|
105
|
+
next_offset = sealed.offset_chars + len(content)
|
|
106
|
+
return ArtifactReadResult(
|
|
107
|
+
ref=sealed.ref,
|
|
108
|
+
content=content,
|
|
109
|
+
offset_chars=sealed.offset_chars,
|
|
110
|
+
next_offset_chars=next_offset,
|
|
111
|
+
complete=next_offset == len(text),
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
__all__ = ["NativeArtifactStorePort"]
|