agentengine-sdk-python 0.8.4__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.4.dist-info → agentengine_sdk_python-0.8.6.dist-info}/METADATA +17 -10
- agentengine_sdk_python-0.8.6.dist-info/RECORD +1731 -0
- 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/_process.py +83 -0
- ksadk/_str_enum.py +17 -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/a2ui/core.py +3 -3
- ksadk/api/client.py +38 -79
- ksadk/api/sse_stream.py +96 -0
- ksadk/builders/code_builder.py +121 -118
- ksadk/builders/container_builder.py +11 -29
- ksadk/builders/framework_requirements.py +22 -2
- ksadk/builders/managed_runtime_builder.py +12 -0
- ksadk/builders/source_provenance.py +87 -0
- ksadk/cli/__init__.py +36 -0
- ksadk/cli/cmd_a2a.py +43 -0
- ksadk/cli/cmd_build.py +9 -0
- ksadk/cli/cmd_config.py +4 -4
- ksadk/cli/cmd_create.py +12 -12
- ksadk/cli/cmd_deploy.py +27 -2
- ksadk/cli/cmd_hermes.py +24 -2
- ksadk/cli/cmd_invoke.py +64 -88
- ksadk/cli/cmd_openclaw.py +26 -1
- ksadk/cli/cmd_plugin.py +70 -12
- ksadk/cli/cmd_studio.py +69 -17
- ksadk/cli/cmd_web.py +2 -0
- ksadk/cli/hosted_invoke.py +206 -0
- ksadk/cli/invoke_content.py +60 -0
- ksadk/cli/openclaw_env.py +1 -1
- ksadk/cli/resource_common.py +26 -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 -1047
- 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/__init__.py +1 -1
- ksadk/configs/env_registry.py +216 -143
- ksadk/configs/env_registry_a2a.py +173 -0
- ksadk/configs/env_registry_studio.py +134 -0
- ksadk/configs/global_config.py +2 -1
- ksadk/configs/settings.py +9 -3
- ksadk/connector/__init__.py +17 -0
- ksadk/connector/channel.py +477 -0
- ksadk/context_engine/assembler.py +9 -0
- ksadk/context_engine/capabilities.py +52 -4
- ksadk/context_engine/contributors.py +80 -17
- ksadk/context_engine/instruction_authority.py +18 -0
- ksadk/conversations/attachment_storage.py +10 -3
- ksadk/conversations/attachments.py +69 -20
- ksadk/conversations/contracts.py +28 -9
- ksadk/conversations/message_projection.py +51 -155
- ksadk/conversations/message_projection_blocks.py +137 -0
- ksadk/conversations/model_context.py +11 -3
- ksadk/conversations/normalize.py +28 -10
- ksadk/conversations/projector.py +63 -0
- ksadk/conversations/runtime_baseline.py +37 -0
- ksadk/conversations/runtime_compaction.py +7 -2
- ksadk/conversations/runtime_input.py +16 -4
- ksadk/conversations/runtime_invocation.py +17 -4
- ksadk/conversations/runtime_observability.py +39 -10
- ksadk/conversations/runtime_payloads.py +12 -0
- ksadk/conversations/runtime_persistence.py +296 -32
- ksadk/conversations/runtime_preparation.py +98 -13
- ksadk/conversations/runtime_projection.py +217 -0
- ksadk/conversations/runtime_resume.py +141 -70
- ksadk/conversations/runtime_stream_events.py +29 -35
- ksadk/conversations/runtime_streaming.py +8 -0
- 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/_codex_items.py +16 -8
- ksadk/events/adapters/_langgraph_support.py +46 -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/events/session_event.py +2 -2
- ksadk/harness/__init__.py +18 -0
- ksadk/harness/app.py +11 -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 +230 -0
- 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/capabilities.py +115 -0
- ksadk/harness/capability_adapters/__init__.py +1 -0
- ksadk/harness/capability_adapters/native_dsh.py +289 -0
- ksadk/harness/capability_runtime.py +332 -0
- ksadk/harness/closure_contract.py +92 -0
- ksadk/harness/compaction_record.py +153 -0
- ksadk/harness/compiler.py +284 -0
- ksadk/harness/config.py +28 -5
- ksadk/harness/conformance/__init__.py +33 -0
- ksadk/harness/conformance/contract.py +504 -0
- ksadk/harness/conformance/fixtures.py +102 -0
- ksadk/harness/context_engine.py +388 -0
- ksadk/harness/context_maintenance.py +259 -0
- ksadk/harness/context_manifest.py +188 -0
- ksadk/harness/context_sections.py +397 -0
- ksadk/harness/context_tuning.py +168 -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/draft_runtime.py +322 -0
- ksadk/harness/engine/__init__.py +40 -0
- ksadk/harness/engine/base.py +122 -0
- ksadk/harness/engine/budgets.py +108 -0
- ksadk/harness/engine/capability_declarations.py +59 -0
- ksadk/harness/engine/completion_guard.py +57 -0
- ksadk/harness/engine/context_pipeline.py +1351 -0
- ksadk/harness/engine/graph_builder.py +352 -0
- ksadk/harness/engine/hooked_reasoner.py +380 -0
- ksadk/harness/engine/langgraph.py +1049 -0
- ksadk/harness/engine/mcp_disclosure.py +701 -0
- 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 +81 -0
- ksadk/harness/engine/postgres_checkpointer.py +386 -0
- ksadk/harness/engine/run_control_bridge.py +100 -0
- ksadk/harness/engine/run_types.py +98 -0
- ksadk/harness/engine/skill_disclosure.py +275 -0
- ksadk/harness/engine/spans.py +41 -0
- ksadk/harness/engine/steering.py +177 -0
- ksadk/harness/engine/subagents.py +360 -0
- ksadk/harness/engine/thread_ids.py +112 -0
- ksadk/harness/engine/tool_dispatch.py +249 -0
- ksadk/harness/event_tree.py +212 -0
- ksadk/harness/events.py +498 -0
- ksadk/harness/execution_policy.py +104 -0
- ksadk/harness/hooks.py +259 -0
- ksadk/harness/insights.py +210 -0
- ksadk/harness/lifecycle.py +578 -0
- ksadk/harness/lifecycle_conformance.py +233 -0
- ksadk/harness/lifecycle_local_plane.py +104 -0
- ksadk/harness/loop/__init__.py +44 -0
- ksadk/harness/loop/reason.py +699 -0
- ksadk/harness/loop/tools.py +907 -0
- ksadk/harness/managed_runtime.py +1044 -0
- ksadk/harness/mcp_disclosure_contract.py +85 -0
- ksadk/harness/mcp_matrix.py +474 -0
- ksadk/harness/mcp_result_policy.py +44 -0
- ksadk/harness/mcp_runtime.py +504 -0
- ksadk/harness/memory_consolidation.py +157 -0
- ksadk/harness/memory_loop.py +156 -0
- ksadk/harness/memory_runtime.py +541 -0
- ksadk/harness/metrics.py +90 -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 +468 -0
- ksadk/harness/model_provider.py +430 -0
- 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/observability/__init__.py +29 -0
- ksadk/harness/observability/inspection.py +528 -0
- ksadk/harness/observability/metrics.py +167 -0
- ksadk/harness/observability/otel_exporter.py +218 -0
- ksadk/harness/progress_adapters/__init__.py +5 -0
- ksadk/harness/progress_adapters/native_todo.py +75 -0
- ksadk/harness/prompt_cache.py +132 -0
- ksadk/harness/public_activity.py +213 -0
- ksadk/harness/public_output.py +30 -0
- ksadk/harness/public_summary.py +36 -0
- ksadk/harness/readiness.py +249 -0
- ksadk/harness/reasoner.py +779 -17
- ksadk/harness/release_readiness.py +140 -0
- ksadk/harness/resource_ref.py +69 -0
- ksadk/harness/rpc.py +200 -0
- ksadk/harness/run_control.py +773 -0
- ksadk/harness/runtime.py +157 -113
- ksadk/harness/runtime_capabilities.py +228 -0
- ksadk/harness/runtime_server.py +514 -0
- ksadk/harness/sandbox_adapters.py +739 -0
- ksadk/harness/sandbox_backend.py +733 -0
- ksadk/harness/sandbox_conformance.py +288 -0
- ksadk/harness/sandbox_lease.py +77 -0
- ksadk/harness/sandbox_lease_conformance.py +259 -0
- ksadk/harness/sandbox_matrix.py +170 -0
- ksadk/harness/sandbox_reconciliation.py +140 -0
- ksadk/harness/sandbox_recovery.py +586 -0
- ksadk/harness/sandbox_recovery_conformance.py +246 -0
- ksadk/harness/sdk.py +153 -0
- ksadk/harness/session_store.py +589 -0
- 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_composition.py +212 -0
- ksadk/harness/skill_feedback.py +123 -0
- ksadk/harness/skill_intent.py +47 -0
- ksadk/harness/skill_matrix.py +233 -0
- ksadk/harness/skill_runtime.py +317 -0
- ksadk/harness/spec.py +342 -0
- ksadk/harness/state.py +155 -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/strategies.py +149 -0
- ksadk/harness/subagent.py +263 -0
- 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 +134 -0
- ksadk/harness/tool_receipts.py +96 -0
- ksadk/harness/tool_reliability.py +81 -0
- ksadk/harness/tool_result_policy.py +216 -0
- ksadk/harness/tools.py +52 -0
- ksadk/harness/user_errors.py +69 -0
- ksadk/harness/working_context.py +81 -0
- ksadk/harness/working_context_patch.py +99 -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/identity/resolver.py +18 -0
- ksadk/interaction/__init__.py +1 -1
- ksadk/interaction/ledger.py +1 -1
- ksadk/interaction/provider.py +1 -1
- ksadk/interaction/providers/__init__.py +3 -1
- ksadk/interaction/providers/adk.py +1 -1
- ksadk/interaction/providers/codex.py +1 -1
- ksadk/interaction/providers/harness.py +50 -0
- ksadk/interaction/providers/langgraph.py +9 -2
- ksadk/kernel/__init__.py +10 -0
- ksadk/kernel/approval_presentation.py +91 -0
- ksadk/kernel/authorization.py +1 -1
- ksadk/kernel/bootstrap.py +220 -252
- ksadk/kernel/contract_fingerprints.py +45 -1
- ksadk/kernel/contracts.py +30 -0
- ksadk/kernel/control.py +180 -29
- ksadk/kernel/execution_grants.py +428 -0
- ksadk/kernel/execution_grants_memory.py +252 -0
- ksadk/kernel/execution_grants_postgres.py +395 -0
- ksadk/kernel/execution_grants_sqlite.py +435 -0
- ksadk/kernel/execution_host_ingress.py +1071 -0
- ksadk/kernel/history_projection.py +120 -0
- ksadk/kernel/ingress.py +139 -226
- ksadk/kernel/ingress_bootstrap.py +268 -0
- ksadk/kernel/legacy_history.py +179 -0
- ksadk/kernel/mapping.py +1 -1
- ksadk/kernel/memory_store.py +61 -58
- ksadk/kernel/memory_store_projection.py +63 -0
- ksadk/kernel/postgres_event_log.py +181 -0
- ksadk/kernel/postgres_store.py +230 -231
- ksadk/kernel/readiness.py +125 -0
- ksadk/kernel/recovery.py +166 -16
- ksadk/kernel/recovery_projection.py +124 -0
- ksadk/kernel/runtime_checkpoint.py +34 -0
- ksadk/kernel/sql/001_agent_kernel.sql +28 -0
- ksadk/kernel/sqlite_schema.py +100 -0
- ksadk/kernel/sqlite_store.py +410 -200
- ksadk/kernel/state.py +2 -3
- ksadk/kernel/store.py +104 -5
- 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 +369 -340
- ksadk/kernel/worker_controls.py +454 -0
- ksadk/kernel/worker_history.py +72 -0
- ksadk/kernel/worker_identity.py +74 -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/coordinator.py +22 -6
- ksadk/memory/extraction.py +159 -7
- ksadk/memory/models.py +77 -1
- ksadk/memory/provider_resolver.py +5 -0
- ksadk/memory/providers/local_candidates.py +183 -0
- ksadk/memory/providers/local_postgres.py +200 -0
- ksadk/memory/providers/local_sqlite.py +280 -67
- ksadk/memory/resolved_policy.py +12 -7
- ksadk/memory/retrieval.py +189 -0
- ksadk/memory/store_adapter.py +150 -0
- 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_policy.py +2 -2
- ksadk/model_proxy/compat.py +670 -0
- ksadk/model_proxy/detect.py +254 -0
- ksadk/model_proxy/server.py +14 -9
- ksadk/model_proxy/transform.py +72 -6
- ksadk/plugins/__init__.py +1 -1
- ksadk/plugins/bridges/dsh.py +29 -20
- ksadk/plugins/bridges/dsh_profile_manifest.py +36 -0
- ksadk/plugins/builtin_resources.py +199 -0
- ksadk/plugins/builtins.py +417 -185
- ksadk/plugins/companion_artifacts.py +83 -0
- ksadk/plugins/companions.py +368 -0
- ksadk/plugins/context_contributor.py +15 -4
- ksadk/plugins/contracts.py +1 -1
- ksadk/plugins/dsh_channels.py +156 -0
- ksadk/plugins/dsh_dependency_policy.py +41 -0
- ksadk/plugins/dsh_home.py +140 -0
- ksadk/plugins/dsh_teams.py +105 -0
- ksadk/plugins/dsh_toolchain.py +92 -21
- ksadk/plugins/execution_host.py +107 -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-channels-client/client.js +19 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/index.mjs +7 -0
- ksadk/plugins/providers/bundles/dsh-channels-client/package.json +12 -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-client/client.js +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/index.mjs +11 -0
- ksadk/plugins/providers/bundles/dsh-teams-client/package.json +35 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/index.mjs +13 -0
- ksadk/plugins/providers/bundles/dsh-teams-leader-policy/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/index.mjs +12 -0
- ksadk/plugins/providers/bundles/dsh-teams-profile/package.json +26 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-router/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/index.mjs +16 -0
- ksadk/plugins/providers/bundles/dsh-teams-tasks/package.json +27 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/index.mjs +25 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/package.json +29 -0
- ksadk/plugins/providers/bundles/dsh-teams-tools/tools.json +235 -0
- ksadk/plugins/providers/bundles/ksadk-codex/index.mjs +1 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +51 -1
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +2 -2
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/client.mjs +133 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-companion-host/index.mjs +14 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/client.js +27 -4
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +9 -5
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
- ksadk/plugins/providers/codex.py +52 -40
- ksadk/plugins/providers/codex_native.py +20 -0
- ksadk/plugins/providers/codex_skills.py +46 -0
- ksadk/plugins/providers/dsh_capabilities.py +49 -143
- ksadk/plugins/providers/dsh_connector_lease.py +225 -0
- ksadk/plugins/providers/dsh_mcp.py +163 -1
- ksadk/plugins/providers/harness.py +413 -52
- ksadk/plugins/providers/harness_context.py +61 -0
- ksadk/plugins/providers/harness_contributions.py +241 -0
- ksadk/plugins/providers/harness_delegation.py +670 -0
- ksadk/plugins/providers/harness_hooks.py +121 -0
- ksadk/plugins/providers/harness_managed.py +550 -0
- ksadk/plugins/providers/harness_tools.py +455 -0
- 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/providers/shipped_dsh.py +4 -1
- ksadk/plugins/subagent_providers/codex.py +28 -6
- ksadk/plugins/teams/__init__.py +5 -0
- ksadk/plugins/teams/api.py +405 -0
- ksadk/plugins/teams/application.py +540 -0
- ksadk/plugins/teams/artifacts.py +60 -0
- 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/context.py +96 -0
- ksadk/plugins/teams/contracts.py +136 -0
- ksadk/plugins/teams/domain.py +1480 -0
- ksadk/plugins/teams/domain_values.py +24 -0
- ksadk/plugins/teams/effect_contracts.py +255 -0
- ksadk/plugins/teams/errors.py +13 -0
- ksadk/plugins/teams/execution_projection.py +255 -0
- ksadk/plugins/teams/leader_decisions.py +106 -0
- ksadk/plugins/teams/migration.py +311 -0
- ksadk/plugins/teams/migration_cli.py +322 -0
- ksadk/plugins/teams/postgres_store.py +352 -0
- ksadk/plugins/teams/release_contracts.py +60 -0
- ksadk/plugins/teams/runtime.py +853 -0
- ksadk/plugins/teams/source_projection.py +84 -0
- ksadk/plugins/teams/store.py +519 -0
- ksadk/plugins/teams/task_decisions.py +436 -0
- ksadk/plugins/teams/tool_service.py +152 -0
- ksadk/plugins/teams/transport.py +96 -0
- ksadk/plugins/teams/workspaces.py +255 -0
- 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 +83 -401
- ksadk/runners/_langgraph_state_reader.py +106 -0
- ksadk/runners/_langgraph_tool_projection.py +86 -0
- ksadk/runners/_langgraph_tools_transformer.py +27 -0
- ksadk/runners/_session_identity.py +285 -0
- ksadk/runners/adk_runner.py +220 -350
- ksadk/runners/base_runner.py +6 -5
- ksadk/runners/langgraph_runner.py +208 -195
- ksadk/runners/patch_langchain.py +47 -0
- ksadk/runners/usage_accumulator.py +11 -3
- 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 +134 -129
- ksadk/runtime/adapter.py +40 -3
- ksadk/runtime/conversation_execution.py +29 -3
- ksadk/runtime/executor.py +105 -7
- ksadk/runtime/factory.py +45 -3
- ksadk/runtime/framework_adapters.py +184 -10
- ksadk/runtime/hosted_finalizer.py +4 -6
- ksadk/runtime/launch.py +2 -0
- ksadk/runtime/preprocessing.py +11 -3
- ksadk/runtime/runner_adapter.py +160 -21
- ksadk/runtime/skill_eval_result.py +36 -0
- ksadk/runtime/timing.py +46 -0
- ksadk/runtime/usage.py +49 -18
- ksadk/runtime_context.py +105 -1
- ksadk/sandbox/backends/e2b.py +272 -24
- ksadk/sandbox/backends/local_process.py +73 -39
- ksadk/sandbox/base.py +62 -1
- ksadk/sandbox/diagnostics.py +82 -0
- ksadk/sandbox/e2b_connection.py +9 -1
- ksadk/sandbox/local_controls.py +776 -0
- ksadk/sandbox/local_launcher.py +124 -0
- ksadk/scheduler/dispatcher.py +1 -1
- ksadk/server/factory.py +178 -25
- ksadk/server/history_deadline.py +158 -0
- ksadk/server/history_page_cache.py +129 -0
- ksadk/server/invocation_identity.py +118 -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/common.py +32 -3
- ksadk/server/routes/control.py +112 -9
- ksadk/server/routes/dependencies.py +2 -1
- ksadk/server/routes/display_projection.py +154 -0
- ksadk/server/routes/kernel_ingress.py +26 -3
- ksadk/server/routes/misc.py +331 -33
- ksadk/server/routes/models.py +28 -4
- ksadk/server/routes/openai_compat.py +82 -13
- ksadk/server/routes/projection.py +159 -216
- ksadk/server/routes/run.py +112 -37
- ksadk/server/routes/sessions.py +493 -358
- ksadk/server/routes/streaming.py +68 -15
- ksadk/server/routes/tool_receipt_claim_routes.py +107 -0
- ksadk/server/routes/workspace.py +135 -23
- ksadk/server/static/assets/{ArtifactsPanel-CGbWlMNh.js → ArtifactsPanel-CILaW-fC.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-b4C7upmO.js → CodeBlock-BVrNVtJC.js} +10 -7
- ksadk/server/static/assets/MathMessageMarkdown-Dp7c4wWD.js +8 -0
- ksadk/server/static/assets/{MermaidBlock-BEBN4Ksz.js → MermaidBlock-Dxop8Rd7.js} +9 -9
- ksadk/server/static/assets/{NativeTerminalPanel-zvL-WpAn.js → NativeTerminalPanel-Cjjz8B30.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-BYafW7Za.js → abnfDiagram-VCTEODGH-ckWDmOzw.js} +1 -1
- ksadk/server/static/assets/{arc-bTohInsS.js → arc-DqxJede-.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-pn_DuLy6.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-Ch5Lbzsi.js → architectureDiagram-5GKGNRK7-SEQA4bVi.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-kqF4MDOG.js → blockDiagram-NRAW4CY4-pM0B-6NJ.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-8uSRIODv.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-DkhehZDr.js → chunk-5VM5RSS4-GJHDr9Ww.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-BdXhtPe9.js → chunk-F27PBJKO-CbAN45AV.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-DPTpvpwi.js → chunk-G27WJ6UU-D5ngbbzF.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-Pqoh38el.js → chunk-JWPE2WC7-Cc5IwuYC.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-DeU00qC-.js → chunk-LCL6LL3I-CprgDDdJ.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CzxScFkr.js → chunk-POPQ4Y6H-CDZhSy82.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-DpqMx-ux.js → chunk-RHFEMEQ7-CZchUNro.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-C6t0SypQ.js → chunk-SVP7TREG-BVruqk6T.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-DVaeafZk.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-Bf9D3tzJ.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-B9cY3iTz.js → cynefinDiagram-5FMLGOSQ-BIyq3EJb.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-CSwlx3CB.js → dagre-3AP2YEHR-eBw08Qdk.js} +1 -1
- ksadk/server/static/assets/{dagre-UBpgon5q.js → dagre-DfvnEf45.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-C9akhN9a.js → diagram-S7CK7UJ4-CUSrE3Mg.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-CgedhTPI.js → diagram-UQ7AKVKN-Dq5Zw2gy.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-Cjucz5BY.js → diagram-VSXAHHWV-DyUHfNwT.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-Dd4Vleyn.js → diagram-VX7I27RA-CREmM89O.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-CZ2jGtYW.js → diagram-Z3DM3KII-Dw9zhHUK.js} +1 -1
- ksadk/server/static/assets/{dist-Bj730Ib4.js → dist-0uJ4tdx6.js} +1 -1
- ksadk/server/static/assets/{dist-BnaTiyzN.js → dist-AEv-vXf-.js} +1 -1
- ksadk/server/static/assets/{dist-BgV_owcB.js → dist-B49GzZDb.js} +1 -1
- ksadk/server/static/assets/{dist-D_ctSS2i.js → dist-B8Myiet9.js} +1 -1
- ksadk/server/static/assets/{dist-ufY3F5p6.js → dist-BBsYarrI.js} +2 -2
- ksadk/server/static/assets/{dist-ClYUxfeK.js → dist-BQMrUwdI.js} +1 -1
- ksadk/server/static/assets/{dist-CFzsn6BG.js → dist-BX_-FENW.js} +1 -1
- ksadk/server/static/assets/{dist-B3FR1SKK.js → dist-CD4L6ymH.js} +1 -1
- ksadk/server/static/assets/{dist-Cf125P_m.js → dist-CHpW1BHj.js} +1 -1
- ksadk/server/static/assets/{dist-DVCOWtha.js → dist-CVPau3tn.js} +1 -1
- ksadk/server/static/assets/{dist-DFD6Qa6T.js → dist-C_qdxcSH.js} +1 -1
- ksadk/server/static/assets/{dist-BIr4DSRq.js → dist-Co68Apq4.js} +1 -1
- ksadk/server/static/assets/{dist-DiixqL0J.js → dist-Cp2PaOMY.js} +1 -1
- ksadk/server/static/assets/{dist-fBO2v5Kt.js → dist-CuR5Bgme.js} +1 -1
- ksadk/server/static/assets/{dist-DoVSwoDb.js → dist-DDSyLEOX.js} +1 -1
- ksadk/server/static/assets/{dist-C5_ZAZsG.js → dist-DUxO0R99.js} +1 -1
- ksadk/server/static/assets/{dist-C1NMAY5a.js → dist-QzbGrED_.js} +1 -1
- ksadk/server/static/assets/dist-bupkyEBZ.js +1 -0
- ksadk/server/static/assets/{dist-DvFK7p5S.js → dist-cxTGfdqx.js} +1 -1
- ksadk/server/static/assets/{dist-CB9iJrvg.js → dist-hL5p1til.js} +1 -1
- ksadk/server/static/assets/{dist-btbmmX5O.js → dist-lOy23y43.js} +1 -1
- ksadk/server/static/assets/{dist-QfkEHOlb.js → dist-pq-nD33R.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-Ci8NqqZu.js → ebnfDiagram-PWID7BFC-BS5LdNoR.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CCIOhLZG.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-Cp_r9Hb6.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-Dlhc8Wr8.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-CO0rRTRA.js → infoDiagram-RXCK75RN-C1kEtv2y.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CHiaedSS.js → ishikawaDiagram-5VMMS53U-BCNPyMka.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-CHcCIB09.js → journeyDiagram-EYS64GPL--cDbKnjP.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CJ_ebBZf.js → kanban-definition-3QL26DDD-R1rAVw2f.js} +1 -1
- ksadk/server/static/assets/{katex-B4weu383.js → katex-BT-X-V7U.js} +1 -1
- ksadk/server/static/assets/{linear-V-MgYHW1.js → linear-DTR631iG.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-CBijEX_c.js → mermaid-parser.core-DfFzJhX8.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-Bc-pQvpp.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-D7genGLl.js → pegDiagram-XKGWAZYB-xWXPEh0c.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-hwiz6fbw.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-Bxj32zwD.js → pieDiagram-E7YTZNPT-BudBDlCI.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-BURv2mGh.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-CCsh3avW.js → railroadDiagram-O6MQD6OU-BdAYRYB8.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-_FRRBKEd.js → requirementDiagram-EFPCY7ZU-CBBmaL70.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-C-gr2o9M.js → sankeyDiagram-P5KCCOFB-Doc3rdwp.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-D97NmfKg.js → sequenceDiagram-WJ2MYXX4-0J8R8hWW.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DjrPC5FX.js → sizeCapture-X5ZJPWSS-CfFLlWsK.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-DzMNg1hh.js → stateDiagram-HBIQ2CUA-jBwkjtTy.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-Cw1fPb5w.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-Cssf_CsU.js → swimlanes-XN3QIQJK-B0WxTQf8.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-Cc3JMBAF.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-BWTHzyS1.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-BSKgJsmR.js → vennDiagram-4TSXK5OY-9gX1VMDC.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-DokNktqB.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-eflHNoaZ.js → wardleyDiagram-VM6X3IG4-sEs_BP6O.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-eYqrQ-v4.js → xychartDiagram-S5SC5T6Z-Ll4jvUN9.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +34 -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/invocation_identity.py +235 -0
- 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/__init__.py +26 -0
- ksadk/skills/events.py +464 -0
- ksadk/skills/loader.py +44 -2
- ksadk/skills/manifest_cache.py +263 -0
- ksadk/skills/mcp_server/__init__.py +0 -0
- ksadk/skills/mcp_server/_registry.py +33 -0
- ksadk/skills/mcp_server/_routing.py +26 -0
- ksadk/skills/mcp_server/_workspace_files.py +160 -0
- ksadk/skills/mcp_server/register.py +415 -0
- ksadk/skills/mcp_server/server.py +218 -0
- ksadk/skills/models.py +11 -0
- ksadk/skills/observability.py +132 -0
- ksadk/skills/package_store.py +75 -2
- ksadk/skills/runtime/agent.py +38 -5
- ksadk/skills/runtime/artifacts.py +87 -0
- ksadk/skills/runtime/backends/e2b.py +400 -56
- ksadk/skills/runtime/backends/local.py +621 -119
- ksadk/skills/runtime/base.py +78 -7
- ksadk/skills/runtime/executor.py +266 -1
- ksadk/skills/runtime/loader.py +108 -3
- ksadk/skills/runtime/request.py +18 -0
- ksadk/skills/service_client.py +6 -1
- ksadk/skills/tool_defs.py +108 -3
- 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 +784 -419
- 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 +31 -2
- ksadk/studio/api_plugin_routes.py +39 -12
- ksadk/studio/api_resource_connections.py +79 -41
- ksadk/studio/attachment_store.py +14 -2
- ksadk/studio/authoring.py +12 -6
- ksadk/studio/authoring_coordinator.py +4 -2
- ksadk/studio/build_resolution.py +117 -0
- ksadk/studio/build_singleflight.py +37 -0
- ksadk/studio/builder.py +32 -2
- ksadk/studio/capabilities.py +31 -9
- ksadk/studio/channel_connections.py +333 -0
- ksadk/studio/cloud.py +113 -387
- ksadk/studio/cloud_gateways.py +424 -0
- ksadk/studio/cloud_shared_web.py +82 -2
- ksadk/studio/codex_agent_service.py +19 -2
- ksadk/studio/codex_builder.py +1 -1
- ksadk/studio/codex_manifest.py +5 -1
- ksadk/studio/codex_provider_build.py +65 -0
- ksadk/studio/codex_run.py +6 -1
- ksadk/studio/compiler.py +112 -6
- ksadk/studio/configuration.py +182 -0
- ksadk/studio/contract_base.py +19 -0
- ksadk/studio/contracts.py +260 -202
- ksadk/studio/dsh_application.py +183 -27
- ksadk/studio/dsh_capability_service.py +302 -189
- ksadk/studio/dsh_lifecycle.py +58 -0
- ksadk/studio/dsh_mcp_transport.py +191 -0
- ksadk/studio/dsh_provider_registration.py +55 -16
- ksadk/studio/entry.py +53 -0
- ksadk/studio/event_store.py +53 -5
- ksadk/studio/execution_host.py +598 -0
- ksadk/studio/framework_run.py +50 -10
- ksadk/studio/hosted_kernel.py +1 -1
- ksadk/studio/interaction_submission.py +265 -0
- ksadk/studio/kernel_registry.py +429 -0
- ksadk/studio/kernel_sqlite_migration.py +181 -0
- 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 +1939 -345
- ksadk/studio/model_content_stream.py +129 -0
- ksadk/studio/model_credentials.py +196 -0
- ksadk/studio/model_profile_service.py +89 -40
- 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_documents.py +172 -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 +39 -12
- ksadk/studio/plugin_kernel_adapter.py +89 -0
- ksadk/studio/plugin_lifecycle.py +80 -0
- ksadk/studio/plugin_native_activation.py +163 -0
- ksadk/studio/plugin_runtime.py +832 -99
- ksadk/studio/plugin_runtime_admission.py +57 -0
- ksadk/studio/presentation.py +92 -0
- ksadk/studio/provider_recovery.py +59 -0
- ksadk/studio/public_output_store.py +69 -0
- ksadk/studio/recovery_page.py +70 -0
- ksadk/studio/resource_authority.py +69 -34
- ksadk/studio/resource_catalog.py +14 -12
- ksadk/studio/run_activity.py +848 -0
- ksadk/studio/run_controls.py +185 -0
- ksadk/studio/run_documents.py +127 -0
- ksadk/studio/run_service.py +1220 -335
- ksadk/studio/run_submission_receipts.py +68 -0
- ksadk/studio/runtime_catalog.py +73 -11
- ksadk/studio/runtime_prewarm.py +22 -0
- ksadk/studio/runtime_source.py +1 -1
- ksadk/studio/scheduler_assistant.py +4 -1
- ksadk/studio/scheduler_runtime.py +32 -289
- ksadk/studio/service.py +615 -246
- ksadk/studio/service_settings.py +229 -0
- ksadk/studio/shared_web.py +518 -181
- 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-CkufcPYo.js +44 -0
- ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-DYG1Wzbx.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
- ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-BeyLyQHu.js +59 -0
- ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
- ksadk/studio/static/assets/TeamsPage-CCaaGaVp.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
- ksadk/studio/static/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-5Zn1gqJv.js +36 -0
- ksadk/studio/static/assets/{blockDiagram-I7D4REHJ-CFmPl1de.js → blockDiagram-I7D4REHJ-CLB4L11u.js} +6 -6
- ksadk/studio/static/assets/{c4Diagram-7LVT6UL2-BRrGu8qt.js → c4Diagram-7LVT6UL2-BOma_Z_F.js} +7 -7
- ksadk/studio/static/assets/channel-r8itPEik.js +1 -0
- ksadk/studio/static/assets/chunk-2E4U76K2-BFf_huql.js +2 -0
- ksadk/studio/static/assets/chunk-2ZTRR5NV-C2qZJila.js +2 -0
- ksadk/studio/static/assets/chunk-3Z5EZCMW-DMniOlPd.js +1 -0
- ksadk/studio/static/assets/{chunk-4HAMMTFA-D220vUtq.js → chunk-4HAMMTFA-DVtDP4rm.js} +7 -7
- ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
- ksadk/studio/static/assets/chunk-6AZGARVD-BB6FqMl-.js +1 -0
- ksadk/studio/static/assets/chunk-6EIED4P4-DdUJkP0f.js +1 -0
- ksadk/studio/static/assets/chunk-6K3QC6MW-CqVsVn-y.js +1 -0
- ksadk/studio/static/assets/chunk-6TQVIW2G-DKlLbNIP.js +1 -0
- ksadk/studio/static/assets/chunk-747NJXEK-BFkZPlab.js +2 -0
- ksadk/studio/static/assets/chunk-75Z2AOVW-BZNhM4vB.js +2 -0
- ksadk/studio/static/assets/chunk-CLGD4ZFX-D-GTtyKs.js +1 -0
- ksadk/studio/static/assets/{chunk-DU6HZSFF-C4DtVpCu.js → chunk-DU6HZSFF-CpEZCUgg.js} +1 -1
- ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
- ksadk/studio/static/assets/{chunk-GMAD6QVW-DiQA-u2N.js → chunk-GMAD6QVW-DE_8H717.js} +6 -6
- ksadk/studio/static/assets/chunk-GVQU2GXP-BfEB0lNv.js +1 -0
- ksadk/studio/static/assets/chunk-I5DQTOEV-Hm2LfiYI.js +1 -0
- ksadk/studio/static/assets/chunk-ICYGCRZG-749o-pGJ.js +1 -0
- ksadk/studio/static/assets/chunk-IH6LHLGP-CC6I9F3i.js +1 -0
- ksadk/studio/static/assets/{chunk-IMKFNOWR-BSlbjT_b.js → chunk-IMKFNOWR-D38axYOR.js} +5 -5
- ksadk/studio/static/assets/chunk-KI3K4JFJ-Rma-0k_M.js +1 -0
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Dq5xn7aL.js +1 -0
- ksadk/studio/static/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
- ksadk/studio/static/assets/{chunk-OSK3NFVY-M2m6G3j4.js → chunk-OSK3NFVY-DiCQjx9b.js} +5 -5
- ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
- ksadk/studio/static/assets/{chunk-P2QGCYS3-DezaQxiK.js → chunk-P2QGCYS3-VdhKmfYq.js} +1 -1
- ksadk/studio/static/assets/chunk-POPQ4Y6H-C1_rzO5M.js +1 -0
- ksadk/studio/static/assets/chunk-PWAF6VOD-B45HvflI.js +1 -0
- ksadk/studio/static/assets/{chunk-SHT3W25Y-DAyIVp5H.js → chunk-SHT3W25Y-DsCFnRVE.js} +9 -9
- ksadk/studio/static/assets/{chunk-SVP7TREG-DulomOrS.js → chunk-SVP7TREG-DljApgRX.js} +1 -1
- ksadk/studio/static/assets/{chunk-TICWLB2K-bHJYoflj.js → chunk-TICWLB2K-DWqRtyqa.js} +6 -6
- ksadk/studio/static/assets/chunk-TLUHSLCS-DUeGgnD5.js +2 -0
- ksadk/studio/static/assets/chunk-UY3FDG6J-CnmaAkG5.js +1 -0
- ksadk/studio/static/assets/chunk-XHIXRSVI-BFQ6B8BE.js +1 -0
- ksadk/studio/static/assets/chunk-XXDRQBXY-DqAYeljN.js +1 -0
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-DjeMNJmu.js +1 -0
- ksadk/studio/static/assets/clsx-DB0hHKMi.js +1 -0
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-om8AY0Mc.js +1 -0
- ksadk/studio/static/assets/createLucideIcon-DR0LGTP5.js +1 -0
- ksadk/studio/static/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-6BrmK52S.js +62 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
- ksadk/studio/static/assets/{diagram-S7CK7UJ4-0BZ98mya.js → diagram-S7CK7UJ4-C6aH78c4.js} +3 -3
- ksadk/studio/static/assets/diagram-UQ7AKVKN-DY_tQ6C_.js +41 -0
- ksadk/studio/static/assets/diagram-VSXAHHWV-DX9p5cQT.js +3 -0
- ksadk/studio/static/assets/diagram-VX7I27RA-DB2WSH8X.js +24 -0
- ksadk/studio/static/assets/diagram-Z3DM3KII-Ce1BJwHE.js +24 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
- ksadk/studio/static/assets/{erDiagram-RLTQ6QDP-DLGry2Ap.js → erDiagram-RLTQ6QDP-CGthTMmJ.js} +6 -6
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
- ksadk/studio/static/assets/flowDiagram-HODETNUW-CZ1tEenp.js +1 -0
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BfoAZW9X.js +292 -0
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-S985OIJF.js +106 -0
- ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
- ksadk/studio/static/assets/index-C7DNDik2.css +2 -0
- ksadk/studio/static/assets/index-Cy68gTlH.js +265 -0
- ksadk/studio/static/assets/index.dom-BQenBtFm.js +1 -0
- ksadk/studio/static/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-CO3W8tFn.js +2 -0
- ksadk/studio/static/assets/{ishikawaDiagram-5VMMS53U-CljI2wyf.js → ishikawaDiagram-5VMMS53U-BUGEl8cO.js} +2 -2
- ksadk/studio/static/assets/{journeyDiagram-3NMN7TZE-D50Fo2sL.js → journeyDiagram-3NMN7TZE-Ch2ZYxvr.js} +6 -6
- ksadk/studio/static/assets/{kanban-definition-UXKFOSKX-DimfOTam.js → kanban-definition-UXKFOSKX-Da-Fp4vC.js} +3 -3
- ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
- ksadk/studio/static/assets/{line-CX5BOOUP.js → line-BDaeq300.js} +1 -1
- ksadk/studio/static/assets/linear-DmucvK78.js +1 -0
- ksadk/studio/static/assets/mermaid-parser.core-Cj5mYdBi.js +4 -0
- ksadk/studio/static/assets/{mindmap-definition-YA3MSWOX-Bizzqy5R.js → mindmap-definition-YA3MSWOX-CvlsVQ38.js} +1 -1
- ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-BuHuNgT5.js +1 -0
- ksadk/studio/static/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
- ksadk/studio/static/assets/{pieDiagram-E7YTZNPT-B9mrFSDF.js → pieDiagram-E7YTZNPT-DlrWiSOv.js} +1 -1
- ksadk/studio/static/assets/preload-helper-CO68xz6u.js +1 -0
- ksadk/studio/static/assets/presentation-yYw7xK60-BmcZriri.js +1 -0
- ksadk/studio/static/assets/{quadrantDiagram-AXDQQJYC-NzUfCbMR.js → quadrantDiagram-AXDQQJYC-BA3hpUZM.js} +6 -6
- ksadk/studio/static/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
- ksadk/studio/static/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-BxpAazym.js +1 -0
- ksadk/studio/static/assets/{requirementDiagram-BXWQKSXE-BF3d103U.js → requirementDiagram-BXWQKSXE-E-Ge0FcV.js} +1 -1
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
- ksadk/studio/static/assets/{sequenceDiagram-WJ2MYXX4-Dh4wZtUm.js → sequenceDiagram-WJ2MYXX4-CcElXGg4.js} +9 -9
- ksadk/studio/static/assets/src-B6xuSHsQ.js +1 -0
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DdXZOFqY.js +1 -0
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-CJbOM-QK.js +1 -0
- ksadk/studio/static/assets/swimlanes-42K2YHIH-NtgEEHLY.js +1 -0
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-D-AVlW8B.js +8 -0
- ksadk/studio/static/assets/{timeline-definition-24CTP7MA-DxmSSjRB.js → timeline-definition-24CTP7MA-CIuYhNy3.js} +7 -7
- ksadk/studio/static/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
- ksadk/studio/static/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-7HbApbrv.js +34 -0
- ksadk/studio/static/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
- ksadk/studio/static/assets/{wardleyDiagram-VM6X3IG4-Ba1AOWoe.js → wardleyDiagram-VM6X3IG4-CMJiaedy.js} +1 -1
- ksadk/studio/static/assets/{xychartDiagram-S5SC5T6Z-Cr5pt5Y-.js → xychartDiagram-S5SC5T6Z-BdgtMvW2.js} +6 -6
- ksadk/studio/static/index.html +8 -2
- ksadk/studio/teams_catalog.py +166 -0
- ksadk/studio/teams_installation.py +217 -0
- ksadk/studio/teams_node.py +549 -0
- ksadk/studio/teams_node_factory.py +558 -0
- ksadk/studio/teams_node_runner.py +72 -0
- ksadk/studio/teams_node_v1.py +935 -0
- ksadk/studio/teams_remote.py +496 -0
- ksadk/studio/templates.py +41 -19
- ksadk/studio/validator.py +13 -0
- ksadk/studio/workspace.py +19 -4
- ksadk/studio/workspace_plugins.py +138 -0
- ksadk/studio/workspace_registry.py +286 -0
- 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 +93 -88
- ksadk/toolsets/a2a.py +89 -89
- ksadk/toolsets/sandbox.py +377 -6
- ksadk/toolsets/skill_management.py +315 -0
- ksadk/toolsets/skills.py +446 -378
- ksadk/toolsets/tool_selection.py +94 -0
- ksadk/toolsets/workspace.py +344 -326
- ksadk/toolsets/workspace_editing.py +291 -0
- ksadk/toolsets/workspace_identity.py +15 -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/memory_backend/providers/lancedb.py +56 -2
- ksadk_runtime_common/schemas/memory_backend_manifest.schema.json +148 -148
- ksadk_runtime_common/workspace_files/router.py +28 -14
- agentengine_sdk_python-0.8.4.dist-info/RECORD +0 -1070
- ksadk/server/static/assets/MathMessageMarkdown-DbdW5A4_.js +0 -8
- ksadk/server/static/assets/architecture-7GRP2DOG-BW5UtSnx.js +0 -1
- ksadk/server/static/assets/channel-CF5Up3hQ.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-KkXX47WI.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Cz81acRQ.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Cz81acRQ.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-DVWs8a2t.js +0 -1
- ksadk/server/static/assets/dist-B2_CVgKv.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-CQqR2hg3.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-DDRRbGPm.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-fgWEf7UD.js +0 -1
- ksadk/server/static/assets/index-DcTML1Up.css +0 -2
- ksadk/server/static/assets/index-Dh2XHqPK.js +0 -244
- ksadk/server/static/assets/info-A6RAGUB7-BUecLTdt.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BeW-btFv.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-X0xh4SaT.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-DzRMSqjd.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Cc44icX-.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-D6S4BdV-.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-vD3aVE2o.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CYbW_b4T.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BIcjKFhF.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-tq3K3Ybl.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-DBXt3GdU.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-DrCy4E_l.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-CefhOliM.js +0 -1
- ksadk/studio/static/assets/CodeBlock-DCUUY0PL-BLjA7kbS.js +0 -41
- ksadk/studio/static/assets/MathMessageMarkdown-CBcDrAw--CUYIXwgI.js +0 -8
- ksadk/studio/static/assets/MermaidBlock-DBFTztfQ-BTYKWEbD.js +0 -44
- ksadk/studio/static/assets/PrismRenderer-wiXRHURw.js +0 -3
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-CLETGjKq.js +0 -1
- ksadk/studio/static/assets/architecture-7GRP2DOG-hXMiO_AU.js +0 -1
- ksadk/studio/static/assets/architectureDiagram-5GKGNRK7-B5EQysk6.js +0 -36
- ksadk/studio/static/assets/channel-BqO-gtEw.js +0 -1
- ksadk/studio/static/assets/chunk-75Z2AOVW-C8lLv_qc.js +0 -2
- ksadk/studio/static/assets/chunk-F27PBJKO-Cpw14SNG.js +0 -1
- ksadk/studio/static/assets/chunk-GVQU2GXP-DUdNBUCi.js +0 -1
- ksadk/studio/static/assets/chunk-L3NEJ4N5-Db8Ab22W.js +0 -1
- ksadk/studio/static/assets/chunk-POPQ4Y6H-DOpufJ3t.js +0 -1
- ksadk/studio/static/assets/chunk-PWAF6VOD-CfLb1gSc.js +0 -1
- ksadk/studio/static/assets/chunk-XXDRQBXY-7PcdR2B1.js +0 -1
- ksadk/studio/static/assets/classDiagram-ZZMXUADV-D_bW8JjA.js +0 -1
- ksadk/studio/static/assets/classDiagram-v2-VYDZK3BY-D_bW8JjA.js +0 -1
- ksadk/studio/static/assets/cose-bilkent-JH36ORCC-snL88wkX.js +0 -1
- ksadk/studio/static/assets/cynefin-OW5HDTMX-Bd1YhRo1.js +0 -1
- ksadk/studio/static/assets/cynefinDiagram-5FMLGOSQ-BBrIG_mI.js +0 -62
- ksadk/studio/static/assets/dagre-GXQ25YYZ-DtF1nGdY.js +0 -4
- ksadk/studio/static/assets/diagram-UQ7AKVKN-6mLKEo6L.js +0 -41
- ksadk/studio/static/assets/diagram-VSXAHHWV-CJBIaiZ2.js +0 -3
- ksadk/studio/static/assets/diagram-VX7I27RA-BohLEE1C.js +0 -24
- ksadk/studio/static/assets/diagram-Z3DM3KII-D8KIGonG.js +0 -24
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-C99HU61t.js +0 -1
- ksadk/studio/static/assets/eventmodeling-NTZA5JFV-B1_5Ac8j.js +0 -1
- ksadk/studio/static/assets/flowDiagram-HODETNUW-DD5hmicn.js +0 -1
- ksadk/studio/static/assets/ganttDiagram-EL5Y4UJY-BPJrVLSG.js +0 -292
- ksadk/studio/static/assets/gitGraph-4MIJSDKK-Cy_ZQBGi.js +0 -1
- ksadk/studio/static/assets/gitGraphDiagram-WWUBYQGX-CZCUz4MT.js +0 -106
- ksadk/studio/static/assets/index-CeHL9ARV.css +0 -2
- ksadk/studio/static/assets/index-D9QEcVpL.js +0 -320
- ksadk/studio/static/assets/info-A6RAGUB7-DBzDQB_I.js +0 -1
- ksadk/studio/static/assets/infoDiagram-27XIBGKW-B-sq07Hi.js +0 -2
- ksadk/studio/static/assets/linear-BCxN9JLv.js +0 -1
- ksadk/studio/static/assets/mermaid-parser.core-BdCz8fkS.js +0 -7
- ksadk/studio/static/assets/packet-AYTQ26CC-gPln-_kG.js +0 -1
- ksadk/studio/static/assets/pegDiagram-XKGWAZYB-Dy3fB-gW.js +0 -1
- ksadk/studio/static/assets/pie-WAS4IAKB-qZdHMr7B.js +0 -1
- ksadk/studio/static/assets/radar-RG4KPBEZ-BZlnaea9.js +0 -1
- ksadk/studio/static/assets/railroad-74A4TZTK-Ce3__H9c.js +0 -1
- ksadk/studio/static/assets/railroad-abnf-HS5TGJTU-DqQn7EzD.js +0 -1
- ksadk/studio/static/assets/railroad-ebnf-LZEXJU2U-B55kCA8F.js +0 -1
- ksadk/studio/static/assets/railroad-peg-WCYAUIDC-DfQnvkHd.js +0 -1
- ksadk/studio/static/assets/railroadDiagram-O6MQD6OU-DnhMjZCk.js +0 -1
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-Bo-JTwt0.js +0 -40
- ksadk/studio/static/assets/src-SFn9St9H.js +0 -1
- ksadk/studio/static/assets/stateDiagram-D77RDMKH-DH774G6d.js +0 -1
- ksadk/studio/static/assets/stateDiagram-v2-MP3YSRHH-DZvVWPBo.js +0 -1
- ksadk/studio/static/assets/swimlanes-42K2YHIH-Bl13OvTX.js +0 -1
- ksadk/studio/static/assets/swimlanesDiagram-VR7AAH4N-BnFOTALJ.js +0 -8
- ksadk/studio/static/assets/treeView-Q6P3EWNA-D5Nn9Swz.js +0 -1
- ksadk/studio/static/assets/treemap-WGGIJYW6-CgHgnQhE.js +0 -1
- ksadk/studio/static/assets/vennDiagram-4TSXK5OY-B9QEXcJq.js +0 -34
- ksadk/studio/static/assets/wardley-WFR3VGLG-DXrK2RRY.js +0 -1
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.6.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.6.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.6.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.4.dist-info → agentengine_sdk_python-0.8.6.dist-info}/top_level.txt +0 -0
- /ksadk/studio/static/assets/{MathMessageMarkdown-CBcDrAw--BEOyPC3w.css → MathMessageMarkdown-BesSeCYl-BEOyPC3w.css} +0 -0
ksadk/studio/api.py
CHANGED
|
@@ -4,18 +4,25 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import base64
|
|
7
|
+
import hashlib
|
|
7
8
|
import hmac
|
|
8
9
|
import json
|
|
10
|
+
import logging
|
|
9
11
|
import os
|
|
10
12
|
import secrets
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
11
16
|
from collections.abc import AsyncIterator
|
|
12
17
|
from contextlib import asynccontextmanager
|
|
13
18
|
from pathlib import Path
|
|
14
19
|
from typing import Any, Literal
|
|
20
|
+
from urllib.parse import quote
|
|
15
21
|
|
|
22
|
+
import httpx
|
|
16
23
|
from fastapi import FastAPI, File, Header, Query, Request, Response, UploadFile
|
|
17
24
|
from fastapi.exceptions import RequestValidationError
|
|
18
|
-
from fastapi.responses import FileResponse, JSONResponse, StreamingResponse
|
|
25
|
+
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse, StreamingResponse
|
|
19
26
|
from fastapi.staticfiles import StaticFiles
|
|
20
27
|
from starlette.background import BackgroundTask
|
|
21
28
|
|
|
@@ -26,13 +33,17 @@ from ksadk.conversations.contracts import (
|
|
|
26
33
|
validate_conversation_input,
|
|
27
34
|
)
|
|
28
35
|
from ksadk.conversations.projector import project_conversation_item
|
|
36
|
+
from ksadk.conversations.runtime_payloads import extract_responses_resume_input
|
|
29
37
|
from ksadk.events.canonical import parse_runtime_event_lenient
|
|
30
38
|
from ksadk.scheduler.contracts import ScheduledTask
|
|
39
|
+
from ksadk.studio.api_a2a_routes import register_a2a_routes
|
|
31
40
|
from ksadk.studio.api_catalog_routes import register_catalog_routes
|
|
32
41
|
from ksadk.studio.api_contracts import (
|
|
33
42
|
AgentScheduleRequest,
|
|
34
43
|
AuthoringCommitRequest,
|
|
35
44
|
BuildRequest,
|
|
45
|
+
CancelChildRequest,
|
|
46
|
+
ChildInputRequest,
|
|
36
47
|
CloudAgentVersionRollbackRequest,
|
|
37
48
|
CloudChatInteractionSubmitRequest,
|
|
38
49
|
CloudChatMessageRequest,
|
|
@@ -42,12 +53,15 @@ from ksadk.studio.api_contracts import (
|
|
|
42
53
|
CreateAgentRequest,
|
|
43
54
|
ImportRootRequest,
|
|
44
55
|
InteractionSubmitRequest,
|
|
56
|
+
LinkedDirectoryRequest,
|
|
45
57
|
ProjectInspectRequest,
|
|
58
|
+
PromoteChildRequest,
|
|
46
59
|
PromptCompileRequest,
|
|
47
60
|
QuickAuthoringRequest,
|
|
48
61
|
RollbackRequest,
|
|
49
62
|
RunRequest,
|
|
50
63
|
SessionExchangeRequest,
|
|
64
|
+
SteerRunRequest,
|
|
51
65
|
StudioEvaluationCreate,
|
|
52
66
|
ValidationRequest,
|
|
53
67
|
WorkspaceOpenRequest,
|
|
@@ -79,6 +93,11 @@ from ksadk.studio.api_helpers import (
|
|
|
79
93
|
from ksadk.studio.api_memory_routes import register_memory_routes
|
|
80
94
|
from ksadk.studio.api_plugin_routes import register_plugin_routes
|
|
81
95
|
from ksadk.studio.api_resource_connections import register_resource_connection_routes
|
|
96
|
+
from ksadk.studio.channel_connections import (
|
|
97
|
+
CHANNEL_ACTIONS,
|
|
98
|
+
ChannelAgentConnectionInput,
|
|
99
|
+
ChannelConnectionSettings,
|
|
100
|
+
)
|
|
82
101
|
from ksadk.studio.cloud_shared_web import CloudSharedWebBridge, cloud_chat_target, is_cloud_agent_id
|
|
83
102
|
from ksadk.studio.codex_manifest import CodexAgentManifest
|
|
84
103
|
from ksadk.studio.contracts import (
|
|
@@ -90,8 +109,24 @@ from ksadk.studio.contracts import (
|
|
|
90
109
|
OperationStatus,
|
|
91
110
|
)
|
|
92
111
|
from ksadk.studio.errors import StudioError
|
|
112
|
+
from ksadk.studio.native_documents import (
|
|
113
|
+
NativeDocumentActionRequest,
|
|
114
|
+
document_metadata,
|
|
115
|
+
is_local_desktop_request,
|
|
116
|
+
perform_document_action,
|
|
117
|
+
)
|
|
118
|
+
from ksadk.studio.run_activity import register_activity_routes
|
|
119
|
+
from ksadk.studio.run_documents import read_document
|
|
93
120
|
from ksadk.studio.service import StudioService
|
|
94
121
|
from ksadk.studio.shared_web import StudioSharedWebBridge
|
|
122
|
+
from ksadk.studio.workspace_registry import (
|
|
123
|
+
LinkedDirectoryPolicy,
|
|
124
|
+
WorkspaceRegistry,
|
|
125
|
+
WorkspaceRuntimeManager,
|
|
126
|
+
)
|
|
127
|
+
from ksadk.version import __version__ as _sdk_version
|
|
128
|
+
|
|
129
|
+
logger = logging.getLogger(__name__)
|
|
95
130
|
|
|
96
131
|
_WRITE_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
|
|
97
132
|
_PUBLIC_API_PATHS = {
|
|
@@ -105,107 +140,38 @@ _LOCAL_HOSTS = {"127.0.0.1", "::1", "localhost", "testserver"}
|
|
|
105
140
|
# convention. This is a narrow transport normalizer, not a provider payload
|
|
106
141
|
# rewrite: only fields owned by the frozen RuntimeEvent envelope/content
|
|
107
142
|
# contracts are translated before strict parsing.
|
|
108
|
-
|
|
109
|
-
"schemaVersion": "schema_version",
|
|
110
|
-
"eventId": "event_id",
|
|
111
|
-
"runId": "run_id",
|
|
112
|
-
"runSeq": "run_seq",
|
|
113
|
-
"scopeId": "scope_id",
|
|
114
|
-
"parentScopeId": "parent_scope_id",
|
|
115
|
-
"eventType": "event_type",
|
|
116
|
-
"itemId": "item_id",
|
|
117
|
-
"itemKind": "item_kind",
|
|
118
|
-
"interactionId": "interaction_id",
|
|
119
|
-
"interactionKind": "interaction_kind",
|
|
120
|
-
"continuationId": "continuation_id",
|
|
121
|
-
"resumeAttemptId": "resume_attempt_id",
|
|
122
|
-
"outputRefs": "output_refs",
|
|
123
|
-
"inputTokens": "input_tokens",
|
|
124
|
-
"outputTokens": "output_tokens",
|
|
125
|
-
"totalTokens": "total_tokens",
|
|
126
|
-
"cachedTokens": "cached_tokens",
|
|
127
|
-
"reasoningTokens": "reasoning_tokens",
|
|
128
|
-
}
|
|
129
|
-
_SOURCE_WIRE_ALIASES = {
|
|
130
|
-
"nativeEventId": "native_event_id",
|
|
131
|
-
"nativeCursor": "native_cursor",
|
|
132
|
-
"nativeRunId": "native_run_id",
|
|
133
|
-
"nativeItemId": "native_item_id",
|
|
134
|
-
}
|
|
135
|
-
_CONTENT_WIRE_ALIASES = {
|
|
136
|
-
"contentType": "content_type",
|
|
137
|
-
"partId": "part_id",
|
|
138
|
-
"callId": "call_id",
|
|
139
|
-
"artifactId": "artifact_id",
|
|
140
|
-
"mimeType": "mime_type",
|
|
141
|
-
"isError": "is_error",
|
|
142
|
-
}
|
|
143
|
+
import re as _re
|
|
143
144
|
|
|
145
|
+
from ksadk.studio.api_cloud_chat_routes import _normalize_cloud_runtime_event_wire, _cloud_event_conversation_item, register_cloud_chat_routes
|
|
144
146
|
|
|
145
|
-
|
|
146
|
-
"""Normalize only historic REST casing at the RuntimeEvent boundary."""
|
|
147
|
+
from ksadk.studio.api_cloud_chat_routes import _RUNTIME_EVENT_WIRE_ALIASES, _SOURCE_WIRE_ALIASES, _CONTENT_WIRE_ALIASES
|
|
147
148
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
normalized["source"] = {
|
|
152
|
-
_SOURCE_WIRE_ALIASES.get(key, key): item for key, item in source.items()
|
|
153
|
-
}
|
|
149
|
+
# 内容 hash 文件名(如 index-CQj_Jm9z.js)可安全 immutable 强缓存;
|
|
150
|
+
# index.html 与动态 HTML 仍需每次校验。
|
|
151
|
+
_HASHED_ASSET_RE = _re.compile(r"-[A-Za-z0-9_]{8,}\.(js|css|woff2?|ttf|png|svg|webp|mp4|wasm)$")
|
|
154
152
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
)
|
|
177
|
-
"""Project a complete cloud RuntimeEvent without inventing a browser item.
|
|
178
|
-
|
|
179
|
-
Cloud SessionEvent history has a compatibility envelope around the runtime
|
|
180
|
-
payload. Keep the source event untouched, but add the same typed
|
|
181
|
-
ConversationItem that local Studio streams use whenever the nested event
|
|
182
|
-
validates against RuntimeEvent/v2. A malformed or older envelope is still
|
|
183
|
-
observable to diagnostics, never guessed into an actionable chat card.
|
|
184
|
-
"""
|
|
185
|
-
|
|
186
|
-
payload = event.get("payload") if isinstance(event.get("payload"), dict) else event
|
|
187
|
-
content = payload.get("content") if isinstance(payload.get("content"), dict) else {}
|
|
188
|
-
candidates = (
|
|
189
|
-
content.get("runtime_event"),
|
|
190
|
-
content.get("runtimeEvent"),
|
|
191
|
-
payload.get("runtime_event"),
|
|
192
|
-
payload.get("runtimeEvent"),
|
|
193
|
-
event.get("runtime_event"),
|
|
194
|
-
event.get("runtimeEvent"),
|
|
195
|
-
)
|
|
196
|
-
raw_event = next((candidate for candidate in candidates if isinstance(candidate, dict)), None)
|
|
197
|
-
if raw_event is None:
|
|
198
|
-
return None
|
|
199
|
-
try:
|
|
200
|
-
runtime_event = parse_runtime_event_lenient(_normalize_cloud_runtime_event_wire(raw_event))
|
|
201
|
-
item = project_conversation_item(
|
|
202
|
-
runtime_event, # type: ignore[arg-type]
|
|
203
|
-
session_id=session_id,
|
|
204
|
-
run_id=runtime_event.run_id,
|
|
205
|
-
)
|
|
206
|
-
except (TypeError, ValueError):
|
|
207
|
-
return None
|
|
208
|
-
return item.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
153
|
+
|
|
154
|
+
def _cache_control_for(path: str, response: Any) -> str:
|
|
155
|
+
if path.startswith(("/api/", "/v1/")):
|
|
156
|
+
return "no-store"
|
|
157
|
+
if _HASHED_ASSET_RE.search(path) and 200 <= response.status_code < 300:
|
|
158
|
+
return "public, max-age=31536000, immutable"
|
|
159
|
+
return response.headers.get("Cache-Control", "no-cache")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
_PYPI_LATEST_URL = "https://pypi.org/pypi/ksadk/json"
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _version_key(value: str) -> tuple[int, ...]:
|
|
166
|
+
parts = [int(piece) for piece in value.split(".") if piece.isdigit()]
|
|
167
|
+
return tuple(parts) or (0,)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
async def _fetch_latest_ksadk_version() -> str:
|
|
171
|
+
async with httpx.AsyncClient(timeout=httpx.Timeout(6.0)) as client:
|
|
172
|
+
response = await client.get(_PYPI_LATEST_URL)
|
|
173
|
+
response.raise_for_status()
|
|
174
|
+
return str(response.json()["info"]["version"])
|
|
209
175
|
|
|
210
176
|
|
|
211
177
|
def create_studio_app(
|
|
@@ -216,21 +182,114 @@ def create_studio_app(
|
|
|
216
182
|
csrf_token: str | None = None,
|
|
217
183
|
security_enabled: bool = True,
|
|
218
184
|
) -> FastAPI:
|
|
219
|
-
|
|
185
|
+
initial_service = service or StudioService(root)
|
|
186
|
+
studio = WorkspaceRuntimeManager(
|
|
187
|
+
initial_service, lambda workspace_root: StudioService(workspace_root)
|
|
188
|
+
)
|
|
220
189
|
session_secret = session_token or secrets.token_urlsafe(32)
|
|
221
190
|
csrf_secret = csrf_token or secrets.token_urlsafe(24)
|
|
191
|
+
session_cookie_name = "agentkit_studio_session_" + hashlib.sha256(
|
|
192
|
+
session_secret.encode("utf-8")
|
|
193
|
+
).hexdigest()[:16]
|
|
194
|
+
legacy_session_cookie_name = "agentkit_studio_session"
|
|
222
195
|
|
|
223
196
|
@asynccontextmanager
|
|
224
197
|
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
|
|
198
|
+
lazy_desktop_start = os.environ.get("KSADK_STUDIO_LAZY_START") == "1"
|
|
199
|
+
warmups: set[asyncio.Task[None]] = set()
|
|
200
|
+
|
|
201
|
+
def schedule_runtime_warmup(runtime: StudioService) -> None:
|
|
202
|
+
async def warm_runtime() -> None:
|
|
203
|
+
try:
|
|
204
|
+
await runtime.start()
|
|
205
|
+
except Exception:
|
|
206
|
+
# Runtime warmup is best effort; core Studio remains usable
|
|
207
|
+
# while optional DSH capability discovery is unavailable.
|
|
208
|
+
return
|
|
209
|
+
# The Channel UI is a wheel-owned client bundle. Bootstrap it
|
|
210
|
+
# after the listener is available and through the same Profile
|
|
211
|
+
# maintenance fence used by other DSH mutations.
|
|
212
|
+
if (
|
|
213
|
+
os.environ.get("KSADK_STUDIO_CHANNEL_DEFAULT", "1")
|
|
214
|
+
.strip()
|
|
215
|
+
.lower()
|
|
216
|
+
not in {"0", "false", "no", "off"}
|
|
217
|
+
and not os.environ.get("KSADK_DSH_HOME", "").strip()
|
|
218
|
+
and not os.environ.get("KSADK_DSH_PROFILE", "").strip()
|
|
219
|
+
):
|
|
220
|
+
try:
|
|
221
|
+
from ksadk.plugins.dsh_channels import (
|
|
222
|
+
channel_default_bootstrap_needed,
|
|
223
|
+
configure_channel_profile,
|
|
224
|
+
)
|
|
225
|
+
from ksadk.studio.api_plugin_routes import _studio_dsh_options
|
|
226
|
+
|
|
227
|
+
home, profile, command, _ = _studio_dsh_options(runtime)
|
|
228
|
+
# 可选 bootstrap 必须先确认 DSH 命令真实可用:无工具链的
|
|
229
|
+
# 环境进入 Profile 维护栅栏后,恢复失败会按契约保持
|
|
230
|
+
# admission 关闭,导致整个会话面永久 503(回归过)。
|
|
231
|
+
if command and shutil.which(str(command[0])) is None:
|
|
232
|
+
logger.info(
|
|
233
|
+
"Channel 默认激活跳过:DSH 命令不可用 (%s)",
|
|
234
|
+
command[0],
|
|
235
|
+
)
|
|
236
|
+
elif profile == "web" and command and channel_default_bootstrap_needed(home):
|
|
237
|
+
async def configure_channel():
|
|
238
|
+
await asyncio.to_thread(
|
|
239
|
+
configure_channel_profile,
|
|
240
|
+
workspace=runtime.workspace.root,
|
|
241
|
+
dsh_home=home,
|
|
242
|
+
dsh_command=command,
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
await runtime.reconfigure_dsh_profile(configure_channel)
|
|
246
|
+
except Exception as error:
|
|
247
|
+
logger.info("Channel 默认激活未完成(可手动启用): %s", error)
|
|
248
|
+
|
|
249
|
+
if os.environ.get(
|
|
250
|
+
"KSADK_STUDIO_TEAMS_DEFAULT", "1"
|
|
251
|
+
).strip().lower() not in {"0", "false", "no", "off"}:
|
|
252
|
+
installation = getattr(runtime, "teams_installation", None)
|
|
253
|
+
if installation is not None and not installation.status().get("enabled"):
|
|
254
|
+
try:
|
|
255
|
+
await installation.enable()
|
|
256
|
+
except Exception as error:
|
|
257
|
+
# 默认启用是预期行为,但 DSH 工具链/权威不可用时必须静默
|
|
258
|
+
# 降级,核心 Studio 与其他插件不受影响;页面仍保留手动入口。
|
|
259
|
+
logger.info(
|
|
260
|
+
"Teams 默认激活未完成(可手动启用): %s", error
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
task = asyncio.create_task(warm_runtime())
|
|
264
|
+
warmups.add(task)
|
|
265
|
+
task.add_done_callback(warmups.discard)
|
|
266
|
+
|
|
225
267
|
try:
|
|
226
|
-
|
|
227
|
-
await studio.
|
|
268
|
+
app.state.runtime_warmups = schedule_runtime_warmup
|
|
269
|
+
await studio.start(wait_for_dsh=not lazy_desktop_start)
|
|
270
|
+
# Optional plugin activation must not hold the HTTP listener closed
|
|
271
|
+
# while DSH starts subprocesses or acquires an authority lease.
|
|
272
|
+
schedule_runtime_warmup(studio.active)
|
|
273
|
+
# Pre-resolve the entry redirect choice once off the request path;
|
|
274
|
+
# failures are swallowed and ``index()`` has its own bounded wait.
|
|
275
|
+
probe_warmup = getattr(
|
|
276
|
+
studio.active.dsh_capabilities, "schedule_plugin_probe_warmup", None
|
|
277
|
+
)
|
|
278
|
+
if callable(probe_warmup):
|
|
279
|
+
probe_warmup()
|
|
280
|
+
await studio.run_service.recover_interrupted(studio.resolve_run_spec)
|
|
228
281
|
await studio.scheduler.start_if_available()
|
|
229
282
|
yield
|
|
230
283
|
finally:
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
284
|
+
app.state.runtime_warmups = None
|
|
285
|
+
for task in tuple(warmups):
|
|
286
|
+
task.cancel()
|
|
287
|
+
if warmups:
|
|
288
|
+
await asyncio.gather(*warmups, return_exceptions=True)
|
|
289
|
+
for runtime in studio.services():
|
|
290
|
+
await runtime.scheduler.stop()
|
|
291
|
+
await runtime.aclose()
|
|
292
|
+
runtime.credentials.clear_session()
|
|
234
293
|
|
|
235
294
|
app = FastAPI(
|
|
236
295
|
title="AgentKit Local Studio",
|
|
@@ -261,14 +320,18 @@ def create_studio_app(
|
|
|
261
320
|
collaboration_mode: str | None = None,
|
|
262
321
|
goal_objective: str | None = None,
|
|
263
322
|
runtime_input: Any = None,
|
|
323
|
+
presentation_profile: Literal["flat-v1", "agent-block-v1"] = "flat-v1",
|
|
264
324
|
idempotency_key: str,
|
|
265
325
|
) -> StreamingResponse:
|
|
266
326
|
"""Create an observer-only SSE response for one durable Studio run."""
|
|
267
327
|
|
|
268
328
|
queue: asyncio.Queue = asyncio.Queue()
|
|
329
|
+
from ksadk.studio.presentation import StudioConversationProjection
|
|
330
|
+
|
|
331
|
+
presentation = StudioConversationProjection(session_id, presentation_profile)
|
|
269
332
|
|
|
270
333
|
def observe(event):
|
|
271
|
-
queue.put_nowait(event)
|
|
334
|
+
queue.put_nowait(presentation.apply(event))
|
|
272
335
|
|
|
273
336
|
# The Operation owns the runtime task. The SSE response is only one
|
|
274
337
|
# observer, so refreshing or switching chats cannot cancel the Run.
|
|
@@ -285,6 +348,10 @@ def create_studio_app(
|
|
|
285
348
|
runtime_input=runtime_input,
|
|
286
349
|
idempotency_key=idempotency_key,
|
|
287
350
|
on_event=observe,
|
|
351
|
+
**(
|
|
352
|
+
{"presentation_profile": presentation_profile}
|
|
353
|
+
if presentation_profile != "flat-v1" else {}
|
|
354
|
+
),
|
|
288
355
|
)
|
|
289
356
|
|
|
290
357
|
async def render():
|
|
@@ -324,7 +391,8 @@ def create_studio_app(
|
|
|
324
391
|
|
|
325
392
|
static_root = Path(__file__).with_name("static")
|
|
326
393
|
shared_web = StudioSharedWebBridge(studio)
|
|
327
|
-
|
|
394
|
+
register_activity_routes(app, studio, resolve_run_id=shared_web.resolve_run_reference)
|
|
395
|
+
cloud_web = CloudSharedWebBridge(studio)
|
|
328
396
|
app.state.shared_web_bridge = shared_web
|
|
329
397
|
app.mount("/static", StaticFiles(directory=static_root), name="studio-static")
|
|
330
398
|
|
|
@@ -379,8 +447,10 @@ def create_studio_app(
|
|
|
379
447
|
or shared_web_api
|
|
380
448
|
or responses_api
|
|
381
449
|
):
|
|
382
|
-
supplied =
|
|
383
|
-
|
|
450
|
+
supplied = (
|
|
451
|
+
request.cookies.get(session_cookie_name)
|
|
452
|
+
or request.cookies.get(legacy_session_cookie_name)
|
|
453
|
+
or request.headers.get("X-AgentKit-Session")
|
|
384
454
|
)
|
|
385
455
|
if not supplied or not hmac.compare_digest(supplied, session_secret):
|
|
386
456
|
return _error_response(
|
|
@@ -391,7 +461,8 @@ def create_studio_app(
|
|
|
391
461
|
),
|
|
392
462
|
request,
|
|
393
463
|
)
|
|
394
|
-
|
|
464
|
+
channel_api = shared_web_api and request.url.path.rsplit("/", 1)[-1] in CHANNEL_ACTIONS
|
|
465
|
+
if (studio_api or responses_api or channel_api) and request.method in _WRITE_METHODS:
|
|
395
466
|
csrf = request.headers.get("X-CSRF-Token")
|
|
396
467
|
if not csrf or not hmac.compare_digest(csrf, csrf_secret):
|
|
397
468
|
return _error_response(
|
|
@@ -404,11 +475,7 @@ def create_studio_app(
|
|
|
404
475
|
)
|
|
405
476
|
response = await call_next(request)
|
|
406
477
|
response.headers["X-Request-Id"] = request.state.request_id
|
|
407
|
-
response.headers["Cache-Control"] = (
|
|
408
|
-
"no-store"
|
|
409
|
-
if request.url.path.startswith(("/api/", "/v1/"))
|
|
410
|
-
else response.headers.get("Cache-Control", "no-cache")
|
|
411
|
-
)
|
|
478
|
+
response.headers["Cache-Control"] = _cache_control_for(request.url.path, response)
|
|
412
479
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
413
480
|
response.headers["X-Frame-Options"] = "DENY"
|
|
414
481
|
response.headers["Referrer-Policy"] = "no-referrer"
|
|
@@ -466,18 +533,23 @@ def create_studio_app(
|
|
|
466
533
|
)
|
|
467
534
|
|
|
468
535
|
@app.get("/")
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
# module again when a lazy chunk imports the unversioned URL.
|
|
476
|
-
response = Response(content=html, media_type="text/html")
|
|
477
|
-
response.headers["Cache-Control"] = "no-store"
|
|
536
|
+
@app.get("/studio-recovery/")
|
|
537
|
+
@app.get("/studio-shell/")
|
|
538
|
+
async def index(request: Request):
|
|
539
|
+
from ksadk.studio.entry import studio_entry_response
|
|
540
|
+
|
|
541
|
+
response = await studio_entry_response(studio, request, static_root)
|
|
478
542
|
if security_enabled:
|
|
479
543
|
response.set_cookie(
|
|
480
|
-
|
|
544
|
+
session_cookie_name,
|
|
545
|
+
session_secret,
|
|
546
|
+
httponly=True,
|
|
547
|
+
samesite="strict",
|
|
548
|
+
secure=False,
|
|
549
|
+
path="/",
|
|
550
|
+
)
|
|
551
|
+
response.set_cookie(
|
|
552
|
+
legacy_session_cookie_name,
|
|
481
553
|
session_secret,
|
|
482
554
|
httponly=True,
|
|
483
555
|
samesite="strict",
|
|
@@ -486,6 +558,42 @@ def create_studio_app(
|
|
|
486
558
|
)
|
|
487
559
|
return response
|
|
488
560
|
|
|
561
|
+
@app.get("/api/v1/plugin-ecosystems/dsh/recovery")
|
|
562
|
+
async def dsh_recovery_status():
|
|
563
|
+
# This endpoint must remain a read-only snapshot: no Core startup, Profile
|
|
564
|
+
# projection, credential resolution, or filesystem repair is attempted.
|
|
565
|
+
return studio.dsh_capabilities.startup_status
|
|
566
|
+
|
|
567
|
+
@app.get("/api/v1/plugins/workspace-contributions")
|
|
568
|
+
async def workspace_contributions():
|
|
569
|
+
"""Expose enabled UI contributions without booting the DSH Core."""
|
|
570
|
+
from ksadk.plugins.dsh_channels import channel_workspace_contributions
|
|
571
|
+
from ksadk.plugins.dsh_home import studio_dsh_home
|
|
572
|
+
|
|
573
|
+
runtime = studio.active
|
|
574
|
+
contributions = await asyncio.to_thread(
|
|
575
|
+
channel_workspace_contributions,
|
|
576
|
+
studio_dsh_home(runtime.workspace.root),
|
|
577
|
+
os.environ.get("KSADK_DSH_PROFILE", "").strip() or "web",
|
|
578
|
+
)
|
|
579
|
+
# Teams remains served by its existing lifecycle endpoint; this endpoint
|
|
580
|
+
# only adds client-only contributions that have no domain lifecycle.
|
|
581
|
+
return {"items": contributions}
|
|
582
|
+
|
|
583
|
+
@app.get("/api/v1/channels/connection")
|
|
584
|
+
async def channel_connection_status():
|
|
585
|
+
return studio.channel_connections.status()
|
|
586
|
+
|
|
587
|
+
@app.put("/api/v1/channels/connection")
|
|
588
|
+
async def configure_channel_connection(payload: ChannelConnectionSettings):
|
|
589
|
+
return await studio.channel_connections.configure(payload)
|
|
590
|
+
|
|
591
|
+
@app.put("/api/v1/channels/agents/{agent_id}/connection")
|
|
592
|
+
async def configure_channel_agent_connection(
|
|
593
|
+
agent_id: str, payload: ChannelAgentConnectionInput
|
|
594
|
+
):
|
|
595
|
+
return await studio.channel_connections.configure_agent(agent_id, payload)
|
|
596
|
+
|
|
489
597
|
@app.get("/favicon.ico")
|
|
490
598
|
async def favicon():
|
|
491
599
|
return Response(status_code=204)
|
|
@@ -591,6 +699,31 @@ def create_studio_app(
|
|
|
591
699
|
or metadata.get("invocationId")
|
|
592
700
|
or f"resp_{secrets.token_hex(12)}"
|
|
593
701
|
)
|
|
702
|
+
resume_input = extract_responses_resume_input(payload.get("input"))
|
|
703
|
+
if resume_input is not None:
|
|
704
|
+
previous_response_id = str(payload.get("previous_response_id") or "").strip()
|
|
705
|
+
if not previous_response_id:
|
|
706
|
+
raise StudioError(
|
|
707
|
+
"PREVIOUS_RESPONSE_REQUIRED",
|
|
708
|
+
"恢复审批时必须提供 previous_response_id",
|
|
709
|
+
status_code=422,
|
|
710
|
+
field="previous_response_id",
|
|
711
|
+
)
|
|
712
|
+
if bool(payload.get("stream")):
|
|
713
|
+
return StreamingResponse(
|
|
714
|
+
shared_web.stream_response_resume(
|
|
715
|
+
previous_response_id=previous_response_id,
|
|
716
|
+
response_id=response_id,
|
|
717
|
+
resume_input=resume_input,
|
|
718
|
+
),
|
|
719
|
+
media_type="text/event-stream",
|
|
720
|
+
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
721
|
+
)
|
|
722
|
+
return await shared_web.invoke_response_resume(
|
|
723
|
+
previous_response_id=previous_response_id,
|
|
724
|
+
response_id=response_id,
|
|
725
|
+
resume_input=resume_input,
|
|
726
|
+
)
|
|
594
727
|
bridge_payload: dict[str, Any] = {
|
|
595
728
|
"AgentId": shared_web.resolve_agent_id(agent_id),
|
|
596
729
|
"SessionId": session_id or f"ses_{secrets.token_hex(12)}",
|
|
@@ -603,10 +736,9 @@ def create_studio_app(
|
|
|
603
736
|
"ReasoningEffort": reasoning_effort,
|
|
604
737
|
"ModelExplicit": bool(str(payload.get("model") or "").strip()),
|
|
605
738
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
)
|
|
739
|
+
# The shared bridge validates the model after ensuring the current
|
|
740
|
+
# immutable Build. Do not validate here: provider-backed catalogs are
|
|
741
|
+
# discovered during a cold Build and may legitimately be empty now.
|
|
610
742
|
if bool(payload.get("stream")):
|
|
611
743
|
return StreamingResponse(
|
|
612
744
|
shared_web.stream_run(bridge_payload),
|
|
@@ -617,7 +749,7 @@ def create_studio_app(
|
|
|
617
749
|
|
|
618
750
|
@app.post("/v1/responses/{response_id}/cancel")
|
|
619
751
|
async def cancel_openai_response(response_id: str):
|
|
620
|
-
result = shared_web.cancel_run(response_id)
|
|
752
|
+
result = await shared_web.cancel_run(response_id)
|
|
621
753
|
return {
|
|
622
754
|
"id": response_id,
|
|
623
755
|
"object": "response",
|
|
@@ -688,6 +820,10 @@ def create_studio_app(
|
|
|
688
820
|
data = await cloud_web.submit_interaction(
|
|
689
821
|
cloud_target, str(payload.get("SessionId") or ""), payload
|
|
690
822
|
)
|
|
823
|
+
elif action == "CancelRun" or (
|
|
824
|
+
action == "RunAgent" and payload.get("Background") is True
|
|
825
|
+
):
|
|
826
|
+
data = await cloud_web.cloud.shared_web_action(cloud_target, action, payload)
|
|
691
827
|
elif action == "RunAgent":
|
|
692
828
|
# Open the upstream connection before StreamingResponse
|
|
693
829
|
# commits status 200, so admission failures remain a
|
|
@@ -721,7 +857,15 @@ def create_studio_app(
|
|
|
721
857
|
)
|
|
722
858
|
return {"Code": 0, "Message": "OK", "Data": data}
|
|
723
859
|
if action == "GetAgentUiBootstrap":
|
|
724
|
-
|
|
860
|
+
bootstrap_agent_id = shared_web.resolve_agent_id(
|
|
861
|
+
requested_agent_id or None
|
|
862
|
+
)
|
|
863
|
+
# 冷启动时 provider 模型描述符尚未发现;绑定 model:provider:*
|
|
864
|
+
# 的 Agent(尤其 Harness)若直接解析会 RESOURCE_NOT_FOUND,
|
|
865
|
+
# 前端只能无限转圈。访问资源库不应该是打开对话的前置条件。
|
|
866
|
+
if not bootstrap_agent_id.startswith(("ar-", "account:")):
|
|
867
|
+
await runtime_model_catalog()
|
|
868
|
+
data = shared_web.bootstrap(bootstrap_agent_id)
|
|
725
869
|
elif action == "ListAgentModels":
|
|
726
870
|
model_agent_id = shared_web.resolve_agent_id(requested_agent_id or None)
|
|
727
871
|
# A cold Studio process has no discovered provider descriptors.
|
|
@@ -741,6 +885,12 @@ def create_studio_app(
|
|
|
741
885
|
)
|
|
742
886
|
elif action == "GetSession":
|
|
743
887
|
data = await shared_web.get_session(str(payload.get("SessionId") or ""))
|
|
888
|
+
elif action == "GetRunReceipt":
|
|
889
|
+
data = shared_web.run_receipt(
|
|
890
|
+
shared_web.resolve_agent_id(requested_agent_id or None),
|
|
891
|
+
str(payload.get("SessionId") or ""),
|
|
892
|
+
str(payload.get("InvocationId") or ""),
|
|
893
|
+
)
|
|
744
894
|
elif action == "CompactSession":
|
|
745
895
|
data = await shared_web.compact_session(
|
|
746
896
|
shared_web.resolve_agent_id(requested_agent_id or None),
|
|
@@ -771,9 +921,25 @@ def create_studio_app(
|
|
|
771
921
|
},
|
|
772
922
|
)
|
|
773
923
|
elif action == "CancelRun":
|
|
774
|
-
data = shared_web.cancel_run(str(payload.get("InvocationId") or ""))
|
|
924
|
+
data = await shared_web.cancel_run(str(payload.get("InvocationId") or ""))
|
|
925
|
+
elif action == "SteerRun":
|
|
926
|
+
instruction = payload.get("Text")
|
|
927
|
+
if (
|
|
928
|
+
not isinstance(instruction, str)
|
|
929
|
+
or not instruction.strip()
|
|
930
|
+
or len(instruction) > 32768
|
|
931
|
+
):
|
|
932
|
+
raise StudioError(
|
|
933
|
+
"RUN_STEER_INVALID", "插话内容必须是非空文本", status_code=422
|
|
934
|
+
)
|
|
935
|
+
data = await shared_web.steer_run(
|
|
936
|
+
str(payload.get("InvocationId") or ""),
|
|
937
|
+
instruction,
|
|
938
|
+
delivery=payload.get("Delivery", "replace"),
|
|
939
|
+
)
|
|
775
940
|
elif action == "SubmitInteraction":
|
|
776
941
|
run_id = str(payload.get("RunId") or "")
|
|
942
|
+
studio._require_direct_run(run_id)
|
|
777
943
|
interaction_id = str(payload.get("InteractionId") or "")
|
|
778
944
|
resolved = await studio.run_service.submit_interaction(
|
|
779
945
|
run_id,
|
|
@@ -810,6 +976,10 @@ def create_studio_app(
|
|
|
810
976
|
elif action == "ListToolReceipts":
|
|
811
977
|
data = {"ToolReceipts": []}
|
|
812
978
|
else:
|
|
979
|
+
# Channel-related actions: proxy to channel backend
|
|
980
|
+
if action in CHANNEL_ACTIONS:
|
|
981
|
+
status, body = await studio.channel_connections.proxy(action, payload)
|
|
982
|
+
return JSONResponse(status_code=status, content=body)
|
|
813
983
|
return JSONResponse(
|
|
814
984
|
status_code=404,
|
|
815
985
|
content={
|
|
@@ -829,6 +999,34 @@ def create_studio_app(
|
|
|
829
999
|
},
|
|
830
1000
|
)
|
|
831
1001
|
|
|
1002
|
+
@app.get("/agentengine/api/v1/SubscribeSessionEvents")
|
|
1003
|
+
async def shared_chat_subscribe_session_events(
|
|
1004
|
+
request: Request,
|
|
1005
|
+
session_id: str = Query(alias="SessionId"),
|
|
1006
|
+
after_seq: int = Query(default=0, ge=0),
|
|
1007
|
+
agent_id: str | None = Query(default=None, alias="AgentId"),
|
|
1008
|
+
):
|
|
1009
|
+
requested_agent_id = str(
|
|
1010
|
+
agent_id or request.cookies.get("agentkit_studio_chat_agent") or ""
|
|
1011
|
+
)
|
|
1012
|
+
if not is_cloud_agent_id(requested_agent_id):
|
|
1013
|
+
raise StudioError("CLOUD_AGENT_REQUIRED", "需要云端 Agent", status_code=400)
|
|
1014
|
+
stream = await cloud_web.cloud.subscribe_cloud_session_events(
|
|
1015
|
+
cloud_chat_target(requested_agent_id), session_id=session_id, after_seq=after_seq,
|
|
1016
|
+
)
|
|
1017
|
+
async def forward():
|
|
1018
|
+
try:
|
|
1019
|
+
async for chunk in stream:
|
|
1020
|
+
yield chunk
|
|
1021
|
+
finally:
|
|
1022
|
+
close = getattr(stream, "aclose", None)
|
|
1023
|
+
if close is not None:
|
|
1024
|
+
await close()
|
|
1025
|
+
return StreamingResponse(
|
|
1026
|
+
forward(), media_type="text/event-stream",
|
|
1027
|
+
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
1028
|
+
)
|
|
1029
|
+
|
|
832
1030
|
@app.get("/agentengine/api/v1/SubscribeRunEvents")
|
|
833
1031
|
async def shared_chat_subscribe_run_events(
|
|
834
1032
|
request: Request,
|
|
@@ -882,7 +1080,15 @@ def create_studio_app(
|
|
|
882
1080
|
status_code=401,
|
|
883
1081
|
)
|
|
884
1082
|
response.set_cookie(
|
|
885
|
-
|
|
1083
|
+
session_cookie_name,
|
|
1084
|
+
session_secret,
|
|
1085
|
+
httponly=True,
|
|
1086
|
+
samesite="strict",
|
|
1087
|
+
secure=False,
|
|
1088
|
+
path="/",
|
|
1089
|
+
)
|
|
1090
|
+
response.set_cookie(
|
|
1091
|
+
legacy_session_cookie_name,
|
|
886
1092
|
session_secret,
|
|
887
1093
|
httponly=True,
|
|
888
1094
|
samesite="strict",
|
|
@@ -896,18 +1102,21 @@ def create_studio_app(
|
|
|
896
1102
|
return {
|
|
897
1103
|
"serverVersion": "1.0.0",
|
|
898
1104
|
"apiVersion": "v1",
|
|
1105
|
+
"sdkVersion": _sdk_version,
|
|
899
1106
|
"sessionTokenRequired": security_enabled,
|
|
900
1107
|
"csrfToken": csrf_secret,
|
|
901
1108
|
"workspace": {
|
|
902
1109
|
"name": studio.workspace.root.name,
|
|
903
1110
|
"path": str(studio.workspace.root),
|
|
1111
|
+
"workspaceId": studio.workspace_record.workspace_id,
|
|
904
1112
|
},
|
|
905
1113
|
"operationScope": studio.deployment_operation_scope(),
|
|
1114
|
+
"frontend": studio.frontend_assets(),
|
|
906
1115
|
"features": {
|
|
907
1116
|
"build": True,
|
|
908
1117
|
"run": True,
|
|
909
1118
|
"runtimeRegistry": True,
|
|
910
|
-
"runtimeTypes": ["codex", "adk", "langgraph"],
|
|
1119
|
+
"runtimeTypes": ["harness", "codex", "adk", "langgraph"],
|
|
911
1120
|
"evaluation": True,
|
|
912
1121
|
"deployment": True,
|
|
913
1122
|
"cloudRebuild": False,
|
|
@@ -924,7 +1133,24 @@ def create_studio_app(
|
|
|
924
1133
|
|
|
925
1134
|
@app.put("/api/v1/system/settings")
|
|
926
1135
|
async def update_settings(payload: dict[str, Any]):
|
|
927
|
-
return studio.
|
|
1136
|
+
return await studio.apply_settings(payload)
|
|
1137
|
+
|
|
1138
|
+
@app.get("/api/v1/system/update-check")
|
|
1139
|
+
async def update_check():
|
|
1140
|
+
try:
|
|
1141
|
+
latest = await _fetch_latest_ksadk_version()
|
|
1142
|
+
except Exception as exc: # noqa: BLE001 - 检查更新失败只降级展示,不进错误链路
|
|
1143
|
+
return {
|
|
1144
|
+
"currentVersion": _sdk_version,
|
|
1145
|
+
"latestVersion": None,
|
|
1146
|
+
"hasUpdate": False,
|
|
1147
|
+
"error": type(exc).__name__,
|
|
1148
|
+
}
|
|
1149
|
+
return {
|
|
1150
|
+
"currentVersion": _sdk_version,
|
|
1151
|
+
"latestVersion": latest,
|
|
1152
|
+
"hasUpdate": _version_key(latest) > _version_key(_sdk_version),
|
|
1153
|
+
}
|
|
928
1154
|
|
|
929
1155
|
@app.get("/api/v1/schedules")
|
|
930
1156
|
async def list_schedules():
|
|
@@ -1036,23 +1262,222 @@ def create_studio_app(
|
|
|
1036
1262
|
studio.get_agent_schedule(agent_id, task_id)
|
|
1037
1263
|
return {"items": studio.scheduler.list_occurrences(task_id, limit=limit)}
|
|
1038
1264
|
|
|
1265
|
+
def _decode_text_file(path: Path) -> str:
|
|
1266
|
+
"""Decode with an encoding fallback chain so legacy GBK/GB18030 files
|
|
1267
|
+
written by agents preview correctly instead of turning into mojibake."""
|
|
1268
|
+
raw = path.read_bytes()
|
|
1269
|
+
for encoding in ("utf-8-sig", "utf-8", "gb18030"):
|
|
1270
|
+
try:
|
|
1271
|
+
return raw.decode(encoding)
|
|
1272
|
+
except UnicodeDecodeError:
|
|
1273
|
+
continue
|
|
1274
|
+
return raw.decode("utf-8", errors="replace")
|
|
1275
|
+
|
|
1276
|
+
@app.get("/api/v1/workspace/file")
|
|
1277
|
+
async def read_workspace_file(path: str = Query(...), download: bool = Query(default=False)):
|
|
1278
|
+
"""Read one file inside the workspace (or a linked directory) for preview.
|
|
1279
|
+
|
|
1280
|
+
Absolute paths outside the workspace and its linked directories are
|
|
1281
|
+
rejected, as are oversized files; preview clients render the payload
|
|
1282
|
+
according to the returned contentType.
|
|
1283
|
+
"""
|
|
1284
|
+
import mimetypes
|
|
1285
|
+
from urllib.parse import quote
|
|
1286
|
+
|
|
1287
|
+
raw = Path(path).expanduser()
|
|
1288
|
+
candidate = raw if raw.is_absolute() else studio.workspace.root / raw
|
|
1289
|
+
try:
|
|
1290
|
+
resolved = candidate.resolve()
|
|
1291
|
+
except OSError as error:
|
|
1292
|
+
raise StudioError("WORKSPACE_FILE_INVALID", "文件路径无效", status_code=422) from error
|
|
1293
|
+
|
|
1294
|
+
allowed_roots = [studio.workspace.root.resolve()]
|
|
1295
|
+
for item in LinkedDirectoryPolicy(studio.workspace.root).list():
|
|
1296
|
+
linked = Path(item.path).expanduser().resolve()
|
|
1297
|
+
if linked.is_dir():
|
|
1298
|
+
allowed_roots.append(linked)
|
|
1299
|
+
if not any(
|
|
1300
|
+
resolved == root or resolved.is_relative_to(root) for root in allowed_roots
|
|
1301
|
+
):
|
|
1302
|
+
raise StudioError(
|
|
1303
|
+
"WORKSPACE_FILE_FORBIDDEN", "路径不在工作区(或链接目录)内", status_code=403
|
|
1304
|
+
)
|
|
1305
|
+
if not resolved.is_file():
|
|
1306
|
+
raise StudioError("WORKSPACE_FILE_NOT_FOUND", "文件不存在", status_code=404)
|
|
1307
|
+
size = resolved.stat().st_size
|
|
1308
|
+
if size > 2 * 1024 * 1024:
|
|
1309
|
+
raise StudioError(
|
|
1310
|
+
"WORKSPACE_FILE_TOO_LARGE", "文件超过 2MB 预览上限", status_code=413
|
|
1311
|
+
)
|
|
1312
|
+
suffix = resolved.suffix.lower()
|
|
1313
|
+
if suffix in {
|
|
1314
|
+
".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico",
|
|
1315
|
+
}:
|
|
1316
|
+
content_type = mimetypes.guess_type(resolved.name)[0] or "application/octet-stream"
|
|
1317
|
+
media_category = "image"
|
|
1318
|
+
payload: bytes | str = resolved.read_bytes()
|
|
1319
|
+
elif suffix in {".md", ".markdown"}:
|
|
1320
|
+
content_type, media_category = "text/markdown", "markdown"
|
|
1321
|
+
payload = _decode_text_file(resolved)
|
|
1322
|
+
else:
|
|
1323
|
+
text_types = {
|
|
1324
|
+
".txt", ".json", ".csv", ".tsv", ".log", ".py", ".js", ".ts", ".tsx",
|
|
1325
|
+
".jsx", ".html", ".css", ".yaml", ".yml", ".toml", ".xml", ".sh",
|
|
1326
|
+
".sql", ".rs", ".go", ".java", ".c", ".cpp", ".h", ".diff", ".ini",
|
|
1327
|
+
}
|
|
1328
|
+
if suffix not in text_types:
|
|
1329
|
+
raise StudioError(
|
|
1330
|
+
"WORKSPACE_FILE_UNSUPPORTED", "该文件类型暂不支持预览", status_code=415
|
|
1331
|
+
)
|
|
1332
|
+
content_type, media_category = "text/plain", "text"
|
|
1333
|
+
payload = _decode_text_file(resolved)
|
|
1334
|
+
response = {
|
|
1335
|
+
"path": str(resolved),
|
|
1336
|
+
"name": resolved.name,
|
|
1337
|
+
"sizeBytes": size,
|
|
1338
|
+
"contentType": content_type,
|
|
1339
|
+
"mediaCategory": media_category,
|
|
1340
|
+
}
|
|
1341
|
+
if download:
|
|
1342
|
+
quoted = quote(resolved.name)
|
|
1343
|
+
return Response(
|
|
1344
|
+
content=payload if isinstance(payload, bytes) else payload.encode("utf-8"),
|
|
1345
|
+
media_type=content_type,
|
|
1346
|
+
headers={"Content-Disposition": f"attachment; filename*=UTF-8''{quoted}"},
|
|
1347
|
+
)
|
|
1348
|
+
if media_category == "image":
|
|
1349
|
+
import base64
|
|
1350
|
+
|
|
1351
|
+
response["dataBase64"] = base64.b64encode(payload).decode("ascii")
|
|
1352
|
+
else:
|
|
1353
|
+
response["content"] = payload
|
|
1354
|
+
return response
|
|
1355
|
+
|
|
1039
1356
|
@app.post("/api/v1/workspaces:open")
|
|
1040
1357
|
async def open_workspace(payload: WorkspaceOpenRequest):
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1358
|
+
try:
|
|
1359
|
+
# A user-selected directory is itself the workspace. The registry
|
|
1360
|
+
# entry is created as part of opening it; callers do not need to
|
|
1361
|
+
# pre-register paths in a separate settings screen.
|
|
1362
|
+
record = studio.switch(payload.path, create=True)
|
|
1363
|
+
# Start local state immediately, but keep optional DSH/Profile
|
|
1364
|
+
# discovery off the workspace-switch response path.
|
|
1365
|
+
runtime = studio.active
|
|
1366
|
+
await runtime.start(wait_for_dsh=False)
|
|
1367
|
+
schedule_runtime_warmup = getattr(app.state, "runtime_warmups", None)
|
|
1368
|
+
if schedule_runtime_warmup is not None:
|
|
1369
|
+
schedule_runtime_warmup(runtime)
|
|
1370
|
+
except FileNotFoundError as error:
|
|
1371
|
+
raise StudioError("WORKSPACE_NOT_FOUND", "工作区目录不存在", status_code=404) from error
|
|
1372
|
+
response = {
|
|
1373
|
+
"name": record.name,
|
|
1374
|
+
"path": record.path,
|
|
1375
|
+
"workspaceId": record.workspace_id,
|
|
1376
|
+
}
|
|
1377
|
+
# Preserve the legacy reconnect response shape for the daemon root;
|
|
1378
|
+
# switched workspaces include the stable identity for scoped clients.
|
|
1379
|
+
if os.path.normcase(record.path) == os.path.normcase(str(initial_service.workspace.root)):
|
|
1380
|
+
response.pop("workspaceId", None)
|
|
1381
|
+
return response
|
|
1382
|
+
|
|
1383
|
+
@app.post("/api/v1/workspaces:choose")
|
|
1384
|
+
async def choose_workspace_directory():
|
|
1385
|
+
"""Open the host folder chooser for a local Web Studio session."""
|
|
1386
|
+
if sys.platform != "darwin":
|
|
1387
|
+
raise StudioError(
|
|
1388
|
+
"WORKSPACE_PICKER_UNAVAILABLE",
|
|
1389
|
+
"当前系统没有可用的原生目录选择器,请输入目录路径",
|
|
1390
|
+
status_code=501,
|
|
1391
|
+
)
|
|
1392
|
+
script = (
|
|
1393
|
+
'tell application "System Events" to set selectedFolder to choose folder '
|
|
1394
|
+
'with prompt "选择 AgentKit Studio 工作区"\n'
|
|
1395
|
+
'POSIX path of selectedFolder'
|
|
1396
|
+
)
|
|
1397
|
+
result = await asyncio.to_thread(
|
|
1398
|
+
subprocess.run,
|
|
1399
|
+
["osascript", "-e", script],
|
|
1400
|
+
capture_output=True,
|
|
1401
|
+
text=True,
|
|
1402
|
+
check=False,
|
|
1403
|
+
)
|
|
1404
|
+
if result.returncode != 0:
|
|
1405
|
+
return {"path": None, "cancelled": True}
|
|
1406
|
+
path = result.stdout.strip()
|
|
1407
|
+
return {"path": path or None, "cancelled": not bool(path)}
|
|
1408
|
+
|
|
1409
|
+
@app.get("/api/v1/workspaces")
|
|
1410
|
+
async def list_workspaces():
|
|
1411
|
+
active_path = os.path.normcase(str(studio.workspace.root))
|
|
1412
|
+
items = []
|
|
1413
|
+
for record in WorkspaceRegistry().list():
|
|
1414
|
+
item = record.__dict__.copy()
|
|
1415
|
+
item["active"] = os.path.normcase(record.path) == active_path
|
|
1416
|
+
items.append(item)
|
|
1417
|
+
return {"items": items}
|
|
1418
|
+
|
|
1419
|
+
@app.post("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1420
|
+
async def add_linked_directory(workspace_id: str, payload: LinkedDirectoryRequest):
|
|
1421
|
+
record = next(
|
|
1422
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1423
|
+
)
|
|
1424
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1425
|
+
str(studio.workspace.root)
|
|
1426
|
+
):
|
|
1046
1427
|
raise StudioError(
|
|
1047
|
-
"
|
|
1048
|
-
|
|
1049
|
-
|
|
1428
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1429
|
+
)
|
|
1430
|
+
item = LinkedDirectoryPolicy(studio.workspace.root).set(
|
|
1431
|
+
payload.path, payload.mode, payload.label
|
|
1432
|
+
)
|
|
1433
|
+
return item.__dict__
|
|
1434
|
+
|
|
1435
|
+
@app.get("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1436
|
+
async def list_linked_directories(workspace_id: str):
|
|
1437
|
+
record = next(
|
|
1438
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1439
|
+
)
|
|
1440
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1441
|
+
str(studio.workspace.root)
|
|
1442
|
+
):
|
|
1443
|
+
raise StudioError(
|
|
1444
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1050
1445
|
)
|
|
1051
1446
|
return {
|
|
1052
|
-
"
|
|
1053
|
-
"path": str(studio.workspace.root),
|
|
1447
|
+
"items": [item.__dict__ for item in LinkedDirectoryPolicy(studio.workspace.root).list()]
|
|
1054
1448
|
}
|
|
1055
1449
|
|
|
1450
|
+
@app.delete("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1451
|
+
async def remove_linked_directory(workspace_id: str, path: str):
|
|
1452
|
+
record = next(
|
|
1453
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1454
|
+
)
|
|
1455
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1456
|
+
str(studio.workspace.root)
|
|
1457
|
+
):
|
|
1458
|
+
raise StudioError(
|
|
1459
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1460
|
+
)
|
|
1461
|
+
return {"removed": LinkedDirectoryPolicy(studio.workspace.root).remove(path)}
|
|
1462
|
+
|
|
1463
|
+
@app.get("/api/v1/workspaces/{workspace_id}/linked-directories/authorize")
|
|
1464
|
+
async def authorize_linked_directory(
|
|
1465
|
+
workspace_id: str,
|
|
1466
|
+
path: str,
|
|
1467
|
+
operation: Literal["read", "write"] = "read",
|
|
1468
|
+
):
|
|
1469
|
+
record = next(
|
|
1470
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1471
|
+
)
|
|
1472
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1473
|
+
str(studio.workspace.root)
|
|
1474
|
+
):
|
|
1475
|
+
raise StudioError(
|
|
1476
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1477
|
+
)
|
|
1478
|
+
allowed = LinkedDirectoryPolicy(studio.workspace.root).authorize(path, operation)
|
|
1479
|
+
return {"path": path, "operation": operation, "allowed": allowed}
|
|
1480
|
+
|
|
1056
1481
|
@app.get("/api/v1/codex/manifest")
|
|
1057
1482
|
async def get_codex_manifest():
|
|
1058
1483
|
return studio.codex_manifest_state()
|
|
@@ -1212,6 +1637,19 @@ def create_studio_app(
|
|
|
1212
1637
|
display_input = "\n".join(text_parts).strip()
|
|
1213
1638
|
if not display_input:
|
|
1214
1639
|
display_input = "请处理本轮附件:" + "、".join(attachment_names)
|
|
1640
|
+
from ksadk.a2a.presentation import negotiate_presentation_profile
|
|
1641
|
+
|
|
1642
|
+
requested_profile = conversation_input.extensions.get("ksadk.presentation", {}).get(
|
|
1643
|
+
"profile"
|
|
1644
|
+
)
|
|
1645
|
+
presentation_profile = negotiate_presentation_profile(
|
|
1646
|
+
producer_declares_capability=any(
|
|
1647
|
+
capability.name == "agent.block" and capability.mode in {"native", "translated"}
|
|
1648
|
+
for capability in surface.outputs
|
|
1649
|
+
),
|
|
1650
|
+
requested_profile=requested_profile,
|
|
1651
|
+
renderer_supports_agent_block=requested_profile == "agent-block-v1",
|
|
1652
|
+
)
|
|
1215
1653
|
return _stream_studio_run(
|
|
1216
1654
|
build_id,
|
|
1217
1655
|
user_input=display_input,
|
|
@@ -1222,6 +1660,7 @@ def create_studio_app(
|
|
|
1222
1660
|
approval_mode=conversation_input.approval_mode,
|
|
1223
1661
|
collaboration_mode=conversation_input.collaboration_mode,
|
|
1224
1662
|
goal_objective=conversation_input.goal_objective,
|
|
1663
|
+
presentation_profile=presentation_profile,
|
|
1225
1664
|
runtime_input=runtime_parts if attachment_names else None,
|
|
1226
1665
|
idempotency_key=key,
|
|
1227
1666
|
)
|
|
@@ -1377,6 +1816,30 @@ def create_studio_app(
|
|
|
1377
1816
|
async def get_agent(agent_id: str):
|
|
1378
1817
|
return studio.agent_detail(agent_id)
|
|
1379
1818
|
|
|
1819
|
+
@app.post("/api/v1/agents/{agent_id}/runtime:prewarm", status_code=202)
|
|
1820
|
+
async def prewarm_agent_runtime(agent_id: str, payload: dict[str, Any]):
|
|
1821
|
+
"""后台准备不可变 Build 的 Host,不提前绑定下一轮 Session 配置。"""
|
|
1822
|
+
session_id = str(payload.get("sessionId") or "")
|
|
1823
|
+
if not session_id:
|
|
1824
|
+
raise StudioError(
|
|
1825
|
+
"SESSION_ID_REQUIRED", "缺少 sessionId", status_code=422
|
|
1826
|
+
)
|
|
1827
|
+
try:
|
|
1828
|
+
build = await studio.ensure_current_build(agent_id)
|
|
1829
|
+
except StudioError as exc:
|
|
1830
|
+
raise StudioError(
|
|
1831
|
+
"BUILD_NOT_FOUND", f"Agent 尚无可运行的 Build:{exc.message}",
|
|
1832
|
+
status_code=404,
|
|
1833
|
+
) from exc
|
|
1834
|
+
|
|
1835
|
+
from ksadk.studio.runtime_prewarm import prewarm_runtime_build
|
|
1836
|
+
|
|
1837
|
+
task = asyncio.create_task(prewarm_runtime_build(studio, build.id))
|
|
1838
|
+
app.state.runtime_prewarms = getattr(app.state, "runtime_prewarms", set())
|
|
1839
|
+
app.state.runtime_prewarms.add(task)
|
|
1840
|
+
task.add_done_callback(app.state.runtime_prewarms.discard)
|
|
1841
|
+
return {"status": "prewarming", "buildId": build.id}
|
|
1842
|
+
|
|
1380
1843
|
@app.get("/api/v1/agents/{agent_id}/models")
|
|
1381
1844
|
async def get_agent_models(agent_id: str):
|
|
1382
1845
|
model_agent_id = shared_web.resolve_agent_id(agent_id)
|
|
@@ -1535,19 +1998,94 @@ def create_studio_app(
|
|
|
1535
1998
|
|
|
1536
1999
|
@app.get("/api/v1/runs/{run_id}")
|
|
1537
2000
|
async def get_run(run_id: str):
|
|
1538
|
-
|
|
2001
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2002
|
+
if runtime is None:
|
|
2003
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2004
|
+
return runtime.event_store.get(run_id)
|
|
1539
2005
|
|
|
1540
2006
|
@app.post("/api/v1/runs/{run_id}:cancel", status_code=202)
|
|
1541
2007
|
async def cancel_run(run_id: str):
|
|
1542
|
-
|
|
2008
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2009
|
+
if runtime is None:
|
|
2010
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2011
|
+
runtime._require_direct_run(run_id)
|
|
2012
|
+
return await runtime.run_service.cancel_run(run_id)
|
|
1543
2013
|
|
|
1544
2014
|
@app.post("/api/v1/runs/{run_id}:pause", status_code=202)
|
|
1545
2015
|
async def pause_run(run_id: str):
|
|
1546
|
-
|
|
2016
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2017
|
+
if runtime is None:
|
|
2018
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2019
|
+
runtime._require_direct_run(run_id)
|
|
2020
|
+
return await runtime.run_service.pause_run(run_id)
|
|
2021
|
+
|
|
2022
|
+
@app.post("/api/v1/runs/{run_id}:steer", status_code=202)
|
|
2023
|
+
async def steer_run(run_id: str, payload: SteerRunRequest):
|
|
2024
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2025
|
+
if runtime is None:
|
|
2026
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2027
|
+
runtime._require_direct_run(run_id)
|
|
2028
|
+
return await runtime.run_service.steer_run(run_id, payload.text, delivery=payload.delivery)
|
|
1547
2029
|
|
|
1548
2030
|
@app.post("/api/v1/runs/{run_id}:resume", status_code=202)
|
|
1549
2031
|
async def resume_run(run_id: str):
|
|
1550
|
-
|
|
2032
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2033
|
+
if runtime is None:
|
|
2034
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2035
|
+
runtime._require_direct_run(run_id)
|
|
2036
|
+
return await runtime.run_service.resume_run(run_id)
|
|
2037
|
+
|
|
2038
|
+
@app.get("/api/v1/runs/{run_id}/public-output/{artifact_id}")
|
|
2039
|
+
async def public_tool_output(run_id: str, artifact_id: str):
|
|
2040
|
+
from ksadk.studio.public_output_store import PublicOutputStore
|
|
2041
|
+
|
|
2042
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2043
|
+
if runtime is None:
|
|
2044
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2045
|
+
runtime._require_direct_run(run_id)
|
|
2046
|
+
data = PublicOutputStore(runtime.workspace).read(run_id, artifact_id)
|
|
2047
|
+
return Response(content=data["text"], media_type="text/plain; charset=utf-8", headers={
|
|
2048
|
+
"Content-Disposition": 'attachment; filename="tool-output.txt"',
|
|
2049
|
+
"X-Content-Type-Options": "nosniff", "Cache-Control": "private, no-store",
|
|
2050
|
+
"X-Ksadk-Output-Truncated": str(data["truncated"]).lower(),
|
|
2051
|
+
})
|
|
2052
|
+
|
|
2053
|
+
@app.get("/api/v1/runs/{run_id}/children")
|
|
2054
|
+
async def child_tasks(run_id: str):
|
|
2055
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2056
|
+
if runtime is None:
|
|
2057
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2058
|
+
runtime._require_direct_run(run_id)
|
|
2059
|
+
return await runtime.run_service.child_tasks(run_id)
|
|
2060
|
+
|
|
2061
|
+
@app.post("/api/v1/runs/{run_id}/children/{child_run_id}:cancel", status_code=202)
|
|
2062
|
+
async def cancel_child(run_id: str, child_run_id: str, payload: CancelChildRequest):
|
|
2063
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2064
|
+
if runtime is None:
|
|
2065
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2066
|
+
runtime._require_direct_run(run_id)
|
|
2067
|
+
return await runtime.run_service.cancel_child(run_id, child_run_id,
|
|
2068
|
+
command_id=payload.command_id)
|
|
2069
|
+
|
|
2070
|
+
@app.post("/api/v1/runs/{run_id}/children/{child_run_id}:promote", status_code=202)
|
|
2071
|
+
async def promote_child(run_id: str, child_run_id: str, payload: PromoteChildRequest):
|
|
2072
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2073
|
+
if runtime is None:
|
|
2074
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2075
|
+
runtime._require_direct_run(run_id)
|
|
2076
|
+
return await runtime.run_service.promote_child(run_id, child_run_id,
|
|
2077
|
+
command_id=payload.command_id)
|
|
2078
|
+
|
|
2079
|
+
@app.post("/api/v1/runs/{run_id}/children/{child_run_id}:send", status_code=202)
|
|
2080
|
+
async def send_child_input(run_id: str, child_run_id: str, payload: ChildInputRequest):
|
|
2081
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2082
|
+
if runtime is None:
|
|
2083
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2084
|
+
runtime._require_direct_run(run_id)
|
|
2085
|
+
return await runtime.run_service.send_child_input(
|
|
2086
|
+
run_id, child_run_id, text=payload.text, command_id=payload.command_id,
|
|
2087
|
+
expected_goal_revision=payload.expected_goal_revision,
|
|
2088
|
+
)
|
|
1551
2089
|
|
|
1552
2090
|
@app.post("/api/v1/runs/{run_id}/interactions/{interaction_id}:submit")
|
|
1553
2091
|
async def submit_run_interaction(
|
|
@@ -1555,7 +2093,10 @@ def create_studio_app(
|
|
|
1555
2093
|
interaction_id: str,
|
|
1556
2094
|
payload: InteractionSubmitRequest,
|
|
1557
2095
|
):
|
|
1558
|
-
|
|
2096
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2097
|
+
if runtime is None:
|
|
2098
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2099
|
+
return await runtime.run_service.submit_interaction(
|
|
1559
2100
|
run_id,
|
|
1560
2101
|
interaction_id,
|
|
1561
2102
|
name=payload.name,
|
|
@@ -1567,7 +2108,10 @@ def create_studio_app(
|
|
|
1567
2108
|
@app.get("/api/v1/runs/{run_id}/context")
|
|
1568
2109
|
async def get_run_context(run_id: str):
|
|
1569
2110
|
"""Runtime Context Evidence:planned/projected/actual + 精度 + ownership。"""
|
|
1570
|
-
|
|
2111
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2112
|
+
if runtime is None:
|
|
2113
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2114
|
+
record = runtime.event_store.get(run_id)
|
|
1571
2115
|
plan = record.context_plan or {}
|
|
1572
2116
|
evidence = record.prompt_evidence or {}
|
|
1573
2117
|
return {
|
|
@@ -1621,7 +2165,10 @@ def create_studio_app(
|
|
|
1621
2165
|
|
|
1622
2166
|
@app.delete("/api/v1/sessions/{session_id}", status_code=204)
|
|
1623
2167
|
async def delete_studio_session(session_id: str):
|
|
1624
|
-
await studio.
|
|
2168
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2169
|
+
if runtime is None:
|
|
2170
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2171
|
+
await runtime.delete_session(session_id)
|
|
1625
2172
|
return Response(status_code=204)
|
|
1626
2173
|
|
|
1627
2174
|
@app.get("/api/v1/sessions/{session_id}/events")
|
|
@@ -1631,7 +2178,10 @@ def create_studio_app(
|
|
|
1631
2178
|
invocation_id: str | None = Query(default=None, alias="invocationId"),
|
|
1632
2179
|
limit: int = Query(default=100, ge=1, le=500),
|
|
1633
2180
|
):
|
|
1634
|
-
|
|
2181
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2182
|
+
if runtime is None:
|
|
2183
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2184
|
+
return await runtime.trajectory_page(
|
|
1635
2185
|
session_id,
|
|
1636
2186
|
before_seq_id=before_seq_id,
|
|
1637
2187
|
invocation_id=invocation_id,
|
|
@@ -1645,10 +2195,13 @@ def create_studio_app(
|
|
|
1645
2195
|
after_seq_id: int = Query(default=0, ge=0, alias="afterSeqId"),
|
|
1646
2196
|
invocation_id: str | None = Query(default=None, alias="invocationId"),
|
|
1647
2197
|
):
|
|
1648
|
-
await studio.
|
|
2198
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2199
|
+
if runtime is None:
|
|
2200
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2201
|
+
await runtime._require_runtime_session(session_id)
|
|
1649
2202
|
last = request.headers.get("Last-Event-ID")
|
|
1650
2203
|
cursor = int(last) if last and last.isdigit() else after_seq_id
|
|
1651
|
-
stream =
|
|
2204
|
+
stream = runtime.stream_trajectory(
|
|
1652
2205
|
session_id,
|
|
1653
2206
|
cursor,
|
|
1654
2207
|
invocation_id=invocation_id,
|
|
@@ -1719,15 +2272,61 @@ def create_studio_app(
|
|
|
1719
2272
|
async def list_runs(session_id: str | None = Query(default=None, alias="sessionId")):
|
|
1720
2273
|
return {"items": studio.event_store.list_runs(session_id=session_id)}
|
|
1721
2274
|
|
|
2275
|
+
@app.get("/api/v1/workspaces/runs")
|
|
2276
|
+
async def list_workspace_runs():
|
|
2277
|
+
"""后台入口:聚合所有已打开 workspace 的运行,并保留归属。"""
|
|
2278
|
+
return {"items": studio.all_runs()}
|
|
2279
|
+
|
|
2280
|
+
@app.get("/api/v1/workspaces/operations")
|
|
2281
|
+
async def list_workspace_operations():
|
|
2282
|
+
return {"items": studio.all_operations()}
|
|
2283
|
+
|
|
2284
|
+
@app.get("/api/v1/runs/{run_id}/documents/metadata")
|
|
2285
|
+
def run_document_metadata(run_id: str, path: str, request: Request):
|
|
2286
|
+
return document_metadata(studio, run_id, path, local=is_local_desktop_request(request))
|
|
2287
|
+
|
|
2288
|
+
@app.post("/api/v1/runs/{run_id}/documents/actions")
|
|
2289
|
+
def run_document_action(run_id: str, payload: NativeDocumentActionRequest, request: Request):
|
|
2290
|
+
return perform_document_action(
|
|
2291
|
+
studio, run_id, payload, local=is_local_desktop_request(request)
|
|
2292
|
+
)
|
|
2293
|
+
|
|
2294
|
+
@app.get("/api/v1/runs/{run_id}/documents/content")
|
|
2295
|
+
def run_document(run_id: str, path: str, preview: bool = False):
|
|
2296
|
+
file_path, content = read_document(studio, run_id, path)
|
|
2297
|
+
if preview:
|
|
2298
|
+
return JSONResponse(
|
|
2299
|
+
{"name": file_path.name, "content": content},
|
|
2300
|
+
headers={"Cache-Control": "no-store"},
|
|
2301
|
+
)
|
|
2302
|
+
return Response(
|
|
2303
|
+
content,
|
|
2304
|
+
media_type="text/markdown",
|
|
2305
|
+
headers={
|
|
2306
|
+
"Content-Disposition": "attachment; filename*=UTF-8''"
|
|
2307
|
+
+ quote(file_path.name),
|
|
2308
|
+
"X-Content-Type-Options": "nosniff",
|
|
2309
|
+
"Cache-Control": "no-store",
|
|
2310
|
+
},
|
|
2311
|
+
)
|
|
2312
|
+
|
|
1722
2313
|
@app.get("/api/v1/runs/{run_id}/events")
|
|
1723
2314
|
async def run_events(
|
|
1724
2315
|
run_id: str,
|
|
1725
2316
|
request: Request,
|
|
1726
2317
|
after: int = Query(default=0, ge=0),
|
|
2318
|
+
presentation_profile: Literal["flat-v1", "agent-block-v1"] | None = Query(
|
|
2319
|
+
default=None, alias="presentationProfile"
|
|
2320
|
+
),
|
|
1727
2321
|
):
|
|
1728
2322
|
last = request.headers.get("Last-Event-ID")
|
|
1729
2323
|
cursor = int(last) if last and last.isdigit() else after
|
|
1730
|
-
|
|
2324
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2325
|
+
if runtime is None:
|
|
2326
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2327
|
+
events = await runtime.run_service.events(
|
|
2328
|
+
run_id, after=cursor, presentation_profile=presentation_profile
|
|
2329
|
+
)
|
|
1731
2330
|
return _sse(events)
|
|
1732
2331
|
|
|
1733
2332
|
@app.get("/api/v1/traces/overview")
|
|
@@ -1742,6 +2341,10 @@ def create_studio_app(
|
|
|
1742
2341
|
status=status,
|
|
1743
2342
|
)
|
|
1744
2343
|
|
|
2344
|
+
@app.get("/api/v1/workspaces/traces")
|
|
2345
|
+
async def list_workspace_traces():
|
|
2346
|
+
return {"items": studio.all_traces()}
|
|
2347
|
+
|
|
1745
2348
|
@app.get("/api/v1/traces")
|
|
1746
2349
|
async def list_traces(
|
|
1747
2350
|
agent_id: str | None = Query(default=None, alias="agentId"),
|
|
@@ -1911,266 +2514,6 @@ def create_studio_app(
|
|
|
1911
2514
|
|
|
1912
2515
|
return await studio.cloud.delete(deployment_id)
|
|
1913
2516
|
|
|
1914
|
-
@app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions")
|
|
1915
|
-
async def list_cloud_chat_sessions(
|
|
1916
|
-
deployment_id: str,
|
|
1917
|
-
page: int = Query(default=1, ge=1),
|
|
1918
|
-
size: int = Query(default=50, ge=1, le=100),
|
|
1919
|
-
):
|
|
1920
|
-
"""List Server-owned sessions for this local deployment receipt only."""
|
|
1921
|
-
|
|
1922
|
-
return await studio.cloud.list_cloud_chat_sessions(deployment_id, page=page, size=size)
|
|
1923
|
-
|
|
1924
|
-
@app.get("/api/v1/deployments/{deployment_id}/cloud-chat/models")
|
|
1925
|
-
async def list_cloud_chat_models(deployment_id: str):
|
|
1926
|
-
"""List models through Studio's signed Server client."""
|
|
1927
|
-
|
|
1928
|
-
return await studio.cloud.list_cloud_chat_models(deployment_id)
|
|
1929
|
-
|
|
1930
|
-
@app.post(
|
|
1931
|
-
"/api/v1/deployments/{deployment_id}/cloud-chat/sessions",
|
|
1932
|
-
status_code=201,
|
|
1933
|
-
)
|
|
1934
|
-
async def create_cloud_chat_session(deployment_id: str):
|
|
1935
|
-
"""Create a cloud session via loopback-held AK/SK; no secret reaches JS."""
|
|
1936
|
-
|
|
1937
|
-
return await studio.cloud.create_cloud_chat_session(deployment_id)
|
|
1938
|
-
|
|
1939
|
-
@app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/messages")
|
|
1940
|
-
async def list_cloud_chat_messages(
|
|
1941
|
-
deployment_id: str,
|
|
1942
|
-
session_id: str,
|
|
1943
|
-
after_seq_id: int | None = Query(default=None, alias="afterSeqId", ge=0),
|
|
1944
|
-
limit: int = Query(default=100, ge=1, le=200),
|
|
1945
|
-
):
|
|
1946
|
-
return await studio.cloud.list_cloud_chat_messages(
|
|
1947
|
-
deployment_id,
|
|
1948
|
-
session_id=session_id,
|
|
1949
|
-
after_seq_id=after_seq_id,
|
|
1950
|
-
limit=limit,
|
|
1951
|
-
)
|
|
1952
|
-
|
|
1953
|
-
@app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events")
|
|
1954
|
-
async def list_cloud_chat_events(
|
|
1955
|
-
deployment_id: str,
|
|
1956
|
-
session_id: str,
|
|
1957
|
-
after_seq_id: int | None = Query(default=None, alias="afterSeqId", ge=0),
|
|
1958
|
-
offset: int | None = Query(default=None, ge=0),
|
|
1959
|
-
limit: int = Query(default=200, ge=1, le=1000),
|
|
1960
|
-
):
|
|
1961
|
-
return await studio.cloud.list_cloud_chat_events(
|
|
1962
|
-
deployment_id,
|
|
1963
|
-
session_id=session_id,
|
|
1964
|
-
after_seq_id=after_seq_id,
|
|
1965
|
-
offset=offset,
|
|
1966
|
-
limit=limit,
|
|
1967
|
-
)
|
|
1968
|
-
|
|
1969
|
-
@app.get("/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/events/stream")
|
|
1970
|
-
async def stream_cloud_chat_events(
|
|
1971
|
-
request: Request,
|
|
1972
|
-
deployment_id: str,
|
|
1973
|
-
session_id: str,
|
|
1974
|
-
after_seq_id: int = Query(default=0, alias="afterSeqId", ge=0),
|
|
1975
|
-
):
|
|
1976
|
-
"""Stream canonical cloud events to the loopback browser.
|
|
1977
|
-
|
|
1978
|
-
The public cloud control plane currently exposes cursor reads for this
|
|
1979
|
-
surface. Keep that cursor in the Studio backend and present one SSE
|
|
1980
|
-
response to the browser, so assistant deltas arrive before the durable
|
|
1981
|
-
terminal message projection without exposing cloud credentials to JS.
|
|
1982
|
-
"""
|
|
1983
|
-
|
|
1984
|
-
async def event_stream() -> AsyncIterator[str]:
|
|
1985
|
-
cursor = after_seq_id
|
|
1986
|
-
idle_polls = 0
|
|
1987
|
-
while not await request.is_disconnected():
|
|
1988
|
-
payload = await studio.cloud.list_cloud_chat_events(
|
|
1989
|
-
deployment_id,
|
|
1990
|
-
session_id=session_id,
|
|
1991
|
-
after_seq_id=cursor,
|
|
1992
|
-
limit=200,
|
|
1993
|
-
)
|
|
1994
|
-
events = payload.get("events") or []
|
|
1995
|
-
if not isinstance(events, list):
|
|
1996
|
-
events = []
|
|
1997
|
-
terminal = False
|
|
1998
|
-
emitted = False
|
|
1999
|
-
for event in events:
|
|
2000
|
-
if not isinstance(event, dict):
|
|
2001
|
-
continue
|
|
2002
|
-
event_payload = (
|
|
2003
|
-
event.get("payload") if isinstance(event.get("payload"), dict) else event
|
|
2004
|
-
)
|
|
2005
|
-
seq = int(
|
|
2006
|
-
event_payload.get("seq")
|
|
2007
|
-
or event_payload.get("seq_id")
|
|
2008
|
-
or event_payload.get("source_session_seq")
|
|
2009
|
-
or event.get("seq")
|
|
2010
|
-
or event.get("seq_id")
|
|
2011
|
-
or 0
|
|
2012
|
-
)
|
|
2013
|
-
if seq and seq <= cursor:
|
|
2014
|
-
continue
|
|
2015
|
-
if seq:
|
|
2016
|
-
cursor = max(cursor, seq)
|
|
2017
|
-
event_type = str(
|
|
2018
|
-
event.get("event_type")
|
|
2019
|
-
or event.get("eventType")
|
|
2020
|
-
or event_payload.get("event_type")
|
|
2021
|
-
or event_payload.get("eventType")
|
|
2022
|
-
or ""
|
|
2023
|
-
).lower()
|
|
2024
|
-
content = (
|
|
2025
|
-
event_payload.get("content")
|
|
2026
|
-
if isinstance(event_payload.get("content"), dict)
|
|
2027
|
-
else {}
|
|
2028
|
-
)
|
|
2029
|
-
status = str(event_payload.get("status") or content.get("status") or "").lower()
|
|
2030
|
-
event_is_terminal = event_type in {
|
|
2031
|
-
"run.completed",
|
|
2032
|
-
"run.complete",
|
|
2033
|
-
"run.succeeded",
|
|
2034
|
-
"run.failed",
|
|
2035
|
-
"run.cancelled",
|
|
2036
|
-
"run.expired",
|
|
2037
|
-
"run.error",
|
|
2038
|
-
} or (
|
|
2039
|
-
event_type in {"run_status", "run.status"}
|
|
2040
|
-
and status
|
|
2041
|
-
in {
|
|
2042
|
-
"completed",
|
|
2043
|
-
"complete",
|
|
2044
|
-
"succeeded",
|
|
2045
|
-
"success",
|
|
2046
|
-
"failed",
|
|
2047
|
-
"cancelled",
|
|
2048
|
-
"canceled",
|
|
2049
|
-
"expired",
|
|
2050
|
-
"error",
|
|
2051
|
-
"aborted",
|
|
2052
|
-
}
|
|
2053
|
-
)
|
|
2054
|
-
terminal = terminal or event_is_terminal
|
|
2055
|
-
emitted = True
|
|
2056
|
-
projected_event = dict(event)
|
|
2057
|
-
conversation_item = _cloud_event_conversation_item(
|
|
2058
|
-
event,
|
|
2059
|
-
session_id=session_id,
|
|
2060
|
-
)
|
|
2061
|
-
if conversation_item is not None:
|
|
2062
|
-
projected_event["conversationItem"] = conversation_item
|
|
2063
|
-
yield (
|
|
2064
|
-
(f"id: {seq}\n" if seq else "")
|
|
2065
|
-
+ "event: session.event\n"
|
|
2066
|
-
+ f"data: {json.dumps(projected_event, ensure_ascii=False)}\n\n"
|
|
2067
|
-
)
|
|
2068
|
-
if terminal or payload.get("session_deleted"):
|
|
2069
|
-
break
|
|
2070
|
-
idle_polls = 0 if emitted else idle_polls + 1
|
|
2071
|
-
if idle_polls and idle_polls % 20 == 0:
|
|
2072
|
-
yield ": keepalive\n\n"
|
|
2073
|
-
await asyncio.sleep(0.25)
|
|
2074
|
-
|
|
2075
|
-
return StreamingResponse(
|
|
2076
|
-
event_stream(),
|
|
2077
|
-
media_type="text/event-stream",
|
|
2078
|
-
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"},
|
|
2079
|
-
)
|
|
2080
|
-
|
|
2081
|
-
@app.delete(
|
|
2082
|
-
"/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}",
|
|
2083
|
-
status_code=204,
|
|
2084
|
-
)
|
|
2085
|
-
async def delete_cloud_chat_session(deployment_id: str, session_id: str):
|
|
2086
|
-
await studio.cloud.delete_cloud_chat_session(deployment_id, session_id=session_id)
|
|
2087
|
-
return Response(status_code=204)
|
|
2088
|
-
|
|
2089
|
-
@app.post(
|
|
2090
|
-
"/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/messages",
|
|
2091
|
-
status_code=202,
|
|
2092
|
-
)
|
|
2093
|
-
async def send_cloud_chat_message(
|
|
2094
|
-
deployment_id: str,
|
|
2095
|
-
session_id: str,
|
|
2096
|
-
payload: CloudChatMessageRequest,
|
|
2097
|
-
):
|
|
2098
|
-
"""Admit one cloud message through Server; response is a durable receipt."""
|
|
2099
|
-
|
|
2100
|
-
return await studio.cloud.send_cloud_chat_message(
|
|
2101
|
-
deployment_id,
|
|
2102
|
-
session_id=session_id,
|
|
2103
|
-
content=payload.content,
|
|
2104
|
-
model=payload.model,
|
|
2105
|
-
model_options=payload.model_options,
|
|
2106
|
-
tool_approval_mode=payload.tool_approval_mode,
|
|
2107
|
-
collaboration_mode=payload.collaboration_mode,
|
|
2108
|
-
goal_objective=payload.goal_objective,
|
|
2109
|
-
)
|
|
2110
|
-
|
|
2111
|
-
@app.post(
|
|
2112
|
-
"/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/messages/stream"
|
|
2113
|
-
)
|
|
2114
|
-
async def stream_cloud_chat_message(
|
|
2115
|
-
request: Request,
|
|
2116
|
-
deployment_id: str,
|
|
2117
|
-
session_id: str,
|
|
2118
|
-
payload: CloudChatMessageRequest,
|
|
2119
|
-
):
|
|
2120
|
-
"""Proxy one signed foreground RunAgent SSE response to loopback UI."""
|
|
2121
|
-
|
|
2122
|
-
upstream = await studio.cloud.stream_cloud_chat_message(
|
|
2123
|
-
deployment_id,
|
|
2124
|
-
session_id=session_id,
|
|
2125
|
-
content=payload.content,
|
|
2126
|
-
model=payload.model,
|
|
2127
|
-
model_options=payload.model_options,
|
|
2128
|
-
tool_approval_mode=payload.tool_approval_mode,
|
|
2129
|
-
collaboration_mode=payload.collaboration_mode,
|
|
2130
|
-
goal_objective=payload.goal_objective,
|
|
2131
|
-
)
|
|
2132
|
-
|
|
2133
|
-
async def proxy_stream() -> AsyncIterator[bytes]:
|
|
2134
|
-
try:
|
|
2135
|
-
while not await request.is_disconnected():
|
|
2136
|
-
try:
|
|
2137
|
-
chunk = await anext(upstream)
|
|
2138
|
-
except StopAsyncIteration:
|
|
2139
|
-
break
|
|
2140
|
-
if await request.is_disconnected():
|
|
2141
|
-
break
|
|
2142
|
-
yield chunk
|
|
2143
|
-
finally:
|
|
2144
|
-
close = getattr(upstream, "aclose", None)
|
|
2145
|
-
if close is not None:
|
|
2146
|
-
await close()
|
|
2147
|
-
|
|
2148
|
-
return StreamingResponse(
|
|
2149
|
-
proxy_stream(),
|
|
2150
|
-
media_type="text/event-stream",
|
|
2151
|
-
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
2152
|
-
)
|
|
2153
|
-
|
|
2154
|
-
@app.post(
|
|
2155
|
-
"/api/v1/deployments/{deployment_id}/cloud-chat/sessions/{session_id}/interactions",
|
|
2156
|
-
status_code=202,
|
|
2157
|
-
)
|
|
2158
|
-
async def submit_cloud_chat_interaction(
|
|
2159
|
-
deployment_id: str,
|
|
2160
|
-
session_id: str,
|
|
2161
|
-
payload: CloudChatInteractionSubmitRequest,
|
|
2162
|
-
):
|
|
2163
|
-
return await studio.cloud.submit_cloud_chat_interaction(
|
|
2164
|
-
deployment_id,
|
|
2165
|
-
session_id=session_id,
|
|
2166
|
-
run_id=payload.run_id,
|
|
2167
|
-
interaction_id=payload.interaction_id,
|
|
2168
|
-
expected_revision=payload.expected_revision,
|
|
2169
|
-
action=payload.action,
|
|
2170
|
-
response=payload.response,
|
|
2171
|
-
idempotency_key=payload.idempotency_key,
|
|
2172
|
-
)
|
|
2173
|
-
|
|
2174
2517
|
@app.post("/api/v1/deployments/{deployment_id}:rollback", status_code=202)
|
|
2175
2518
|
async def rollback_deployment(
|
|
2176
2519
|
deployment_id: str,
|
|
@@ -2185,11 +2528,17 @@ def create_studio_app(
|
|
|
2185
2528
|
|
|
2186
2529
|
@app.get("/api/v1/operations/{operation_id}")
|
|
2187
2530
|
async def get_operation(operation_id: str):
|
|
2188
|
-
|
|
2531
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2532
|
+
if runtime is None:
|
|
2533
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2534
|
+
return runtime.operations.get(operation_id)
|
|
2189
2535
|
|
|
2190
2536
|
@app.post("/api/v1/operations/{operation_id}:cancel")
|
|
2191
2537
|
async def cancel_operation(operation_id: str):
|
|
2192
|
-
|
|
2538
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2539
|
+
if runtime is None:
|
|
2540
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2541
|
+
return runtime.operations.cancel(operation_id)
|
|
2193
2542
|
|
|
2194
2543
|
@app.get("/api/v1/operations/{operation_id}/events")
|
|
2195
2544
|
async def operation_events(
|
|
@@ -2199,7 +2548,10 @@ def create_studio_app(
|
|
|
2199
2548
|
):
|
|
2200
2549
|
last = request.headers.get("Last-Event-ID")
|
|
2201
2550
|
cursor = int(last) if last and last.isdigit() else after
|
|
2202
|
-
|
|
2551
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2552
|
+
if runtime is None:
|
|
2553
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2554
|
+
events = runtime.operations.events(operation_id, after=cursor)
|
|
2203
2555
|
if "application/json" in request.headers.get("Accept", ""):
|
|
2204
2556
|
return {"items": events}
|
|
2205
2557
|
return _sse(events)
|
|
@@ -2209,14 +2561,27 @@ def create_studio_app(
|
|
|
2209
2561
|
studio,
|
|
2210
2562
|
runtime_model_catalog=runtime_model_catalog,
|
|
2211
2563
|
)
|
|
2564
|
+
register_cloud_chat_routes(app, studio)
|
|
2565
|
+
register_a2a_routes(app, studio)
|
|
2212
2566
|
register_memory_routes(app, studio)
|
|
2213
2567
|
register_resource_connection_routes(app, studio)
|
|
2214
2568
|
register_plugin_routes(app, studio)
|
|
2569
|
+
async def workspace_plugin_api(scope, receive, send):
|
|
2570
|
+
# The plugin registry belongs to the active workspace. Mounting the
|
|
2571
|
+
# initial service registry directly would keep lifecycle/routes pinned
|
|
2572
|
+
# to the first folder after a workspace switch.
|
|
2573
|
+
await studio.active.workspace_plugins.api(scope, receive, send)
|
|
2574
|
+
|
|
2575
|
+
app.mount("/api/v1", workspace_plugin_api, name="workspace-plugin-api")
|
|
2215
2576
|
|
|
2216
2577
|
from ksadk.studio.dsh_application import register_dsh_application
|
|
2217
2578
|
|
|
2218
2579
|
register_dsh_application(
|
|
2219
|
-
app,
|
|
2580
|
+
app,
|
|
2581
|
+
studio,
|
|
2582
|
+
session_secret=session_secret,
|
|
2583
|
+
security_enabled=security_enabled,
|
|
2584
|
+
fallback_url="/studio-shell/",
|
|
2220
2585
|
)
|
|
2221
2586
|
|
|
2222
2587
|
return app
|