agentengine-sdk-python 0.8.3__py3-none-any.whl → 0.8.5__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.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/METADATA +13 -9
- agentengine_sdk_python-0.8.5.dist-info/RECORD +1296 -0
- ksadk/_build_provenance.json +1 -1
- ksadk/_process.py +83 -0
- ksadk/_str_enum.py +17 -0
- ksadk/a2ui/core.py +3 -3
- ksadk/api/client.py +111 -91
- ksadk/builders/code_builder.py +74 -21
- ksadk/builders/framework_requirements.py +22 -3
- ksadk/builders/ks3_uploader.py +36 -7
- ksadk/builders/managed_runtime_builder.py +1 -0
- ksadk/cli/__init__.py +68 -3
- ksadk/cli/cmd_config.py +4 -4
- ksadk/cli/cmd_create.py +12 -12
- ksadk/cli/cmd_hermes.py +24 -2
- ksadk/cli/cmd_invoke.py +28 -5
- ksadk/cli/cmd_managed_runtime.py +13 -1
- ksadk/cli/cmd_openclaw.py +26 -1
- ksadk/cli/cmd_plugin.py +76 -13
- ksadk/cli/cmd_studio.py +64 -16
- ksadk/cli/cmd_web.py +2 -5
- ksadk/cli/openclaw_env.py +1 -1
- ksadk/cli/resource_common.py +26 -0
- ksadk/cli/runtime_bootstrap.py +23 -1
- ksadk/codex/client.py +425 -96
- ksadk/codex/projection.py +24 -0
- ksadk/codex/runtime.py +56 -298
- ksadk/common/auth.py +16 -10
- ksadk/configs/__init__.py +1 -1
- ksadk/configs/env_registry.py +153 -31
- ksadk/configs/env_registry_studio.py +86 -0
- ksadk/configs/global_config.py +1 -1
- ksadk/configs/settings.py +3 -3
- ksadk/connector/__init__.py +17 -0
- ksadk/connector/channel.py +477 -0
- ksadk/context_engine/capabilities.py +52 -4
- ksadk/conversations/attachment_storage.py +10 -3
- ksadk/conversations/attachments.py +16 -5
- ksadk/conversations/message_projection.py +133 -21
- ksadk/conversations/normalize.py +28 -10
- ksadk/conversations/projector.py +4 -6
- ksadk/conversations/runtime_baseline.py +37 -0
- ksadk/conversations/runtime_invocation.py +22 -4
- ksadk/conversations/runtime_observability.py +39 -10
- ksadk/conversations/runtime_payloads.py +9 -0
- ksadk/conversations/runtime_persistence.py +105 -9
- ksadk/conversations/runtime_preparation.py +42 -33
- ksadk/conversations/runtime_resume.py +50 -2
- ksadk/conversations/runtime_stream_events.py +34 -35
- ksadk/conversations/runtime_streaming.py +33 -7
- ksadk/deployment/env_forward.py +2 -2
- ksadk/deployment/providers/serverless.py +1 -1
- ksadk/events/adapters/_codex_items.py +16 -8
- ksadk/events/adapters/_codex_validators.py +18 -7
- ksadk/events/adapters/_langgraph_support.py +34 -0
- ksadk/events/adapters/langgraph.py +15 -1
- ksadk/events/canonical_store.py +3 -1
- ksadk/events/projections.py +1 -1
- ksadk/events/session_event.py +2 -2
- ksadk/harness/__init__.py +14 -0
- ksadk/harness/app.py +11 -0
- ksadk/harness/artifact_store.py +213 -0
- ksadk/harness/capabilities.py +115 -0
- ksadk/harness/capability_runtime.py +237 -0
- ksadk/harness/closure_contract.py +92 -0
- ksadk/harness/compaction_record.py +122 -0
- ksadk/harness/compiler.py +284 -0
- ksadk/harness/config.py +2 -2
- ksadk/harness/conformance/__init__.py +33 -0
- ksadk/harness/conformance/contract.py +506 -0
- ksadk/harness/conformance/fixtures.py +102 -0
- ksadk/harness/context_engine.py +403 -0
- ksadk/harness/context_maintenance.py +259 -0
- ksadk/harness/context_manifest.py +188 -0
- ksadk/harness/context_tuning.py +168 -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 +42 -0
- ksadk/harness/engine/context_pipeline.py +579 -0
- ksadk/harness/engine/graph_builder.py +859 -0
- ksadk/harness/engine/langgraph.py +931 -0
- ksadk/harness/engine/mcp_disclosure.py +750 -0
- ksadk/harness/engine/policy_runtime.py +70 -0
- ksadk/harness/engine/postgres_checkpointer.py +63 -0
- ksadk/harness/engine/run_control_bridge.py +80 -0
- ksadk/harness/engine/run_types.py +88 -0
- ksadk/harness/engine/skill_disclosure.py +189 -0
- ksadk/harness/engine/spans.py +41 -0
- ksadk/harness/engine/subagents.py +343 -0
- ksadk/harness/engine/thread_ids.py +112 -0
- ksadk/harness/engine/tool_dispatch.py +144 -0
- ksadk/harness/event_tree.py +212 -0
- ksadk/harness/events.py +461 -0
- ksadk/harness/execution_policy.py +94 -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 +454 -0
- ksadk/harness/loop/tools.py +762 -0
- ksadk/harness/managed_runtime.py +884 -0
- ksadk/harness/mcp_matrix.py +474 -0
- ksadk/harness/mcp_runtime.py +471 -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/model_capability.py +253 -0
- ksadk/harness/model_provider.py +220 -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/prompt_cache.py +70 -0
- ksadk/harness/public_activity.py +154 -0
- ksadk/harness/readiness.py +249 -0
- ksadk/harness/reasoner.py +466 -13
- ksadk/harness/release_readiness.py +140 -0
- ksadk/harness/resource_ref.py +69 -0
- ksadk/harness/run_control.py +668 -0
- ksadk/harness/runtime.py +171 -136
- ksadk/harness/runtime_capabilities.py +158 -0
- ksadk/harness/runtime_server.py +514 -0
- ksadk/harness/sandbox_adapters.py +739 -0
- ksadk/harness/sandbox_backend.py +530 -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/session_store.py +243 -0
- ksadk/harness/skill_composition.py +212 -0
- ksadk/harness/skill_feedback.py +123 -0
- ksadk/harness/skill_matrix.py +233 -0
- ksadk/harness/skill_runtime.py +259 -0
- ksadk/harness/spec.py +332 -0
- ksadk/harness/state.py +153 -0
- ksadk/harness/strategies.py +149 -0
- ksadk/harness/subagent.py +253 -0
- ksadk/harness/tool_policy.py +131 -0
- ksadk/harness/tool_receipts.py +96 -0
- ksadk/harness/tool_reliability.py +81 -0
- ksadk/harness/tools.py +38 -13
- ksadk/harness/user_errors.py +69 -0
- ksadk/harness/working_context.py +81 -0
- ksadk/harness/working_context_patch.py +99 -0
- ksadk/identity/resolver.py +18 -0
- ksadk/interaction/__init__.py +1 -1
- ksadk/interaction/ledger.py +1 -1
- ksadk/interaction/provider.py +2 -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 +2 -1
- ksadk/kernel/__init__.py +10 -0
- ksadk/kernel/approval_presentation.py +91 -0
- ksadk/kernel/authorization.py +1 -1
- ksadk/kernel/bootstrap.py +114 -106
- ksadk/kernel/contract_fingerprints.py +1 -1
- ksadk/kernel/contracts.py +5 -0
- ksadk/kernel/control.py +32 -1
- ksadk/kernel/execution_grants.py +221 -0
- ksadk/kernel/execution_grants_memory.py +133 -0
- ksadk/kernel/execution_grants_postgres.py +217 -0
- ksadk/kernel/execution_grants_sqlite.py +209 -0
- ksadk/kernel/ingress.py +42 -29
- ksadk/kernel/mapping.py +1 -1
- ksadk/kernel/memory_store.py +24 -11
- ksadk/kernel/postgres_store.py +63 -33
- ksadk/kernel/recovery.py +78 -14
- ksadk/kernel/sql/001_agent_kernel.sql +23 -0
- ksadk/kernel/sqlite_store.py +331 -25
- ksadk/kernel/state.py +2 -3
- ksadk/kernel/store.py +72 -2
- ksadk/kernel/worker.py +144 -51
- ksadk/kernel/worker_history.py +72 -0
- ksadk/kernel/worker_identity.py +47 -0
- ksadk/knowledge_base/client.py +57 -27
- ksadk/mcp_runtime/__init__.py +12 -4
- ksadk/memory/adk/backends/sdk_ltm_backend.py +161 -41
- ksadk/memory/adk/resilient_session_service.py +25 -17
- ksadk/memory/adk/short_term_memory.py +26 -9
- ksadk/memory/coordinator.py +22 -6
- ksadk/memory/extraction.py +40 -1
- ksadk/memory/models.py +84 -5
- ksadk/memory/provider_resolver.py +8 -0
- ksadk/memory/providers/local_postgres.py +200 -0
- ksadk/memory/providers/local_sqlite.py +42 -3
- ksadk/memory/retrieval.py +189 -0
- ksadk/memory/store_adapter.py +150 -0
- ksadk/model_policy.py +2 -2
- ksadk/model_proxy/detect.py +254 -0
- ksadk/model_proxy/server.py +14 -7
- ksadk/model_proxy/transform.py +40 -2
- ksadk/plugins/__init__.py +5 -1
- ksadk/plugins/artifacts.py +275 -0
- ksadk/plugins/bridges/__init__.py +4 -2
- ksadk/plugins/bridges/codex.py +120 -13
- ksadk/plugins/bridges/dsh.py +351 -156
- ksadk/plugins/builtins.py +72 -35
- ksadk/plugins/bundle_security.py +28 -4
- ksadk/plugins/codex_manifest.py +983 -0
- ksadk/plugins/companion_artifacts.py +83 -0
- ksadk/plugins/companions.py +368 -0
- ksadk/plugins/composition.py +8 -0
- ksadk/plugins/contracts.py +119 -1
- ksadk/plugins/delivery.py +153 -0
- ksadk/plugins/dsh_channels.py +156 -0
- ksadk/plugins/dsh_home.py +140 -0
- ksadk/plugins/dsh_installation_digest.py +71 -0
- ksadk/plugins/dsh_teams.py +105 -0
- ksadk/plugins/dsh_toolchain.py +203 -32
- ksadk/plugins/ecosystem_probe.py +6 -6
- ksadk/plugins/execution_host.py +99 -0
- ksadk/plugins/host.py +102 -39
- ksadk/plugins/kernel_adapter.py +205 -0
- ksadk/plugins/providers/__init__.py +23 -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/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/index.mjs +53 -0
- ksadk/plugins/providers/bundles/dsh-knowledge/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-memory/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-memory/index.mjs +175 -0
- ksadk/plugins/providers/bundles/dsh-memory/package.json +16 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/client.mjs +166 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/index.mjs +9 -0
- ksadk/plugins/providers/bundles/dsh-platform-resources/package.json +12 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/index.mjs +125 -0
- ksadk/plugins/providers/bundles/dsh-skill-center/package.json +16 -0
- 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/cordis.patch.yml +3 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/index.mjs +920 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-capability-host/package.json +27 -0
- 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 +115 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/index.mjs +19 -0
- ksadk/plugins/providers/bundles/ksadk-dsh-studio/package.json +7 -0
- ksadk/plugins/providers/bundles/ksadk-harness/index.mjs +1 -1
- ksadk/plugins/providers/codex.py +344 -70
- ksadk/plugins/providers/codex_native.py +368 -0
- ksadk/plugins/providers/codex_turn.py +301 -0
- ksadk/plugins/providers/dsh_capabilities.py +1450 -0
- ksadk/plugins/providers/dsh_mcp.py +467 -0
- ksadk/plugins/providers/harness.py +294 -141
- ksadk/plugins/providers/harness_delegation.py +593 -0
- ksadk/plugins/providers/harness_managed.py +456 -0
- ksadk/plugins/providers/harness_tools.py +326 -0
- ksadk/plugins/providers/mcp_projection.py +150 -0
- ksadk/plugins/providers/platform_resources.py +657 -0
- ksadk/plugins/providers/shipped_dsh.py +4 -1
- ksadk/plugins/resolver.py +8 -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 +680 -0
- ksadk/plugins/teams/artifacts.py +60 -0
- ksadk/plugins/teams/context.py +96 -0
- ksadk/plugins/teams/contracts.py +136 -0
- ksadk/plugins/teams/domain.py +1427 -0
- ksadk/plugins/teams/domain_values.py +24 -0
- ksadk/plugins/teams/errors.py +13 -0
- ksadk/plugins/teams/migration.py +311 -0
- ksadk/plugins/teams/migration_cli.py +322 -0
- ksadk/plugins/teams/postgres_store.py +138 -0
- ksadk/plugins/teams/runtime.py +777 -0
- ksadk/plugins/teams/source_projection.py +84 -0
- ksadk/plugins/teams/store.py +311 -0
- ksadk/plugins/teams/task_decisions.py +423 -0
- ksadk/plugins/teams/transport.py +91 -0
- ksadk/plugins/teams/workspaces.py +255 -0
- ksadk/resource_runtime/__init__.py +4 -0
- ksadk/resource_runtime/broker.py +616 -0
- ksadk/resource_runtime/build_artifacts.py +165 -0
- ksadk/resource_runtime/contracts.py +138 -0
- ksadk/resource_runtime/discovery_receipts.py +100 -0
- ksadk/resource_runtime/discovery_skills.py +172 -0
- ksadk/resource_runtime/errors.py +6 -0
- ksadk/resource_runtime/ipc.py +142 -0
- ksadk/resource_runtime/kernel_approval.py +165 -0
- ksadk/resource_runtime/knowledge.py +114 -0
- ksadk/resource_runtime/langgraph.py +94 -0
- ksadk/resource_runtime/leases.py +191 -0
- ksadk/resource_runtime/managed_projection.py +186 -0
- ksadk/resource_runtime/mcp_server.py +138 -0
- ksadk/resource_runtime/memory_provider.py +318 -0
- ksadk/resource_runtime/memory_receipts.py +34 -0
- ksadk/resource_runtime/operation_ledger.py +211 -0
- ksadk/resource_runtime/plugin_config.py +48 -0
- ksadk/resource_runtime/policy_authorization.py +54 -0
- ksadk/resource_runtime/process.py +110 -0
- ksadk/resource_runtime/skill_artifacts.py +153 -0
- ksadk/resource_runtime/skill_runtime.py +42 -0
- ksadk/resource_runtime/skill_workspace.py +118 -0
- ksadk/resource_runtime/skills.py +215 -0
- ksadk/resource_runtime/snapshots.py +180 -0
- ksadk/resource_runtime/socket_server.py +103 -0
- ksadk/resource_runtime/supervisor.py +380 -0
- ksadk/resource_runtime/worker.py +504 -0
- ksadk/runners/_langgraph_runner_streams.py +182 -38
- ksadk/runners/_langgraph_state_reader.py +106 -0
- ksadk/runners/_session_identity.py +285 -0
- ksadk/runners/adk_runner.py +166 -63
- ksadk/runners/base_runner.py +29 -1
- ksadk/runners/langgraph_runner.py +542 -195
- ksadk/runners/patch_langchain.py +47 -0
- ksadk/runners/usage_accumulator.py +11 -3
- ksadk/runtime/_runner_adapter/stream_mapping.py +194 -20
- ksadk/runtime/adapter.py +2 -0
- ksadk/runtime/conversation_execution.py +117 -17
- ksadk/runtime/executor.py +87 -3
- ksadk/runtime/factory.py +65 -274
- ksadk/runtime/framework_adapters.py +23 -0
- ksadk/runtime/preprocessing.py +21 -5
- ksadk/runtime/runner_adapter.py +106 -18
- ksadk/runtime/skill_eval_result.py +36 -0
- ksadk/runtime/timing.py +46 -0
- ksadk/runtime/usage.py +49 -18
- ksadk/runtime_context.py +142 -2
- ksadk/sandbox/backends/e2b.py +288 -25
- ksadk/sandbox/backends/local_process.py +72 -39
- ksadk/sandbox/base.py +64 -1
- ksadk/sandbox/diagnostics.py +82 -0
- ksadk/sandbox/e2b_connection.py +66 -0
- ksadk/sandbox/local_controls.py +746 -0
- ksadk/sandbox/local_launcher.py +90 -0
- ksadk/scheduler/dispatcher.py +1 -1
- ksadk/scheduler/sqlite_store.py +18 -0
- ksadk/server/composition.py +2 -0
- ksadk/server/factory.py +5 -0
- ksadk/server/invocation_identity.py +118 -0
- ksadk/server/persistence_capability.py +516 -0
- ksadk/server/routes/common.py +32 -3
- ksadk/server/routes/control.py +271 -52
- ksadk/server/routes/dependencies.py +16 -0
- ksadk/server/routes/kernel_ingress.py +9 -1
- ksadk/server/routes/misc.py +233 -25
- ksadk/server/routes/models.py +47 -4
- ksadk/server/routes/openai_compat.py +76 -13
- ksadk/server/routes/projection.py +252 -12
- ksadk/server/routes/run.py +106 -35
- ksadk/server/routes/sessions.py +491 -138
- ksadk/server/routes/streaming.py +43 -9
- ksadk/server/routes/workspace.py +130 -21
- ksadk/server/static/assets/{ArtifactsPanel-10GPXIJ6.js → ArtifactsPanel-C1YoaKhx.js} +1 -1
- ksadk/server/static/assets/{CodeBlock-BXk1l-G1.js → CodeBlock-DHuAWfr5.js} +10 -7
- ksadk/server/static/assets/MathMessageMarkdown-cvdrBwYr.js +8 -0
- ksadk/server/static/assets/{MermaidBlock--OEYoXIJ.js → MermaidBlock-DeBkbJvI.js} +9 -9
- ksadk/server/static/assets/{NativeTerminalPanel-DrEe1syq.js → NativeTerminalPanel-oJj44_sV.js} +1 -1
- ksadk/server/static/assets/{abnfDiagram-VCTEODGH-eeTFJLvo.js → abnfDiagram-VCTEODGH-Dhfv25o2.js} +1 -1
- ksadk/server/static/assets/{arc-S3ZNbIAd.js → arc-C35w-pn1.js} +1 -1
- ksadk/server/static/assets/architecture-7GRP2DOG-BCsa26zi.js +1 -0
- ksadk/server/static/assets/{architectureDiagram-5GKGNRK7-CRjgEJDX.js → architectureDiagram-5GKGNRK7-FoMY_u6D.js} +1 -1
- ksadk/server/static/assets/{blockDiagram-NRAW4CY4-C7bsBoNH.js → blockDiagram-NRAW4CY4-zD4Rt7oE.js} +1 -1
- ksadk/server/static/assets/{c4Diagram-UCG6FXSJ-BX3c33Ob.js → c4Diagram-UCG6FXSJ-BCtGGkhN.js} +1 -1
- ksadk/server/static/assets/channel-_KDifNys.js +1 -0
- ksadk/server/static/assets/chunk-2Q5K7J3B-HdVkJ9F0.js +1 -0
- ksadk/server/static/assets/{chunk-5VM5RSS4-bZ7ws-8m.js → chunk-5VM5RSS4-C2Ms13_k.js} +1 -1
- ksadk/server/static/assets/{chunk-F27PBJKO-D2r0pvhY.js → chunk-F27PBJKO-BoTj-qgx.js} +1 -1
- ksadk/server/static/assets/{chunk-G27WJ6UU-CZwF3oUP.js → chunk-G27WJ6UU-DOMyyjHH.js} +1 -1
- ksadk/server/static/assets/{chunk-JWPE2WC7-DigFYCML.js → chunk-JWPE2WC7-DbJJqDli.js} +1 -1
- ksadk/server/static/assets/{chunk-LCL6LL3I-CnorGV5q.js → chunk-LCL6LL3I-CLuRCt_W.js} +1 -1
- ksadk/server/static/assets/{chunk-POPQ4Y6H-CexntQA-.js → chunk-POPQ4Y6H-D0Dz847e.js} +1 -1
- ksadk/server/static/assets/{chunk-RHFEMEQ7-CHTC7UxA.js → chunk-RHFEMEQ7-BWSRzEcd.js} +1 -1
- ksadk/server/static/assets/{chunk-SVP7TREG-BC1EWt_-.js → chunk-SVP7TREG-CPoHqkCY.js} +1 -1
- ksadk/server/static/assets/{chunk-XXDRQBXY-BTG24xN0.js → chunk-XXDRQBXY-Bx1jS-X-.js} +1 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-BVCW3ZqZ.js +1 -0
- ksadk/server/static/assets/{cose-bilkent-JH36ORCC-CkonRdAS.js → cose-bilkent-JH36ORCC-LzyWm4m0.js} +1 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-CNXjFctL.js +1 -0
- ksadk/server/static/assets/{cynefinDiagram-5FMLGOSQ-DEOCBe15.js → cynefinDiagram-5FMLGOSQ-BlW_bHED.js} +1 -1
- ksadk/server/static/assets/{dagre-3AP2YEHR-DBThPuLa.js → dagre-3AP2YEHR-Bu_S86_i.js} +1 -1
- ksadk/server/static/assets/{dagre-ClTPrTht.js → dagre-B7nCawed.js} +1 -1
- ksadk/server/static/assets/{diagram-S7CK7UJ4-DsZHrnpJ.js → diagram-S7CK7UJ4-W_Zow2Km.js} +1 -1
- ksadk/server/static/assets/{diagram-UQ7AKVKN-BJR4nhVr.js → diagram-UQ7AKVKN-CLIKAHON.js} +1 -1
- ksadk/server/static/assets/{diagram-VSXAHHWV-xzcERX0a.js → diagram-VSXAHHWV-Dv6_QAlN.js} +1 -1
- ksadk/server/static/assets/{diagram-VX7I27RA-tn2xM1xu.js → diagram-VX7I27RA-BWAWRDtZ.js} +1 -1
- ksadk/server/static/assets/{diagram-Z3DM3KII-BZPGBkw5.js → diagram-Z3DM3KII-XA_rWMss.js} +1 -1
- ksadk/server/static/assets/dist-0X_j2Rcc.js +1 -0
- ksadk/server/static/assets/{dist-4zN1_tq5.js → dist-1nXCdsej.js} +1 -1
- ksadk/server/static/assets/{dist-M67Hwu0n.js → dist-2vL2sAdF.js} +1 -1
- ksadk/server/static/assets/{dist-BJLUwH6W.js → dist-B3bA05-e.js} +1 -1
- ksadk/server/static/assets/{dist-8VWI-2bZ.js → dist-BLpRy_Yx.js} +1 -1
- ksadk/server/static/assets/{dist-D1V3f1B4.js → dist-BO_UwatH.js} +1 -1
- ksadk/server/static/assets/{dist-Cq4OL6nO.js → dist-BdNFAney.js} +1 -1
- ksadk/server/static/assets/{dist-DfGFrb0v.js → dist-C0J5_3qM.js} +1 -1
- ksadk/server/static/assets/{dist-DyqV4fL4.js → dist-CGt_UGeO.js} +1 -1
- ksadk/server/static/assets/{dist-DjhwGUgZ.js → dist-CIRMvUM4.js} +1 -1
- ksadk/server/static/assets/{dist-B1oWRmrH.js → dist-CIpWk_5f.js} +1 -1
- ksadk/server/static/assets/{dist-CXpH_Rdd.js → dist-CPyieXEf.js} +1 -1
- ksadk/server/static/assets/{dist-Btyo4vX4.js → dist-D-92S-Fd.js} +1 -1
- ksadk/server/static/assets/{dist-u8tVH5Ak.js → dist-DNKuMzWc.js} +1 -1
- ksadk/server/static/assets/{dist-DQAB0qn_.js → dist-DWfdmz9s.js} +2 -2
- ksadk/server/static/assets/{dist-B-46q3Hk.js → dist-DppE_r-D.js} +1 -1
- ksadk/server/static/assets/{dist-C71CsujO.js → dist-DyG6Ya-z.js} +1 -1
- ksadk/server/static/assets/{dist-DJmCPRVB.js → dist-M-SrdhhZ.js} +1 -1
- ksadk/server/static/assets/{dist-Bbwqa8TG.js → dist-mqD5TZup.js} +1 -1
- ksadk/server/static/assets/{dist-BI1qQH4n.js → dist-n3n6t_FO.js} +1 -1
- ksadk/server/static/assets/{dist-DUwKa_l6.js → dist-qe8xjesy.js} +1 -1
- ksadk/server/static/assets/{dist-B0gdk4rl.js → dist-t6MzE0jU.js} +1 -1
- ksadk/server/static/assets/{ebnfDiagram-PWID7BFC-DVfMsLge.js → ebnfDiagram-PWID7BFC-BfCzF1Xi.js} +1 -1
- ksadk/server/static/assets/{erDiagram-SSCWMZ5O-CWEZSYaw.js → erDiagram-SSCWMZ5O-Dpz9_0zn.js} +1 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-B5-8RH9c.js +1 -0
- ksadk/server/static/assets/flowDiagram-A5DVABFB-BppFxEKw.js +1 -0
- ksadk/server/static/assets/{ganttDiagram-EL5Y4UJY-TWIxoyYL.js → ganttDiagram-EL5Y4UJY-DDaG1f4_.js} +1 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-B-AhYj4C.js +1 -0
- ksadk/server/static/assets/{gitGraphDiagram-WWUBYQGX-DDh2hd2S.js → gitGraphDiagram-WWUBYQGX-DcxzRwYC.js} +1 -1
- ksadk/server/static/assets/index-BMd2mucF.css +2 -0
- ksadk/server/static/assets/index-D5qyyhTH.js +244 -0
- ksadk/server/static/assets/info-A6RAGUB7-0uiKrC35.js +1 -0
- ksadk/server/static/assets/{infoDiagram-RXCK75RN-CgoyWiDR.js → infoDiagram-RXCK75RN-CYMdn6lQ.js} +1 -1
- ksadk/server/static/assets/{ishikawaDiagram-5VMMS53U-CyRIu_om.js → ishikawaDiagram-5VMMS53U-CLHFAD6c.js} +1 -1
- ksadk/server/static/assets/{journeyDiagram-EYS64GPL-DN5JXHzN.js → journeyDiagram-EYS64GPL-BHSKQGAl.js} +1 -1
- ksadk/server/static/assets/{kanban-definition-3QL26DDD-CNP3ui66.js → kanban-definition-3QL26DDD-D5W3tjTT.js} +1 -1
- ksadk/server/static/assets/{katex-DWEzQy1d.js → katex-mtjOi4KM.js} +1 -1
- ksadk/server/static/assets/{linear-C-qHp7d2.js → linear-BETqsxE_.js} +1 -1
- ksadk/server/static/assets/{mermaid-parser.core-Cl-K943T.js → mermaid-parser.core-DPWrvs90.js} +2 -2
- ksadk/server/static/assets/{mindmap-definition-FBJOCRG2-D5DB5mYm.js → mindmap-definition-FBJOCRG2-CJG2mfBP.js} +1 -1
- ksadk/server/static/assets/packet-AYTQ26CC-BVTmZ_cw.js +1 -0
- ksadk/server/static/assets/{pegDiagram-XKGWAZYB-BQVc9ia_.js → pegDiagram-XKGWAZYB-GjAPNaqn.js} +1 -1
- ksadk/server/static/assets/pie-WAS4IAKB-DyfxBU7V.js +1 -0
- ksadk/server/static/assets/{pieDiagram-E7YTZNPT-B6UCAvtY.js → pieDiagram-E7YTZNPT-ToIewrqr.js} +1 -1
- ksadk/server/static/assets/{quadrantDiagram-AXDQQJYC-mIr2d3eb.js → quadrantDiagram-AXDQQJYC-4d78KiEY.js} +1 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-FFontjL2.js +1 -0
- ksadk/server/static/assets/railroad-74A4TZTK-D0Uidzen.js +1 -0
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-BOo_9T2h.js +1 -0
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-D6-BjW7Z.js +1 -0
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-CXx__yMm.js +1 -0
- ksadk/server/static/assets/{railroadDiagram-O6MQD6OU-Dt3FFDmK.js → railroadDiagram-O6MQD6OU-DKzx4xfv.js} +1 -1
- ksadk/server/static/assets/{requirementDiagram-EFPCY7ZU-Cz_vQtgF.js → requirementDiagram-EFPCY7ZU-CJYljxQS.js} +1 -1
- ksadk/server/static/assets/{sankeyDiagram-P5KCCOFB-wlO1TsH5.js → sankeyDiagram-P5KCCOFB-DLU2fV1w.js} +1 -1
- ksadk/server/static/assets/{sequenceDiagram-WJ2MYXX4-CHRbElYq.js → sequenceDiagram-WJ2MYXX4-CVqysrA9.js} +1 -1
- ksadk/server/static/assets/{sizeCapture-X5ZJPWSS-DXX54iyO.js → sizeCapture-X5ZJPWSS-BUxfmTHc.js} +1 -1
- ksadk/server/static/assets/{stateDiagram-HBIQ2CUA-Dp_lw9II.js → stateDiagram-HBIQ2CUA-CNFgYI9E.js} +1 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-BXAFScz8.js +1 -0
- ksadk/server/static/assets/{swimlanes-XN3QIQJK-D8O5UlLG.js → swimlanes-XN3QIQJK-B6qCMe8N.js} +1 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uIQ2lJKH.js +8 -0
- ksadk/server/static/assets/{timeline-definition-24CTP7MA-8mfKcxvG.js → timeline-definition-24CTP7MA-CMD3x_U_.js} +1 -1
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5GgucZ.js +1 -0
- ksadk/server/static/assets/treemap-WGGIJYW6-Bq1u1SpG.js +1 -0
- ksadk/server/static/assets/{vennDiagram-4TSXK5OY-EnNl0DE7.js → vennDiagram-4TSXK5OY-BqtUqvXM.js} +1 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-QAt06uEz.js +1 -0
- ksadk/server/static/assets/{wardleyDiagram-VM6X3IG4-DBu5fbYr.js → wardleyDiagram-VM6X3IG4-B5KfDjI-.js} +1 -1
- ksadk/server/static/assets/{xychartDiagram-S5SC5T6Z-BSVXs4IY.js → xychartDiagram-S5SC5T6Z-BaUlSZrn.js} +1 -1
- ksadk/server/static/index.html +2 -2
- ksadk/server/terminal_sessions.py +34 -2
- ksadk/session_context.py +66 -0
- ksadk/sessions/__init__.py +11 -21
- ksadk/sessions/_local_service_sync.py +263 -1
- ksadk/sessions/base.py +176 -0
- ksadk/sessions/errors.py +4 -0
- ksadk/sessions/in_memory.py +309 -19
- ksadk/sessions/invocation_identity.py +235 -0
- ksadk/sessions/local_service.py +83 -1
- ksadk/sessions/persistence.py +275 -0
- ksadk/sessions/postgres_service.py +358 -0
- ksadk/sessions/resilience.py +8 -0
- ksadk/sessions/resilient.py +362 -4
- ksadk/sessions/topology.py +135 -0
- ksadk/skills/__init__.py +26 -0
- ksadk/skills/events.py +464 -0
- 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 +37 -4
- ksadk/skills/observability.py +132 -0
- ksadk/skills/package_store.py +261 -40
- ksadk/skills/runtime/agent.py +67 -9
- ksadk/skills/runtime/artifact_delivery.py +139 -0
- ksadk/skills/runtime/artifacts.py +87 -0
- ksadk/skills/runtime/backends/e2b.py +460 -27
- ksadk/skills/runtime/backends/local.py +629 -62
- ksadk/skills/runtime/base.py +81 -7
- ksadk/skills/runtime/executor.py +268 -1
- ksadk/skills/runtime/loader.py +118 -5
- ksadk/skills/runtime/pinned.py +114 -0
- ksadk/skills/runtime/request.py +49 -0
- ksadk/skills/service_client.py +167 -28
- ksadk/skills/tool_defs.py +108 -3
- ksadk/studio/api.py +810 -93
- ksadk/studio/api_catalog_routes.py +18 -0
- ksadk/studio/api_contracts.py +8 -2
- ksadk/studio/api_plugin_routes.py +562 -104
- ksadk/studio/api_resource_connections.py +221 -0
- ksadk/studio/authoring.py +12 -6
- ksadk/studio/authoring_coordinator.py +23 -16
- ksadk/studio/builder.py +88 -0
- ksadk/studio/capabilities.py +23 -6
- ksadk/studio/channel_connections.py +333 -0
- ksadk/studio/cloud.py +370 -112
- ksadk/studio/cloud_shared_web.py +638 -0
- ksadk/studio/codex_agent_service.py +130 -28
- ksadk/studio/codex_builder.py +242 -3
- ksadk/studio/codex_credentials.py +90 -0
- ksadk/studio/codex_manifest.py +31 -4
- ksadk/studio/codex_plugin_store.py +746 -0
- ksadk/studio/codex_provider_build.py +231 -0
- ksadk/studio/codex_run.py +190 -26
- ksadk/studio/compatibility_report.py +12 -1
- ksadk/studio/compiler.py +88 -14
- ksadk/studio/configuration.py +182 -0
- ksadk/studio/contracts.py +165 -11
- ksadk/studio/dsh_application.py +247 -0
- ksadk/studio/dsh_capability_service.py +1374 -0
- ksadk/studio/dsh_lifecycle.py +58 -0
- ksadk/studio/dsh_models.py +59 -0
- ksadk/studio/dsh_provider_registration.py +367 -21
- ksadk/studio/entry.py +53 -0
- ksadk/studio/event_store.py +36 -5
- ksadk/studio/execution_host.py +525 -0
- ksadk/studio/framework_run.py +32 -10
- ksadk/studio/hosted_kernel.py +89 -14
- ksadk/studio/kernel_registry.py +418 -0
- ksadk/studio/kernel_sqlite_migration.py +181 -0
- ksadk/studio/mcp_runtime.py +11 -3
- ksadk/studio/model_client.py +1180 -66
- ksadk/studio/model_profile_service.py +26 -11
- ksadk/studio/native_documents.py +172 -0
- ksadk/studio/plugin_composition.py +202 -24
- ksadk/studio/plugin_kernel_adapter.py +21 -106
- ksadk/studio/plugin_lifecycle.py +80 -0
- ksadk/studio/plugin_runtime.py +448 -56
- ksadk/studio/provider_recovery.py +59 -0
- ksadk/studio/recovery_page.py +70 -0
- ksadk/studio/resource_authority.py +664 -0
- ksadk/studio/resource_binding_validation.py +77 -0
- ksadk/studio/resource_build_admission.py +196 -0
- ksadk/studio/resource_build_materializer.py +149 -0
- ksadk/studio/resource_catalog.py +149 -2
- ksadk/studio/resource_connections.py +220 -0
- ksadk/studio/run_activity.py +895 -0
- ksadk/studio/run_documents.py +127 -0
- ksadk/studio/run_service.py +789 -83
- ksadk/studio/runtime_catalog.py +53 -10
- ksadk/studio/runtime_source.py +16 -8
- ksadk/studio/scheduler_assistant.py +317 -0
- ksadk/studio/scheduler_runtime.py +32 -280
- ksadk/studio/scheduler_service.py +3 -0
- ksadk/studio/service.py +861 -120
- ksadk/studio/shared_web.py +579 -82
- ksadk/studio/static/assets/ChannelsPage-D_PGmKVq.js +8 -0
- ksadk/studio/static/assets/CodeBlock-DMIf4h33-UIqo-BPW.js +44 -0
- ksadk/studio/static/assets/ExecutionTree-v3HexvPo-Bk8wzGSy.js +1 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- ksadk/studio/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- ksadk/studio/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- ksadk/studio/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- ksadk/studio/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-BEOyPC3w.css +1 -0
- ksadk/studio/static/assets/MathMessageMarkdown-BesSeCYl-OhNwH4K9.js +8 -0
- ksadk/studio/static/assets/MermaidBlock-H_0qzQDf-BdXtxug_.js +11 -0
- ksadk/studio/static/assets/MessageMarkdown-CwMTvgFj-g0I-I4dD.js +59 -0
- ksadk/studio/static/assets/PrismRenderer-5pK6tUdb.js +3 -0
- ksadk/studio/static/assets/TeamsPage-DqX4HWKQ.js +3 -0
- ksadk/studio/static/assets/abnfDiagram-VCTEODGH-Bnb1O3tA.js +1 -0
- ksadk/studio/static/assets/arc-Pry-7G1_.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/array-BifhSqXX.js +1 -0
- ksadk/studio/static/assets/blockDiagram-I7D4REHJ-CLB4L11u.js +129 -0
- ksadk/studio/static/assets/c4Diagram-7LVT6UL2-BOma_Z_F.js +38 -0
- 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-2Q5K7J3B-C1jixKkw.js +1 -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-DVtDP4rm.js +62 -0
- ksadk/studio/static/assets/chunk-5V3GS4D5-i-ZDOEnP.js +1 -0
- ksadk/studio/static/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -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-CpEZCUgg.js +128 -0
- ksadk/studio/static/assets/chunk-F27PBJKO-D7pvKf0C.js +1 -0
- ksadk/studio/static/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- ksadk/studio/static/assets/chunk-GMAD6QVW-DE_8H717.js +72 -0
- 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-D38axYOR.js +231 -0
- ksadk/studio/static/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- 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-DiCQjx9b.js +10 -0
- ksadk/studio/static/assets/chunk-OUJLGHUK-D0j2JRSg.js +2 -0
- ksadk/studio/static/assets/chunk-P2QGCYS3-VdhKmfYq.js +1 -0
- 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-DsCFnRVE.js +168 -0
- ksadk/studio/static/assets/chunk-SVP7TREG-DljApgRX.js +88 -0
- ksadk/studio/static/assets/chunk-TICWLB2K-DWqRtyqa.js +206 -0
- 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/chunk-Y2CYZVJY-DsF7k-Jl.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/cytoscape.esm-CGd-uY3x.js +321 -0
- ksadk/studio/static/assets/dagre-GXQ25YYZ-buZBRlwz.js +4 -0
- ksadk/studio/static/assets/dagre-PrKaheQc.js +1 -0
- ksadk/studio/static/assets/defaultLocale-BFoDCU3G.js +1 -0
- ksadk/studio/static/assets/diagram-S7CK7UJ4-C6aH78c4.js +30 -0
- 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/dist-v5Q1xZ2K.js +1 -0
- ksadk/studio/static/assets/ebnfDiagram-PWID7BFC-Daukxwqf.js +1 -0
- ksadk/studio/static/assets/erDiagram-RLTQ6QDP-CGthTMmJ.js +99 -0
- 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/graphlib-DS17s2tU.js +1 -0
- ksadk/studio/static/assets/iconfont-4HN3C9Pg.woff2 +0 -0
- ksadk/studio/static/assets/index-CfEnms6Y.css +2 -0
- ksadk/studio/static/assets/index-Dp61rOWZ.js +0 -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/init-C-OQMol4.js +1 -0
- ksadk/studio/static/assets/ishikawaDiagram-5VMMS53U-BUGEl8cO.js +70 -0
- ksadk/studio/static/assets/journeyDiagram-3NMN7TZE-Ch2ZYxvr.js +139 -0
- ksadk/studio/static/assets/kanban-definition-UXKFOSKX-Da-Fp4vC.js +89 -0
- ksadk/studio/static/assets/katex-DhON-x74.js +257 -0
- ksadk/studio/static/assets/kingsoft-cloud-BOcLiQ3e.ico +0 -0
- ksadk/studio/static/assets/line-BDaeq300.js +1 -0
- 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-CvlsVQ38.js +96 -0
- ksadk/studio/static/assets/ordinal-BDEzSJ7C.js +1 -0
- ksadk/studio/static/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
- ksadk/studio/static/assets/path-fybaL0A-.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-DlrWiSOv.js +39 -0
- 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-BA3hpUZM.js +7 -0
- 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-E-Ge0FcV.js +84 -0
- ksadk/studio/static/assets/rolldown-runtime-Dy4uBu1J-DK3Fl9T5.js +1 -0
- ksadk/studio/static/assets/rough.esm-Dy-Kn_BL.js +1 -0
- ksadk/studio/static/assets/sankeyDiagram-P5KCCOFB-CA6YKhQ3.js +40 -0
- ksadk/studio/static/assets/sequenceDiagram-WJ2MYXX4-CcElXGg4.js +162 -0
- ksadk/studio/static/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- 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-CIuYhNy3.js +120 -0
- 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-CMJiaedy.js +78 -0
- ksadk/studio/static/assets/xychartDiagram-S5SC5T6Z-BdgtMvW2.js +7 -0
- ksadk/studio/static/index.html +8 -2
- ksadk/studio/teams_catalog.py +133 -0
- ksadk/studio/teams_installation.py +214 -0
- ksadk/studio/teams_node.py +545 -0
- ksadk/studio/teams_node_runner.py +69 -0
- ksadk/studio/teams_remote.py +274 -0
- ksadk/studio/templates.py +40 -19
- ksadk/studio/validator.py +13 -0
- ksadk/studio/workspace.py +19 -4
- ksadk/studio/workspace_plugins.py +136 -0
- ksadk/studio/workspace_registry.py +286 -0
- ksadk/toolsets/__init__.py +11 -0
- ksadk/toolsets/skills.py +446 -378
- ksadk/toolsets/workspace.py +3 -3
- ksadk/toolsets/workspace_identity.py +15 -0
- ksadk/version.py +1 -1
- 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 +26 -13
- agentengine_sdk_python-0.8.3.dist-info/RECORD +0 -833
- ksadk/server/static/assets/MathMessageMarkdown-D9uB55Oh.js +0 -8
- ksadk/server/static/assets/architecture-7GRP2DOG-Dk9nRQ6-.js +0 -1
- ksadk/server/static/assets/channel-s354Yo6o.js +0 -1
- ksadk/server/static/assets/chunk-2Q5K7J3B-CDpPpKR5.js +0 -1
- ksadk/server/static/assets/classDiagram-DTDB5LWJ-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/classDiagram-v2-JRS7N3AN-Dd0nucl9.js +0 -1
- ksadk/server/static/assets/cynefin-OW5HDTMX-BBlT4uMf.js +0 -1
- ksadk/server/static/assets/dist-DdRBIceA.js +0 -1
- ksadk/server/static/assets/eventmodeling-NTZA5JFV-Dr5okd8V.js +0 -1
- ksadk/server/static/assets/flowDiagram-A5DVABFB-VEO-cVcO.js +0 -1
- ksadk/server/static/assets/gitGraph-4MIJSDKK-CKiKY9Cf.js +0 -1
- ksadk/server/static/assets/index-B2k_urY8.js +0 -241
- ksadk/server/static/assets/index-ILPt6IWF.css +0 -2
- ksadk/server/static/assets/info-A6RAGUB7-ubA4Nm_p.js +0 -1
- ksadk/server/static/assets/packet-AYTQ26CC-C7R3NUlK.js +0 -1
- ksadk/server/static/assets/pie-WAS4IAKB-BIT6qjr3.js +0 -1
- ksadk/server/static/assets/radar-RG4KPBEZ-l5noef9X.js +0 -1
- ksadk/server/static/assets/railroad-74A4TZTK-Baea6ZvM.js +0 -1
- ksadk/server/static/assets/railroad-abnf-HS5TGJTU-OKn8zZnU.js +0 -1
- ksadk/server/static/assets/railroad-ebnf-LZEXJU2U-DdKAKC4l.js +0 -1
- ksadk/server/static/assets/railroad-peg-WCYAUIDC-Bds8udlG.js +0 -1
- ksadk/server/static/assets/stateDiagram-v2-4QOOHH4V-5b-8o2iS.js +0 -1
- ksadk/server/static/assets/swimlanesDiagram-VK2B7HYN-uf6WPRA4.js +0 -8
- ksadk/server/static/assets/treeView-Q6P3EWNA-CK5CSrSO.js +0 -1
- ksadk/server/static/assets/treemap-WGGIJYW6-Ch2BKgAM.js +0 -1
- ksadk/server/static/assets/wardley-WFR3VGLG-YW3Q0ml_.js +0 -1
- ksadk/studio/static/assets/PrismRenderer-IYN-ffww.js +0 -3
- ksadk/studio/static/assets/index-DXs1Eq4M.css +0 -1
- ksadk/studio/static/assets/index-DeDqwTsD.js +0 -283
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/WHEEL +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/entry_points.txt +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {agentengine_sdk_python-0.8.3.dist-info → agentengine_sdk_python-0.8.5.dist-info}/top_level.txt +0 -0
ksadk/studio/api.py
CHANGED
|
@@ -4,19 +4,24 @@ 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
|
|
11
|
-
import
|
|
13
|
+
import shutil
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
12
16
|
from collections.abc import AsyncIterator
|
|
13
17
|
from contextlib import asynccontextmanager
|
|
14
18
|
from pathlib import Path
|
|
15
19
|
from typing import Any, Literal
|
|
20
|
+
from urllib.parse import quote
|
|
16
21
|
|
|
17
22
|
from fastapi import FastAPI, File, Header, Query, Request, Response, UploadFile
|
|
18
23
|
from fastapi.exceptions import RequestValidationError
|
|
19
|
-
from fastapi.responses import FileResponse, JSONResponse, StreamingResponse
|
|
24
|
+
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse, StreamingResponse
|
|
20
25
|
from fastapi.staticfiles import StaticFiles
|
|
21
26
|
from starlette.background import BackgroundTask
|
|
22
27
|
|
|
@@ -43,6 +48,7 @@ from ksadk.studio.api_contracts import (
|
|
|
43
48
|
CreateAgentRequest,
|
|
44
49
|
ImportRootRequest,
|
|
45
50
|
InteractionSubmitRequest,
|
|
51
|
+
LinkedDirectoryRequest,
|
|
46
52
|
ProjectInspectRequest,
|
|
47
53
|
PromptCompileRequest,
|
|
48
54
|
QuickAuthoringRequest,
|
|
@@ -79,6 +85,13 @@ from ksadk.studio.api_helpers import (
|
|
|
79
85
|
)
|
|
80
86
|
from ksadk.studio.api_memory_routes import register_memory_routes
|
|
81
87
|
from ksadk.studio.api_plugin_routes import register_plugin_routes
|
|
88
|
+
from ksadk.studio.api_resource_connections import register_resource_connection_routes
|
|
89
|
+
from ksadk.studio.channel_connections import (
|
|
90
|
+
CHANNEL_ACTIONS,
|
|
91
|
+
ChannelAgentConnectionInput,
|
|
92
|
+
ChannelConnectionSettings,
|
|
93
|
+
)
|
|
94
|
+
from ksadk.studio.cloud_shared_web import CloudSharedWebBridge, cloud_chat_target, is_cloud_agent_id
|
|
82
95
|
from ksadk.studio.codex_manifest import CodexAgentManifest
|
|
83
96
|
from ksadk.studio.contracts import (
|
|
84
97
|
AgentAppearance,
|
|
@@ -89,8 +102,23 @@ from ksadk.studio.contracts import (
|
|
|
89
102
|
OperationStatus,
|
|
90
103
|
)
|
|
91
104
|
from ksadk.studio.errors import StudioError
|
|
105
|
+
from ksadk.studio.native_documents import (
|
|
106
|
+
NativeDocumentActionRequest,
|
|
107
|
+
document_metadata,
|
|
108
|
+
is_local_desktop_request,
|
|
109
|
+
perform_document_action,
|
|
110
|
+
)
|
|
111
|
+
from ksadk.studio.run_activity import register_activity_routes
|
|
112
|
+
from ksadk.studio.run_documents import read_document
|
|
92
113
|
from ksadk.studio.service import StudioService
|
|
93
114
|
from ksadk.studio.shared_web import StudioSharedWebBridge
|
|
115
|
+
from ksadk.studio.workspace_registry import (
|
|
116
|
+
LinkedDirectoryPolicy,
|
|
117
|
+
WorkspaceRegistry,
|
|
118
|
+
WorkspaceRuntimeManager,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
logger = logging.getLogger(__name__)
|
|
94
122
|
|
|
95
123
|
_WRITE_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
|
|
96
124
|
_PUBLIC_API_PATHS = {
|
|
@@ -144,9 +172,7 @@ _CONTENT_WIRE_ALIASES = {
|
|
|
144
172
|
def _normalize_cloud_runtime_event_wire(value: dict[str, Any]) -> dict[str, Any]:
|
|
145
173
|
"""Normalize only historic REST casing at the RuntimeEvent boundary."""
|
|
146
174
|
|
|
147
|
-
normalized = {
|
|
148
|
-
_RUNTIME_EVENT_WIRE_ALIASES.get(key, key): item for key, item in value.items()
|
|
149
|
-
}
|
|
175
|
+
normalized = {_RUNTIME_EVENT_WIRE_ALIASES.get(key, key): item for key, item in value.items()}
|
|
150
176
|
source = normalized.get("source")
|
|
151
177
|
if isinstance(source, dict):
|
|
152
178
|
normalized["source"] = {
|
|
@@ -198,9 +224,7 @@ def _cloud_event_conversation_item(
|
|
|
198
224
|
if raw_event is None:
|
|
199
225
|
return None
|
|
200
226
|
try:
|
|
201
|
-
runtime_event = parse_runtime_event_lenient(
|
|
202
|
-
_normalize_cloud_runtime_event_wire(raw_event)
|
|
203
|
-
)
|
|
227
|
+
runtime_event = parse_runtime_event_lenient(_normalize_cloud_runtime_event_wire(raw_event))
|
|
204
228
|
item = project_conversation_item(
|
|
205
229
|
runtime_event, # type: ignore[arg-type]
|
|
206
230
|
session_id=session_id,
|
|
@@ -211,6 +235,21 @@ def _cloud_event_conversation_item(
|
|
|
211
235
|
return item.model_dump(by_alias=True, exclude_none=True, mode="json")
|
|
212
236
|
|
|
213
237
|
|
|
238
|
+
import re as _re
|
|
239
|
+
|
|
240
|
+
# 内容 hash 文件名(如 index-CQj_Jm9z.js)可安全 immutable 强缓存;
|
|
241
|
+
# index.html 与动态 HTML 仍需每次校验。
|
|
242
|
+
_HASHED_ASSET_RE = _re.compile(r"-[A-Za-z0-9_]{8,}\.(js|css|woff2?|ttf|png|svg|webp|mp4|wasm)$")
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _cache_control_for(path: str, response: Any) -> str:
|
|
246
|
+
if path.startswith(("/api/", "/v1/")):
|
|
247
|
+
return "no-store"
|
|
248
|
+
if _HASHED_ASSET_RE.search(path) and 200 <= response.status_code < 300:
|
|
249
|
+
return "public, max-age=31536000, immutable"
|
|
250
|
+
return response.headers.get("Cache-Control", "no-cache")
|
|
251
|
+
|
|
252
|
+
|
|
214
253
|
def create_studio_app(
|
|
215
254
|
root: Path | str,
|
|
216
255
|
*,
|
|
@@ -219,21 +258,114 @@ def create_studio_app(
|
|
|
219
258
|
csrf_token: str | None = None,
|
|
220
259
|
security_enabled: bool = True,
|
|
221
260
|
) -> FastAPI:
|
|
222
|
-
|
|
261
|
+
initial_service = service or StudioService(root)
|
|
262
|
+
studio = WorkspaceRuntimeManager(
|
|
263
|
+
initial_service, lambda workspace_root: StudioService(workspace_root)
|
|
264
|
+
)
|
|
223
265
|
session_secret = session_token or secrets.token_urlsafe(32)
|
|
224
266
|
csrf_secret = csrf_token or secrets.token_urlsafe(24)
|
|
267
|
+
session_cookie_name = "agentkit_studio_session_" + hashlib.sha256(
|
|
268
|
+
session_secret.encode("utf-8")
|
|
269
|
+
).hexdigest()[:16]
|
|
270
|
+
legacy_session_cookie_name = "agentkit_studio_session"
|
|
225
271
|
|
|
226
272
|
@asynccontextmanager
|
|
227
273
|
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
|
|
274
|
+
lazy_desktop_start = os.environ.get("KSADK_STUDIO_LAZY_START") == "1"
|
|
275
|
+
warmups: set[asyncio.Task[None]] = set()
|
|
276
|
+
|
|
277
|
+
def schedule_runtime_warmup(runtime: StudioService) -> None:
|
|
278
|
+
async def warm_runtime() -> None:
|
|
279
|
+
try:
|
|
280
|
+
await runtime.start()
|
|
281
|
+
except Exception:
|
|
282
|
+
# Runtime warmup is best effort; core Studio remains usable
|
|
283
|
+
# while optional DSH capability discovery is unavailable.
|
|
284
|
+
return
|
|
285
|
+
# The Channel UI is a wheel-owned client bundle. Bootstrap it
|
|
286
|
+
# after the listener is available and through the same Profile
|
|
287
|
+
# maintenance fence used by other DSH mutations.
|
|
288
|
+
if (
|
|
289
|
+
os.environ.get("KSADK_STUDIO_CHANNEL_DEFAULT", "1")
|
|
290
|
+
.strip()
|
|
291
|
+
.lower()
|
|
292
|
+
not in {"0", "false", "no", "off"}
|
|
293
|
+
and not os.environ.get("KSADK_DSH_HOME", "").strip()
|
|
294
|
+
and not os.environ.get("KSADK_DSH_PROFILE", "").strip()
|
|
295
|
+
):
|
|
296
|
+
try:
|
|
297
|
+
from ksadk.plugins.dsh_channels import (
|
|
298
|
+
channel_default_bootstrap_needed,
|
|
299
|
+
configure_channel_profile,
|
|
300
|
+
)
|
|
301
|
+
from ksadk.studio.api_plugin_routes import _studio_dsh_options
|
|
302
|
+
|
|
303
|
+
home, profile, command, _ = _studio_dsh_options(runtime)
|
|
304
|
+
# 可选 bootstrap 必须先确认 DSH 命令真实可用:无工具链的
|
|
305
|
+
# 环境进入 Profile 维护栅栏后,恢复失败会按契约保持
|
|
306
|
+
# admission 关闭,导致整个会话面永久 503(回归过)。
|
|
307
|
+
if command and shutil.which(str(command[0])) is None:
|
|
308
|
+
logger.info(
|
|
309
|
+
"Channel 默认激活跳过:DSH 命令不可用 (%s)",
|
|
310
|
+
command[0],
|
|
311
|
+
)
|
|
312
|
+
elif profile == "web" and command and channel_default_bootstrap_needed(home):
|
|
313
|
+
async def configure_channel():
|
|
314
|
+
await asyncio.to_thread(
|
|
315
|
+
configure_channel_profile,
|
|
316
|
+
workspace=runtime.workspace.root,
|
|
317
|
+
dsh_home=home,
|
|
318
|
+
dsh_command=command,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
await runtime.reconfigure_dsh_profile(configure_channel)
|
|
322
|
+
except Exception as error:
|
|
323
|
+
logger.info("Channel 默认激活未完成(可手动启用): %s", error)
|
|
324
|
+
|
|
325
|
+
if os.environ.get(
|
|
326
|
+
"KSADK_STUDIO_TEAMS_DEFAULT", "1"
|
|
327
|
+
).strip().lower() not in {"0", "false", "no", "off"}:
|
|
328
|
+
installation = getattr(runtime, "teams_installation", None)
|
|
329
|
+
if installation is not None and not installation.status().get("enabled"):
|
|
330
|
+
try:
|
|
331
|
+
await installation.enable()
|
|
332
|
+
except Exception as error:
|
|
333
|
+
# 默认启用是预期行为,但 DSH 工具链/权威不可用时必须静默
|
|
334
|
+
# 降级,核心 Studio 与其他插件不受影响;页面仍保留手动入口。
|
|
335
|
+
logger.info(
|
|
336
|
+
"Teams 默认激活未完成(可手动启用): %s", error
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
task = asyncio.create_task(warm_runtime())
|
|
340
|
+
warmups.add(task)
|
|
341
|
+
task.add_done_callback(warmups.discard)
|
|
342
|
+
|
|
228
343
|
try:
|
|
229
|
-
|
|
230
|
-
await studio.
|
|
344
|
+
app.state.runtime_warmups = schedule_runtime_warmup
|
|
345
|
+
await studio.start(wait_for_dsh=not lazy_desktop_start)
|
|
346
|
+
# Optional plugin activation must not hold the HTTP listener closed
|
|
347
|
+
# while DSH starts subprocesses or acquires an authority lease.
|
|
348
|
+
schedule_runtime_warmup(studio.active)
|
|
349
|
+
# Pre-resolve the entry redirect choice once off the request path;
|
|
350
|
+
# failures are swallowed and ``index()`` has its own bounded wait.
|
|
351
|
+
probe_warmup = getattr(
|
|
352
|
+
studio.active.dsh_capabilities, "schedule_plugin_probe_warmup", None
|
|
353
|
+
)
|
|
354
|
+
if callable(probe_warmup):
|
|
355
|
+
probe_warmup()
|
|
356
|
+
await studio.run_service.recover_interrupted(studio.resolve_run_spec)
|
|
231
357
|
await studio.scheduler.start_if_available()
|
|
232
358
|
yield
|
|
233
359
|
finally:
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
360
|
+
app.state.runtime_warmups = None
|
|
361
|
+
for task in tuple(warmups):
|
|
362
|
+
task.cancel()
|
|
363
|
+
if warmups:
|
|
364
|
+
await asyncio.gather(*warmups, return_exceptions=True)
|
|
365
|
+
for runtime in studio.services():
|
|
366
|
+
await runtime.scheduler.stop()
|
|
367
|
+
await runtime.aclose()
|
|
368
|
+
runtime.credentials.clear_session()
|
|
237
369
|
|
|
238
370
|
app = FastAPI(
|
|
239
371
|
title="AgentKit Local Studio",
|
|
@@ -246,6 +378,11 @@ def create_studio_app(
|
|
|
246
378
|
app.state.studio_service = studio
|
|
247
379
|
app.state.session_token = session_secret
|
|
248
380
|
app.state.csrf_token = csrf_secret
|
|
381
|
+
from ksadk.studio.dsh_models import studio_model_projection
|
|
382
|
+
|
|
383
|
+
studio.dsh_capabilities.model_projection = lambda: studio_model_projection(
|
|
384
|
+
studio.catalog, studio.credentials
|
|
385
|
+
)
|
|
249
386
|
|
|
250
387
|
def _stream_studio_run(
|
|
251
388
|
build_id: str,
|
|
@@ -321,8 +458,9 @@ def create_studio_app(
|
|
|
321
458
|
)
|
|
322
459
|
|
|
323
460
|
static_root = Path(__file__).with_name("static")
|
|
324
|
-
_studio_startup_epoch = str(int(time.time()))
|
|
325
461
|
shared_web = StudioSharedWebBridge(studio)
|
|
462
|
+
register_activity_routes(app, studio, resolve_run_id=shared_web.resolve_run_reference)
|
|
463
|
+
cloud_web = CloudSharedWebBridge(studio)
|
|
326
464
|
app.state.shared_web_bridge = shared_web
|
|
327
465
|
app.mount("/static", StaticFiles(directory=static_root), name="studio-static")
|
|
328
466
|
|
|
@@ -377,8 +515,10 @@ def create_studio_app(
|
|
|
377
515
|
or shared_web_api
|
|
378
516
|
or responses_api
|
|
379
517
|
):
|
|
380
|
-
supplied =
|
|
381
|
-
|
|
518
|
+
supplied = (
|
|
519
|
+
request.cookies.get(session_cookie_name)
|
|
520
|
+
or request.cookies.get(legacy_session_cookie_name)
|
|
521
|
+
or request.headers.get("X-AgentKit-Session")
|
|
382
522
|
)
|
|
383
523
|
if not supplied or not hmac.compare_digest(supplied, session_secret):
|
|
384
524
|
return _error_response(
|
|
@@ -389,7 +529,8 @@ def create_studio_app(
|
|
|
389
529
|
),
|
|
390
530
|
request,
|
|
391
531
|
)
|
|
392
|
-
|
|
532
|
+
channel_api = shared_web_api and request.url.path.rsplit("/", 1)[-1] in CHANNEL_ACTIONS
|
|
533
|
+
if (studio_api or responses_api or channel_api) and request.method in _WRITE_METHODS:
|
|
393
534
|
csrf = request.headers.get("X-CSRF-Token")
|
|
394
535
|
if not csrf or not hmac.compare_digest(csrf, csrf_secret):
|
|
395
536
|
return _error_response(
|
|
@@ -402,11 +543,7 @@ def create_studio_app(
|
|
|
402
543
|
)
|
|
403
544
|
response = await call_next(request)
|
|
404
545
|
response.headers["X-Request-Id"] = request.state.request_id
|
|
405
|
-
response.headers["Cache-Control"] = (
|
|
406
|
-
"no-store"
|
|
407
|
-
if request.url.path.startswith(("/api/", "/v1/"))
|
|
408
|
-
else response.headers.get("Cache-Control", "no-cache")
|
|
409
|
-
)
|
|
546
|
+
response.headers["Cache-Control"] = _cache_control_for(request.url.path, response)
|
|
410
547
|
response.headers["X-Content-Type-Options"] = "nosniff"
|
|
411
548
|
response.headers["X-Frame-Options"] = "DENY"
|
|
412
549
|
response.headers["Referrer-Policy"] = "no-referrer"
|
|
@@ -464,29 +601,23 @@ def create_studio_app(
|
|
|
464
601
|
)
|
|
465
602
|
|
|
466
603
|
@app.get("/")
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if "?v=" not in html:
|
|
474
|
-
import re
|
|
475
|
-
|
|
476
|
-
def _add_version(match: "re.Match[str]") -> str:
|
|
477
|
-
attr, path_part = match.group(1), match.group(2)
|
|
478
|
-
return f'{attr}="/static/assets/{path_part}?v={_studio_startup_epoch}"'
|
|
479
|
-
|
|
480
|
-
html = re.sub(
|
|
481
|
-
r'(src|href)="/static/assets/([^"]+)"',
|
|
482
|
-
_add_version,
|
|
483
|
-
html,
|
|
484
|
-
)
|
|
485
|
-
response = Response(content=html, media_type="text/html")
|
|
486
|
-
response.headers["Cache-Control"] = "no-store"
|
|
604
|
+
@app.get("/studio-recovery/")
|
|
605
|
+
@app.get("/studio-shell/")
|
|
606
|
+
async def index(request: Request):
|
|
607
|
+
from ksadk.studio.entry import studio_entry_response
|
|
608
|
+
|
|
609
|
+
response = await studio_entry_response(studio, request, static_root)
|
|
487
610
|
if security_enabled:
|
|
488
611
|
response.set_cookie(
|
|
489
|
-
|
|
612
|
+
session_cookie_name,
|
|
613
|
+
session_secret,
|
|
614
|
+
httponly=True,
|
|
615
|
+
samesite="strict",
|
|
616
|
+
secure=False,
|
|
617
|
+
path="/",
|
|
618
|
+
)
|
|
619
|
+
response.set_cookie(
|
|
620
|
+
legacy_session_cookie_name,
|
|
490
621
|
session_secret,
|
|
491
622
|
httponly=True,
|
|
492
623
|
samesite="strict",
|
|
@@ -495,6 +626,42 @@ def create_studio_app(
|
|
|
495
626
|
)
|
|
496
627
|
return response
|
|
497
628
|
|
|
629
|
+
@app.get("/api/v1/plugin-ecosystems/dsh/recovery")
|
|
630
|
+
async def dsh_recovery_status():
|
|
631
|
+
# This endpoint must remain a read-only snapshot: no Core startup, Profile
|
|
632
|
+
# projection, credential resolution, or filesystem repair is attempted.
|
|
633
|
+
return studio.dsh_capabilities.startup_status
|
|
634
|
+
|
|
635
|
+
@app.get("/api/v1/plugins/workspace-contributions")
|
|
636
|
+
async def workspace_contributions():
|
|
637
|
+
"""Expose enabled UI contributions without booting the DSH Core."""
|
|
638
|
+
from ksadk.plugins.dsh_channels import channel_workspace_contributions
|
|
639
|
+
from ksadk.plugins.dsh_home import studio_dsh_home
|
|
640
|
+
|
|
641
|
+
runtime = studio.active
|
|
642
|
+
contributions = await asyncio.to_thread(
|
|
643
|
+
channel_workspace_contributions,
|
|
644
|
+
studio_dsh_home(runtime.workspace.root),
|
|
645
|
+
os.environ.get("KSADK_DSH_PROFILE", "").strip() or "web",
|
|
646
|
+
)
|
|
647
|
+
# Teams remains served by its existing lifecycle endpoint; this endpoint
|
|
648
|
+
# only adds client-only contributions that have no domain lifecycle.
|
|
649
|
+
return {"items": contributions}
|
|
650
|
+
|
|
651
|
+
@app.get("/api/v1/channels/connection")
|
|
652
|
+
async def channel_connection_status():
|
|
653
|
+
return studio.channel_connections.status()
|
|
654
|
+
|
|
655
|
+
@app.put("/api/v1/channels/connection")
|
|
656
|
+
async def configure_channel_connection(payload: ChannelConnectionSettings):
|
|
657
|
+
return await studio.channel_connections.configure(payload)
|
|
658
|
+
|
|
659
|
+
@app.put("/api/v1/channels/agents/{agent_id}/connection")
|
|
660
|
+
async def configure_channel_agent_connection(
|
|
661
|
+
agent_id: str, payload: ChannelAgentConnectionInput
|
|
662
|
+
):
|
|
663
|
+
return await studio.channel_connections.configure_agent(agent_id, payload)
|
|
664
|
+
|
|
498
665
|
@app.get("/favicon.ico")
|
|
499
666
|
async def favicon():
|
|
500
667
|
return Response(status_code=204)
|
|
@@ -526,9 +693,31 @@ def create_studio_app(
|
|
|
526
693
|
async def openai_responses(payload: dict[str, Any]):
|
|
527
694
|
metadata = payload.get("metadata")
|
|
528
695
|
metadata = metadata if isinstance(metadata, dict) else {}
|
|
529
|
-
|
|
696
|
+
agentengine_metadata = metadata.get("agentengine")
|
|
697
|
+
agentengine_metadata = (
|
|
698
|
+
agentengine_metadata if isinstance(agentengine_metadata, dict) else {}
|
|
699
|
+
)
|
|
700
|
+
agent_id = (
|
|
701
|
+
str(
|
|
702
|
+
metadata.get("agent_id")
|
|
703
|
+
or metadata.get("agentId")
|
|
704
|
+
or agentengine_metadata.get("agent_id")
|
|
705
|
+
or agentengine_metadata.get("agentId")
|
|
706
|
+
or ""
|
|
707
|
+
)
|
|
708
|
+
or None
|
|
709
|
+
)
|
|
530
710
|
requested_approval_mode = (
|
|
531
|
-
str(
|
|
711
|
+
str(
|
|
712
|
+
metadata.get("approval_mode")
|
|
713
|
+
or metadata.get("approvalMode")
|
|
714
|
+
or agentengine_metadata.get("tool_approval_mode")
|
|
715
|
+
or agentengine_metadata.get("approval_mode")
|
|
716
|
+
or agentengine_metadata.get("approvalMode")
|
|
717
|
+
or ""
|
|
718
|
+
)
|
|
719
|
+
.strip()
|
|
720
|
+
.lower()
|
|
532
721
|
)
|
|
533
722
|
if requested_approval_mode and requested_approval_mode not in {"ask", "risk", "full"}:
|
|
534
723
|
raise StudioError(
|
|
@@ -538,7 +727,13 @@ def create_studio_app(
|
|
|
538
727
|
field="metadata.approval_mode",
|
|
539
728
|
)
|
|
540
729
|
collaboration_mode = (
|
|
541
|
-
str(
|
|
730
|
+
str(
|
|
731
|
+
metadata.get("collaboration_mode")
|
|
732
|
+
or metadata.get("collaborationMode")
|
|
733
|
+
or agentengine_metadata.get("collaboration_mode")
|
|
734
|
+
or agentengine_metadata.get("collaborationMode")
|
|
735
|
+
or ""
|
|
736
|
+
)
|
|
542
737
|
.strip()
|
|
543
738
|
.lower()
|
|
544
739
|
)
|
|
@@ -550,7 +745,11 @@ def create_studio_app(
|
|
|
550
745
|
field="metadata.collaboration_mode",
|
|
551
746
|
)
|
|
552
747
|
goal_objective = str(
|
|
553
|
-
metadata.get("goal_objective")
|
|
748
|
+
metadata.get("goal_objective")
|
|
749
|
+
or metadata.get("goalObjective")
|
|
750
|
+
or agentengine_metadata.get("goal_objective")
|
|
751
|
+
or agentengine_metadata.get("goalObjective")
|
|
752
|
+
or ""
|
|
554
753
|
).strip()
|
|
555
754
|
reasoning = payload.get("reasoning")
|
|
556
755
|
reasoning = reasoning if isinstance(reasoning, dict) else {}
|
|
@@ -594,7 +793,7 @@ def create_studio_app(
|
|
|
594
793
|
|
|
595
794
|
@app.post("/v1/responses/{response_id}/cancel")
|
|
596
795
|
async def cancel_openai_response(response_id: str):
|
|
597
|
-
result = shared_web.cancel_run(response_id)
|
|
796
|
+
result = await shared_web.cancel_run(response_id)
|
|
598
797
|
return {
|
|
599
798
|
"id": response_id,
|
|
600
799
|
"object": "response",
|
|
@@ -618,26 +817,121 @@ def create_studio_app(
|
|
|
618
817
|
try:
|
|
619
818
|
cookie_agent_id = request.cookies.get("agentkit_studio_chat_agent")
|
|
620
819
|
requested_agent_id = str(payload.get("AgentId") or cookie_agent_id or "")
|
|
820
|
+
cloud_mode = is_cloud_agent_id(requested_agent_id)
|
|
821
|
+
if cloud_mode:
|
|
822
|
+
# Cloud agents project onto the same shared-web action
|
|
823
|
+
# contract through the cloud-chat proxy, so the ksadk-web
|
|
824
|
+
# headless data layer drives them like hosted-ui does.
|
|
825
|
+
cloud_target = cloud_chat_target(requested_agent_id)
|
|
826
|
+
data = None
|
|
827
|
+
if action == "GetAgentUiBootstrap":
|
|
828
|
+
data = await cloud_web.bootstrap(cloud_target)
|
|
829
|
+
elif action == "ListAgentModels":
|
|
830
|
+
data = await cloud_web.list_models(cloud_target)
|
|
831
|
+
elif action == "ListSessions":
|
|
832
|
+
data = await cloud_web.list_sessions(
|
|
833
|
+
cloud_target,
|
|
834
|
+
page=int(payload.get("Page") or 1),
|
|
835
|
+
page_size=int(payload.get("PageSize") or 30),
|
|
836
|
+
)
|
|
837
|
+
elif action == "CreateSession":
|
|
838
|
+
data = await cloud_web.create_session(cloud_target)
|
|
839
|
+
elif action == "GetSession":
|
|
840
|
+
data = await cloud_web.get_session(
|
|
841
|
+
cloud_target, str(payload.get("SessionId") or "")
|
|
842
|
+
)
|
|
843
|
+
elif action == "DeleteSession":
|
|
844
|
+
data = await cloud_web.delete_session(
|
|
845
|
+
cloud_target, str(payload.get("SessionId") or "")
|
|
846
|
+
)
|
|
847
|
+
elif action == "ListSessionMessages":
|
|
848
|
+
data = await cloud_web.list_messages(
|
|
849
|
+
cloud_target,
|
|
850
|
+
str(payload.get("SessionId") or ""),
|
|
851
|
+
after_seq_id=_optional_int(payload.get("AfterSeqId")),
|
|
852
|
+
before_seq_id=_optional_int(payload.get("BeforeSeqId")),
|
|
853
|
+
limit=int(payload.get("Limit") or 50),
|
|
854
|
+
)
|
|
855
|
+
elif action == "ListSessionEvents":
|
|
856
|
+
data = await cloud_web.list_session_events(
|
|
857
|
+
cloud_target,
|
|
858
|
+
str(payload.get("SessionId") or ""),
|
|
859
|
+
after_seq_id=_optional_int(payload.get("AfterSeqId")),
|
|
860
|
+
offset=_optional_int(payload.get("Offset")),
|
|
861
|
+
limit=int(payload.get("Limit") or 200),
|
|
862
|
+
)
|
|
863
|
+
elif action == "SubmitInteraction":
|
|
864
|
+
data = await cloud_web.submit_interaction(
|
|
865
|
+
cloud_target, str(payload.get("SessionId") or ""), payload
|
|
866
|
+
)
|
|
867
|
+
elif action == "RunAgent":
|
|
868
|
+
# Open the upstream connection before StreamingResponse
|
|
869
|
+
# commits status 200, so admission failures remain a
|
|
870
|
+
# structured HTTP error instead of an empty SSE body.
|
|
871
|
+
upstream_stream = await cloud_web.open_run_stream(cloud_target, payload)
|
|
872
|
+
return StreamingResponse(
|
|
873
|
+
cloud_web.stream_run(
|
|
874
|
+
cloud_target,
|
|
875
|
+
payload,
|
|
876
|
+
upstream_stream=upstream_stream,
|
|
877
|
+
),
|
|
878
|
+
media_type="text/event-stream",
|
|
879
|
+
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
880
|
+
)
|
|
881
|
+
elif action in {
|
|
882
|
+
"GetResponseFeedback",
|
|
883
|
+
"UpsertResponseFeedback",
|
|
884
|
+
"DeleteResponseFeedback",
|
|
885
|
+
"ListSessionCheckpoints",
|
|
886
|
+
"ListToolReceipts",
|
|
887
|
+
}:
|
|
888
|
+
data = {"Feedback": None} if action == "GetResponseFeedback" else {}
|
|
889
|
+
else:
|
|
890
|
+
return JSONResponse(
|
|
891
|
+
status_code=404,
|
|
892
|
+
content={
|
|
893
|
+
"Code": 404,
|
|
894
|
+
"Message": f"Studio 尚未实现云端共享 Web 动作:{action}",
|
|
895
|
+
"Data": {},
|
|
896
|
+
},
|
|
897
|
+
)
|
|
898
|
+
return {"Code": 0, "Message": "OK", "Data": data}
|
|
621
899
|
if action == "GetAgentUiBootstrap":
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
data = shared_web.list_models(
|
|
625
|
-
shared_web.resolve_agent_id(requested_agent_id or None)
|
|
900
|
+
bootstrap_agent_id = shared_web.resolve_agent_id(
|
|
901
|
+
requested_agent_id or None
|
|
626
902
|
)
|
|
903
|
+
# 冷启动时 provider 模型描述符尚未发现;绑定 model:provider:*
|
|
904
|
+
# 的 Agent(尤其 Harness)若直接解析会 RESOURCE_NOT_FOUND,
|
|
905
|
+
# 前端只能无限转圈。访问资源库不应该是打开对话的前置条件。
|
|
906
|
+
if not bootstrap_agent_id.startswith(("ar-", "account:")):
|
|
907
|
+
await runtime_model_catalog()
|
|
908
|
+
data = shared_web.bootstrap(bootstrap_agent_id)
|
|
909
|
+
elif action == "ListAgentModels":
|
|
910
|
+
model_agent_id = shared_web.resolve_agent_id(requested_agent_id or None)
|
|
911
|
+
# A cold Studio process has no discovered provider descriptors.
|
|
912
|
+
# Resolve the same cached catalog as Resources before projecting
|
|
913
|
+
# model windows; visiting Resources must not be a prerequisite.
|
|
914
|
+
await runtime_model_catalog()
|
|
915
|
+
data = shared_web.list_models(model_agent_id)
|
|
627
916
|
elif action == "ListSessions":
|
|
628
|
-
data = shared_web.list_sessions(
|
|
917
|
+
data = await shared_web.list_sessions(
|
|
629
918
|
shared_web.resolve_agent_id(requested_agent_id or None),
|
|
630
919
|
page=int(payload.get("Page") or 1),
|
|
631
920
|
page_size=int(payload.get("PageSize") or 30),
|
|
632
921
|
)
|
|
633
922
|
elif action == "CreateSession":
|
|
634
|
-
data = shared_web.create_session(
|
|
923
|
+
data = await shared_web.create_session(
|
|
635
924
|
shared_web.resolve_agent_id(requested_agent_id or None)
|
|
636
925
|
)
|
|
637
926
|
elif action == "GetSession":
|
|
638
|
-
data = shared_web.get_session(str(payload.get("SessionId") or ""))
|
|
927
|
+
data = await shared_web.get_session(str(payload.get("SessionId") or ""))
|
|
928
|
+
elif action == "CompactSession":
|
|
929
|
+
data = await shared_web.compact_session(
|
|
930
|
+
shared_web.resolve_agent_id(requested_agent_id or None),
|
|
931
|
+
str(payload.get("SessionId") or ""),
|
|
932
|
+
)
|
|
639
933
|
elif action == "DeleteSession":
|
|
640
|
-
data = shared_web.delete_session(str(payload.get("SessionId") or ""))
|
|
934
|
+
data = await shared_web.delete_session(str(payload.get("SessionId") or ""))
|
|
641
935
|
elif action == "ListSessionMessages":
|
|
642
936
|
data = await shared_web.list_messages(
|
|
643
937
|
str(payload.get("SessionId") or ""),
|
|
@@ -648,8 +942,12 @@ def create_studio_app(
|
|
|
648
942
|
elif action == "ListSessionEvents":
|
|
649
943
|
data = await shared_web.list_session_events(str(payload.get("SessionId") or ""))
|
|
650
944
|
elif action == "RunAgent":
|
|
945
|
+
# A cold process has not discovered provider model descriptors
|
|
946
|
+
# yet. Run admission may need to materialize a current Build,
|
|
947
|
+
# so chat must not depend on visiting the Models page first.
|
|
948
|
+
await runtime_model_catalog()
|
|
651
949
|
return StreamingResponse(
|
|
652
|
-
shared_web.stream_run(payload),
|
|
950
|
+
shared_web.stream_run(payload, shared_ui=True),
|
|
653
951
|
media_type="text/event-stream",
|
|
654
952
|
headers={
|
|
655
953
|
"Cache-Control": "no-store",
|
|
@@ -657,7 +955,35 @@ def create_studio_app(
|
|
|
657
955
|
},
|
|
658
956
|
)
|
|
659
957
|
elif action == "CancelRun":
|
|
660
|
-
data = shared_web.cancel_run(str(payload.get("InvocationId") or ""))
|
|
958
|
+
data = await shared_web.cancel_run(str(payload.get("InvocationId") or ""))
|
|
959
|
+
elif action == "SubmitInteraction":
|
|
960
|
+
run_id = str(payload.get("RunId") or "")
|
|
961
|
+
studio._require_direct_run(run_id)
|
|
962
|
+
interaction_id = str(payload.get("InteractionId") or "")
|
|
963
|
+
resolved = await studio.run_service.submit_interaction(
|
|
964
|
+
run_id,
|
|
965
|
+
interaction_id,
|
|
966
|
+
name=str(payload.get("Action") or "submit"),
|
|
967
|
+
data=(
|
|
968
|
+
dict(payload.get("Response"))
|
|
969
|
+
if isinstance(payload.get("Response"), dict)
|
|
970
|
+
else {}
|
|
971
|
+
),
|
|
972
|
+
expected_revision=int(payload.get("ExpectedRevision") or 0),
|
|
973
|
+
idempotency_key=str(payload.get("IdempotencyKey") or ""),
|
|
974
|
+
)
|
|
975
|
+
data = {
|
|
976
|
+
"schema_version": 1,
|
|
977
|
+
"command_id": str(
|
|
978
|
+
resolved.get("eventId")
|
|
979
|
+
or resolved.get("resolutionEventId")
|
|
980
|
+
or f"interaction:{interaction_id}"
|
|
981
|
+
),
|
|
982
|
+
"status": "accepted",
|
|
983
|
+
"message_id": None,
|
|
984
|
+
"run_id": run_id,
|
|
985
|
+
"accepted_seq": int(resolved.get("eventId") or 0),
|
|
986
|
+
}
|
|
661
987
|
elif action in {
|
|
662
988
|
"GetResponseFeedback",
|
|
663
989
|
"UpsertResponseFeedback",
|
|
@@ -669,6 +995,10 @@ def create_studio_app(
|
|
|
669
995
|
elif action == "ListToolReceipts":
|
|
670
996
|
data = {"ToolReceipts": []}
|
|
671
997
|
else:
|
|
998
|
+
# Channel-related actions: proxy to channel backend
|
|
999
|
+
if action in CHANNEL_ACTIONS:
|
|
1000
|
+
status, body = await studio.channel_connections.proxy(action, payload)
|
|
1001
|
+
return JSONResponse(status_code=status, content=body)
|
|
672
1002
|
return JSONResponse(
|
|
673
1003
|
status_code=404,
|
|
674
1004
|
content={
|
|
@@ -689,12 +1019,37 @@ def create_studio_app(
|
|
|
689
1019
|
)
|
|
690
1020
|
|
|
691
1021
|
@app.get("/agentengine/api/v1/SubscribeRunEvents")
|
|
692
|
-
async def shared_chat_subscribe_run_events(
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
1022
|
+
async def shared_chat_subscribe_run_events(
|
|
1023
|
+
request: Request,
|
|
1024
|
+
session_id: str = Query(alias="SessionId"),
|
|
1025
|
+
invocation_id: str = Query(alias="InvocationId"),
|
|
1026
|
+
after_seq_id: int = Query(default=0, alias="AfterSeqId", ge=0),
|
|
1027
|
+
agent_id: str | None = Query(default=None, alias="AgentId"),
|
|
1028
|
+
):
|
|
1029
|
+
requested_agent_id = str(
|
|
1030
|
+
agent_id or request.cookies.get("agentkit_studio_chat_agent") or ""
|
|
1031
|
+
)
|
|
1032
|
+
if is_cloud_agent_id(requested_agent_id):
|
|
1033
|
+
cloud_target = cloud_chat_target(requested_agent_id)
|
|
1034
|
+
return StreamingResponse(
|
|
1035
|
+
cloud_web.subscribe_run_events(
|
|
1036
|
+
cloud_target,
|
|
1037
|
+
session_id,
|
|
1038
|
+
invocation_id,
|
|
1039
|
+
after_seq_id=after_seq_id,
|
|
1040
|
+
),
|
|
1041
|
+
media_type="text/event-stream",
|
|
1042
|
+
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
1043
|
+
)
|
|
1044
|
+
# Validate before StreamingResponse sends headers; invalid identities
|
|
1045
|
+
# remain ordinary actionable HTTP errors.
|
|
1046
|
+
await shared_web.subscription_run_id(session_id, invocation_id)
|
|
696
1047
|
return StreamingResponse(
|
|
697
|
-
|
|
1048
|
+
shared_web.subscribe_run_events(
|
|
1049
|
+
session_id,
|
|
1050
|
+
invocation_id,
|
|
1051
|
+
after_seq_id=after_seq_id,
|
|
1052
|
+
),
|
|
698
1053
|
media_type="text/event-stream",
|
|
699
1054
|
headers={"Cache-Control": "no-store", "X-Accel-Buffering": "no"},
|
|
700
1055
|
)
|
|
@@ -716,7 +1071,15 @@ def create_studio_app(
|
|
|
716
1071
|
status_code=401,
|
|
717
1072
|
)
|
|
718
1073
|
response.set_cookie(
|
|
719
|
-
|
|
1074
|
+
session_cookie_name,
|
|
1075
|
+
session_secret,
|
|
1076
|
+
httponly=True,
|
|
1077
|
+
samesite="strict",
|
|
1078
|
+
secure=False,
|
|
1079
|
+
path="/",
|
|
1080
|
+
)
|
|
1081
|
+
response.set_cookie(
|
|
1082
|
+
legacy_session_cookie_name,
|
|
720
1083
|
session_secret,
|
|
721
1084
|
httponly=True,
|
|
722
1085
|
samesite="strict",
|
|
@@ -735,13 +1098,15 @@ def create_studio_app(
|
|
|
735
1098
|
"workspace": {
|
|
736
1099
|
"name": studio.workspace.root.name,
|
|
737
1100
|
"path": str(studio.workspace.root),
|
|
1101
|
+
"workspaceId": studio.workspace_record.workspace_id,
|
|
738
1102
|
},
|
|
739
1103
|
"operationScope": studio.deployment_operation_scope(),
|
|
1104
|
+
"frontend": studio.frontend_assets(),
|
|
740
1105
|
"features": {
|
|
741
1106
|
"build": True,
|
|
742
1107
|
"run": True,
|
|
743
1108
|
"runtimeRegistry": True,
|
|
744
|
-
"runtimeTypes": ["codex", "adk", "langgraph"],
|
|
1109
|
+
"runtimeTypes": ["harness", "codex", "adk", "langgraph"],
|
|
745
1110
|
"evaluation": True,
|
|
746
1111
|
"deployment": True,
|
|
747
1112
|
"cloudRebuild": False,
|
|
@@ -758,12 +1123,13 @@ def create_studio_app(
|
|
|
758
1123
|
|
|
759
1124
|
@app.put("/api/v1/system/settings")
|
|
760
1125
|
async def update_settings(payload: dict[str, Any]):
|
|
761
|
-
return studio.
|
|
1126
|
+
return await studio.apply_settings(payload)
|
|
762
1127
|
|
|
763
1128
|
@app.get("/api/v1/schedules")
|
|
764
1129
|
async def list_schedules():
|
|
765
1130
|
return {
|
|
766
1131
|
"items": studio.scheduler.list_tasks(),
|
|
1132
|
+
"taskOccurrences": studio.scheduler.task_occurrence_summaries(),
|
|
767
1133
|
"availability": studio.scheduler.availability(),
|
|
768
1134
|
}
|
|
769
1135
|
|
|
@@ -835,6 +1201,10 @@ def create_studio_app(
|
|
|
835
1201
|
task_id: str,
|
|
836
1202
|
payload: AgentScheduleRequest,
|
|
837
1203
|
):
|
|
1204
|
+
existing = studio.get_agent_schedule(agent_id, task_id)
|
|
1205
|
+
await studio.validate_schedule_session(
|
|
1206
|
+
agent_id, payload.continuity, payload.session_id, existing.target.agent_version_ref
|
|
1207
|
+
)
|
|
838
1208
|
return studio.update_agent_schedule(
|
|
839
1209
|
agent_id,
|
|
840
1210
|
task_id,
|
|
@@ -865,23 +1235,222 @@ def create_studio_app(
|
|
|
865
1235
|
studio.get_agent_schedule(agent_id, task_id)
|
|
866
1236
|
return {"items": studio.scheduler.list_occurrences(task_id, limit=limit)}
|
|
867
1237
|
|
|
1238
|
+
def _decode_text_file(path: Path) -> str:
|
|
1239
|
+
"""Decode with an encoding fallback chain so legacy GBK/GB18030 files
|
|
1240
|
+
written by agents preview correctly instead of turning into mojibake."""
|
|
1241
|
+
raw = path.read_bytes()
|
|
1242
|
+
for encoding in ("utf-8-sig", "utf-8", "gb18030"):
|
|
1243
|
+
try:
|
|
1244
|
+
return raw.decode(encoding)
|
|
1245
|
+
except UnicodeDecodeError:
|
|
1246
|
+
continue
|
|
1247
|
+
return raw.decode("utf-8", errors="replace")
|
|
1248
|
+
|
|
1249
|
+
@app.get("/api/v1/workspace/file")
|
|
1250
|
+
async def read_workspace_file(path: str = Query(...), download: bool = Query(default=False)):
|
|
1251
|
+
"""Read one file inside the workspace (or a linked directory) for preview.
|
|
1252
|
+
|
|
1253
|
+
Absolute paths outside the workspace and its linked directories are
|
|
1254
|
+
rejected, as are oversized files; preview clients render the payload
|
|
1255
|
+
according to the returned contentType.
|
|
1256
|
+
"""
|
|
1257
|
+
import mimetypes
|
|
1258
|
+
from urllib.parse import quote
|
|
1259
|
+
|
|
1260
|
+
raw = Path(path).expanduser()
|
|
1261
|
+
candidate = raw if raw.is_absolute() else studio.workspace.root / raw
|
|
1262
|
+
try:
|
|
1263
|
+
resolved = candidate.resolve()
|
|
1264
|
+
except OSError as error:
|
|
1265
|
+
raise StudioError("WORKSPACE_FILE_INVALID", "文件路径无效", status_code=422) from error
|
|
1266
|
+
|
|
1267
|
+
allowed_roots = [studio.workspace.root.resolve()]
|
|
1268
|
+
for item in LinkedDirectoryPolicy(studio.workspace.root).list():
|
|
1269
|
+
linked = Path(item.path).expanduser().resolve()
|
|
1270
|
+
if linked.is_dir():
|
|
1271
|
+
allowed_roots.append(linked)
|
|
1272
|
+
if not any(
|
|
1273
|
+
resolved == root or resolved.is_relative_to(root) for root in allowed_roots
|
|
1274
|
+
):
|
|
1275
|
+
raise StudioError(
|
|
1276
|
+
"WORKSPACE_FILE_FORBIDDEN", "路径不在工作区(或链接目录)内", status_code=403
|
|
1277
|
+
)
|
|
1278
|
+
if not resolved.is_file():
|
|
1279
|
+
raise StudioError("WORKSPACE_FILE_NOT_FOUND", "文件不存在", status_code=404)
|
|
1280
|
+
size = resolved.stat().st_size
|
|
1281
|
+
if size > 2 * 1024 * 1024:
|
|
1282
|
+
raise StudioError(
|
|
1283
|
+
"WORKSPACE_FILE_TOO_LARGE", "文件超过 2MB 预览上限", status_code=413
|
|
1284
|
+
)
|
|
1285
|
+
suffix = resolved.suffix.lower()
|
|
1286
|
+
if suffix in {
|
|
1287
|
+
".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg", ".bmp", ".ico",
|
|
1288
|
+
}:
|
|
1289
|
+
content_type = mimetypes.guess_type(resolved.name)[0] or "application/octet-stream"
|
|
1290
|
+
media_category = "image"
|
|
1291
|
+
payload: bytes | str = resolved.read_bytes()
|
|
1292
|
+
elif suffix in {".md", ".markdown"}:
|
|
1293
|
+
content_type, media_category = "text/markdown", "markdown"
|
|
1294
|
+
payload = _decode_text_file(resolved)
|
|
1295
|
+
else:
|
|
1296
|
+
text_types = {
|
|
1297
|
+
".txt", ".json", ".csv", ".tsv", ".log", ".py", ".js", ".ts", ".tsx",
|
|
1298
|
+
".jsx", ".html", ".css", ".yaml", ".yml", ".toml", ".xml", ".sh",
|
|
1299
|
+
".sql", ".rs", ".go", ".java", ".c", ".cpp", ".h", ".diff", ".ini",
|
|
1300
|
+
}
|
|
1301
|
+
if suffix not in text_types:
|
|
1302
|
+
raise StudioError(
|
|
1303
|
+
"WORKSPACE_FILE_UNSUPPORTED", "该文件类型暂不支持预览", status_code=415
|
|
1304
|
+
)
|
|
1305
|
+
content_type, media_category = "text/plain", "text"
|
|
1306
|
+
payload = _decode_text_file(resolved)
|
|
1307
|
+
response = {
|
|
1308
|
+
"path": str(resolved),
|
|
1309
|
+
"name": resolved.name,
|
|
1310
|
+
"sizeBytes": size,
|
|
1311
|
+
"contentType": content_type,
|
|
1312
|
+
"mediaCategory": media_category,
|
|
1313
|
+
}
|
|
1314
|
+
if download:
|
|
1315
|
+
quoted = quote(resolved.name)
|
|
1316
|
+
return Response(
|
|
1317
|
+
content=payload if isinstance(payload, bytes) else payload.encode("utf-8"),
|
|
1318
|
+
media_type=content_type,
|
|
1319
|
+
headers={"Content-Disposition": f"attachment; filename*=UTF-8''{quoted}"},
|
|
1320
|
+
)
|
|
1321
|
+
if media_category == "image":
|
|
1322
|
+
import base64
|
|
1323
|
+
|
|
1324
|
+
response["dataBase64"] = base64.b64encode(payload).decode("ascii")
|
|
1325
|
+
else:
|
|
1326
|
+
response["content"] = payload
|
|
1327
|
+
return response
|
|
1328
|
+
|
|
868
1329
|
@app.post("/api/v1/workspaces:open")
|
|
869
1330
|
async def open_workspace(payload: WorkspaceOpenRequest):
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1331
|
+
try:
|
|
1332
|
+
# A user-selected directory is itself the workspace. The registry
|
|
1333
|
+
# entry is created as part of opening it; callers do not need to
|
|
1334
|
+
# pre-register paths in a separate settings screen.
|
|
1335
|
+
record = studio.switch(payload.path, create=True)
|
|
1336
|
+
# Start local state immediately, but keep optional DSH/Profile
|
|
1337
|
+
# discovery off the workspace-switch response path.
|
|
1338
|
+
runtime = studio.active
|
|
1339
|
+
await runtime.start(wait_for_dsh=False)
|
|
1340
|
+
schedule_runtime_warmup = getattr(app.state, "runtime_warmups", None)
|
|
1341
|
+
if schedule_runtime_warmup is not None:
|
|
1342
|
+
schedule_runtime_warmup(runtime)
|
|
1343
|
+
except FileNotFoundError as error:
|
|
1344
|
+
raise StudioError("WORKSPACE_NOT_FOUND", "工作区目录不存在", status_code=404) from error
|
|
1345
|
+
response = {
|
|
1346
|
+
"name": record.name,
|
|
1347
|
+
"path": record.path,
|
|
1348
|
+
"workspaceId": record.workspace_id,
|
|
1349
|
+
}
|
|
1350
|
+
# Preserve the legacy reconnect response shape for the daemon root;
|
|
1351
|
+
# switched workspaces include the stable identity for scoped clients.
|
|
1352
|
+
if os.path.normcase(record.path) == os.path.normcase(str(initial_service.workspace.root)):
|
|
1353
|
+
response.pop("workspaceId", None)
|
|
1354
|
+
return response
|
|
1355
|
+
|
|
1356
|
+
@app.post("/api/v1/workspaces:choose")
|
|
1357
|
+
async def choose_workspace_directory():
|
|
1358
|
+
"""Open the host folder chooser for a local Web Studio session."""
|
|
1359
|
+
if sys.platform != "darwin":
|
|
1360
|
+
raise StudioError(
|
|
1361
|
+
"WORKSPACE_PICKER_UNAVAILABLE",
|
|
1362
|
+
"当前系统没有可用的原生目录选择器,请输入目录路径",
|
|
1363
|
+
status_code=501,
|
|
1364
|
+
)
|
|
1365
|
+
script = (
|
|
1366
|
+
'tell application "System Events" to set selectedFolder to choose folder '
|
|
1367
|
+
'with prompt "选择 AgentKit Studio 工作区"\n'
|
|
1368
|
+
'POSIX path of selectedFolder'
|
|
1369
|
+
)
|
|
1370
|
+
result = await asyncio.to_thread(
|
|
1371
|
+
subprocess.run,
|
|
1372
|
+
["osascript", "-e", script],
|
|
1373
|
+
capture_output=True,
|
|
1374
|
+
text=True,
|
|
1375
|
+
check=False,
|
|
1376
|
+
)
|
|
1377
|
+
if result.returncode != 0:
|
|
1378
|
+
return {"path": None, "cancelled": True}
|
|
1379
|
+
path = result.stdout.strip()
|
|
1380
|
+
return {"path": path or None, "cancelled": not bool(path)}
|
|
1381
|
+
|
|
1382
|
+
@app.get("/api/v1/workspaces")
|
|
1383
|
+
async def list_workspaces():
|
|
1384
|
+
active_path = os.path.normcase(str(studio.workspace.root))
|
|
1385
|
+
items = []
|
|
1386
|
+
for record in WorkspaceRegistry().list():
|
|
1387
|
+
item = record.__dict__.copy()
|
|
1388
|
+
item["active"] = os.path.normcase(record.path) == active_path
|
|
1389
|
+
items.append(item)
|
|
1390
|
+
return {"items": items}
|
|
1391
|
+
|
|
1392
|
+
@app.post("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1393
|
+
async def add_linked_directory(workspace_id: str, payload: LinkedDirectoryRequest):
|
|
1394
|
+
record = next(
|
|
1395
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1396
|
+
)
|
|
1397
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1398
|
+
str(studio.workspace.root)
|
|
1399
|
+
):
|
|
875
1400
|
raise StudioError(
|
|
876
|
-
"
|
|
877
|
-
|
|
878
|
-
|
|
1401
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1402
|
+
)
|
|
1403
|
+
item = LinkedDirectoryPolicy(studio.workspace.root).set(
|
|
1404
|
+
payload.path, payload.mode, payload.label
|
|
1405
|
+
)
|
|
1406
|
+
return item.__dict__
|
|
1407
|
+
|
|
1408
|
+
@app.get("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1409
|
+
async def list_linked_directories(workspace_id: str):
|
|
1410
|
+
record = next(
|
|
1411
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1412
|
+
)
|
|
1413
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1414
|
+
str(studio.workspace.root)
|
|
1415
|
+
):
|
|
1416
|
+
raise StudioError(
|
|
1417
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
879
1418
|
)
|
|
880
1419
|
return {
|
|
881
|
-
"
|
|
882
|
-
"path": str(studio.workspace.root),
|
|
1420
|
+
"items": [item.__dict__ for item in LinkedDirectoryPolicy(studio.workspace.root).list()]
|
|
883
1421
|
}
|
|
884
1422
|
|
|
1423
|
+
@app.delete("/api/v1/workspaces/{workspace_id}/linked-directories")
|
|
1424
|
+
async def remove_linked_directory(workspace_id: str, path: str):
|
|
1425
|
+
record = next(
|
|
1426
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1427
|
+
)
|
|
1428
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1429
|
+
str(studio.workspace.root)
|
|
1430
|
+
):
|
|
1431
|
+
raise StudioError(
|
|
1432
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1433
|
+
)
|
|
1434
|
+
return {"removed": LinkedDirectoryPolicy(studio.workspace.root).remove(path)}
|
|
1435
|
+
|
|
1436
|
+
@app.get("/api/v1/workspaces/{workspace_id}/linked-directories/authorize")
|
|
1437
|
+
async def authorize_linked_directory(
|
|
1438
|
+
workspace_id: str,
|
|
1439
|
+
path: str,
|
|
1440
|
+
operation: Literal["read", "write"] = "read",
|
|
1441
|
+
):
|
|
1442
|
+
record = next(
|
|
1443
|
+
(r for r in WorkspaceRegistry().list() if r.workspace_id == workspace_id), None
|
|
1444
|
+
)
|
|
1445
|
+
if record is None or os.path.normcase(record.path) != os.path.normcase(
|
|
1446
|
+
str(studio.workspace.root)
|
|
1447
|
+
):
|
|
1448
|
+
raise StudioError(
|
|
1449
|
+
"WORKSPACE_NOT_FOUND", "工作区不存在或不属于当前 Studio", status_code=404
|
|
1450
|
+
)
|
|
1451
|
+
allowed = LinkedDirectoryPolicy(studio.workspace.root).authorize(path, operation)
|
|
1452
|
+
return {"path": path, "operation": operation, "allowed": allowed}
|
|
1453
|
+
|
|
885
1454
|
@app.get("/api/v1/codex/manifest")
|
|
886
1455
|
async def get_codex_manifest():
|
|
887
1456
|
return studio.codex_manifest_state()
|
|
@@ -970,6 +1539,7 @@ def create_studio_app(
|
|
|
970
1539
|
unrelated Build.
|
|
971
1540
|
"""
|
|
972
1541
|
|
|
1542
|
+
await runtime_model_catalog()
|
|
973
1543
|
build = await studio.ensure_current_build(agent_id)
|
|
974
1544
|
return {
|
|
975
1545
|
"buildId": build.id,
|
|
@@ -1205,9 +1775,53 @@ def create_studio_app(
|
|
|
1205
1775
|
async def get_agent(agent_id: str):
|
|
1206
1776
|
return studio.agent_detail(agent_id)
|
|
1207
1777
|
|
|
1778
|
+
@app.post("/api/v1/agents/{agent_id}/runtime:prewarm", status_code=202)
|
|
1779
|
+
async def prewarm_agent_runtime(agent_id: str, payload: dict[str, Any]):
|
|
1780
|
+
"""后台预热当前 Build 的 Provider 激活(MCP/图编译),不执行任何 turn。
|
|
1781
|
+
|
|
1782
|
+
首 token 延迟的主因是首轮 open_activation 时的 MCP spawn/health/list
|
|
1783
|
+
(实测 ~12s)。前端在进入会话时 fire-and-forget 调用本端点,把这段
|
|
1784
|
+
开销移到用户输入之前;失败静默(首轮照旧现场预热)。
|
|
1785
|
+
"""
|
|
1786
|
+
session_id = str(payload.get("sessionId") or "")
|
|
1787
|
+
if not session_id:
|
|
1788
|
+
raise StudioError(
|
|
1789
|
+
"SESSION_ID_REQUIRED", "缺少 sessionId", status_code=422
|
|
1790
|
+
)
|
|
1791
|
+
try:
|
|
1792
|
+
build = await studio.ensure_current_build(agent_id)
|
|
1793
|
+
except StudioError as exc:
|
|
1794
|
+
raise StudioError(
|
|
1795
|
+
"BUILD_NOT_FOUND", f"Agent 尚无可运行的 Build:{exc.message}",
|
|
1796
|
+
status_code=404,
|
|
1797
|
+
) from exc
|
|
1798
|
+
|
|
1799
|
+
async def warm() -> None:
|
|
1800
|
+
try:
|
|
1801
|
+
spec = studio.resolve_run_spec(build.id)
|
|
1802
|
+
runtime = studio.run_service.plugin_runtime
|
|
1803
|
+
if runtime is None:
|
|
1804
|
+
return
|
|
1805
|
+
kernel_adapter = getattr(runtime, "kernel_adapter", None)
|
|
1806
|
+
if kernel_adapter is None:
|
|
1807
|
+
return
|
|
1808
|
+
# 打开并保留激活(以 session 为 key);下一轮 RunAgent 直接复用,
|
|
1809
|
+
# 不再现场 spawn/health/list MCP。
|
|
1810
|
+
await kernel_adapter(spec, session_id=session_id)
|
|
1811
|
+
except Exception as error:
|
|
1812
|
+
logger.info("runtime prewarm for %s skipped: %s", agent_id, error)
|
|
1813
|
+
|
|
1814
|
+
task = asyncio.create_task(warm())
|
|
1815
|
+
app.state.runtime_prewarms = getattr(app.state, "runtime_prewarms", set())
|
|
1816
|
+
app.state.runtime_prewarms.add(task)
|
|
1817
|
+
task.add_done_callback(app.state.runtime_prewarms.discard)
|
|
1818
|
+
return {"status": "prewarming", "buildId": build.id}
|
|
1819
|
+
|
|
1208
1820
|
@app.get("/api/v1/agents/{agent_id}/models")
|
|
1209
1821
|
async def get_agent_models(agent_id: str):
|
|
1210
|
-
|
|
1822
|
+
model_agent_id = shared_web.resolve_agent_id(agent_id)
|
|
1823
|
+
await runtime_model_catalog()
|
|
1824
|
+
return shared_web.list_models(model_agent_id)
|
|
1211
1825
|
|
|
1212
1826
|
@app.put("/api/v1/agents/{agent_id}")
|
|
1213
1827
|
async def update_agent(
|
|
@@ -1308,6 +1922,7 @@ def create_studio_app(
|
|
|
1308
1922
|
payload: BuildRequest,
|
|
1309
1923
|
idempotency_key: str | None = Header(default=None, alias="Idempotency-Key"),
|
|
1310
1924
|
):
|
|
1925
|
+
await runtime_model_catalog()
|
|
1311
1926
|
return studio.submit_studio_build(
|
|
1312
1927
|
agent_id,
|
|
1313
1928
|
revision=payload.revision,
|
|
@@ -1360,19 +1975,34 @@ def create_studio_app(
|
|
|
1360
1975
|
|
|
1361
1976
|
@app.get("/api/v1/runs/{run_id}")
|
|
1362
1977
|
async def get_run(run_id: str):
|
|
1363
|
-
|
|
1978
|
+
runtime = studio.runtime_for_run(run_id)
|
|
1979
|
+
if runtime is None:
|
|
1980
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
1981
|
+
return runtime.event_store.get(run_id)
|
|
1364
1982
|
|
|
1365
1983
|
@app.post("/api/v1/runs/{run_id}:cancel", status_code=202)
|
|
1366
1984
|
async def cancel_run(run_id: str):
|
|
1367
|
-
|
|
1985
|
+
runtime = studio.runtime_for_run(run_id)
|
|
1986
|
+
if runtime is None:
|
|
1987
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
1988
|
+
runtime._require_direct_run(run_id)
|
|
1989
|
+
return await runtime.run_service.cancel_run(run_id)
|
|
1368
1990
|
|
|
1369
1991
|
@app.post("/api/v1/runs/{run_id}:pause", status_code=202)
|
|
1370
1992
|
async def pause_run(run_id: str):
|
|
1371
|
-
|
|
1993
|
+
runtime = studio.runtime_for_run(run_id)
|
|
1994
|
+
if runtime is None:
|
|
1995
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
1996
|
+
runtime._require_direct_run(run_id)
|
|
1997
|
+
return await runtime.run_service.pause_run(run_id)
|
|
1372
1998
|
|
|
1373
1999
|
@app.post("/api/v1/runs/{run_id}:resume", status_code=202)
|
|
1374
2000
|
async def resume_run(run_id: str):
|
|
1375
|
-
|
|
2001
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2002
|
+
if runtime is None:
|
|
2003
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2004
|
+
runtime._require_direct_run(run_id)
|
|
2005
|
+
return await runtime.run_service.resume_run(run_id)
|
|
1376
2006
|
|
|
1377
2007
|
@app.post("/api/v1/runs/{run_id}/interactions/{interaction_id}:submit")
|
|
1378
2008
|
async def submit_run_interaction(
|
|
@@ -1380,7 +2010,10 @@ def create_studio_app(
|
|
|
1380
2010
|
interaction_id: str,
|
|
1381
2011
|
payload: InteractionSubmitRequest,
|
|
1382
2012
|
):
|
|
1383
|
-
|
|
2013
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2014
|
+
if runtime is None:
|
|
2015
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2016
|
+
return await runtime.run_service.submit_interaction(
|
|
1384
2017
|
run_id,
|
|
1385
2018
|
interaction_id,
|
|
1386
2019
|
name=payload.name,
|
|
@@ -1392,7 +2025,10 @@ def create_studio_app(
|
|
|
1392
2025
|
@app.get("/api/v1/runs/{run_id}/context")
|
|
1393
2026
|
async def get_run_context(run_id: str):
|
|
1394
2027
|
"""Runtime Context Evidence:planned/projected/actual + 精度 + ownership。"""
|
|
1395
|
-
|
|
2028
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2029
|
+
if runtime is None:
|
|
2030
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2031
|
+
record = runtime.event_store.get(run_id)
|
|
1396
2032
|
plan = record.context_plan or {}
|
|
1397
2033
|
evidence = record.prompt_evidence or {}
|
|
1398
2034
|
return {
|
|
@@ -1446,7 +2082,10 @@ def create_studio_app(
|
|
|
1446
2082
|
|
|
1447
2083
|
@app.delete("/api/v1/sessions/{session_id}", status_code=204)
|
|
1448
2084
|
async def delete_studio_session(session_id: str):
|
|
1449
|
-
await studio.
|
|
2085
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2086
|
+
if runtime is None:
|
|
2087
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2088
|
+
await runtime.delete_session(session_id)
|
|
1450
2089
|
return Response(status_code=204)
|
|
1451
2090
|
|
|
1452
2091
|
@app.get("/api/v1/sessions/{session_id}/events")
|
|
@@ -1456,7 +2095,10 @@ def create_studio_app(
|
|
|
1456
2095
|
invocation_id: str | None = Query(default=None, alias="invocationId"),
|
|
1457
2096
|
limit: int = Query(default=100, ge=1, le=500),
|
|
1458
2097
|
):
|
|
1459
|
-
|
|
2098
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2099
|
+
if runtime is None:
|
|
2100
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2101
|
+
return await runtime.trajectory_page(
|
|
1460
2102
|
session_id,
|
|
1461
2103
|
before_seq_id=before_seq_id,
|
|
1462
2104
|
invocation_id=invocation_id,
|
|
@@ -1470,10 +2112,13 @@ def create_studio_app(
|
|
|
1470
2112
|
after_seq_id: int = Query(default=0, ge=0, alias="afterSeqId"),
|
|
1471
2113
|
invocation_id: str | None = Query(default=None, alias="invocationId"),
|
|
1472
2114
|
):
|
|
1473
|
-
await studio.
|
|
2115
|
+
runtime = await studio.runtime_for_session(session_id)
|
|
2116
|
+
if runtime is None:
|
|
2117
|
+
raise StudioError("SESSION_NOT_FOUND", "会话不存在", status_code=404)
|
|
2118
|
+
await runtime._require_runtime_session(session_id)
|
|
1474
2119
|
last = request.headers.get("Last-Event-ID")
|
|
1475
2120
|
cursor = int(last) if last and last.isdigit() else after_seq_id
|
|
1476
|
-
stream =
|
|
2121
|
+
stream = runtime.stream_trajectory(
|
|
1477
2122
|
session_id,
|
|
1478
2123
|
cursor,
|
|
1479
2124
|
invocation_id=invocation_id,
|
|
@@ -1544,6 +2189,44 @@ def create_studio_app(
|
|
|
1544
2189
|
async def list_runs(session_id: str | None = Query(default=None, alias="sessionId")):
|
|
1545
2190
|
return {"items": studio.event_store.list_runs(session_id=session_id)}
|
|
1546
2191
|
|
|
2192
|
+
@app.get("/api/v1/workspaces/runs")
|
|
2193
|
+
async def list_workspace_runs():
|
|
2194
|
+
"""后台入口:聚合所有已打开 workspace 的运行,并保留归属。"""
|
|
2195
|
+
return {"items": studio.all_runs()}
|
|
2196
|
+
|
|
2197
|
+
@app.get("/api/v1/workspaces/operations")
|
|
2198
|
+
async def list_workspace_operations():
|
|
2199
|
+
return {"items": studio.all_operations()}
|
|
2200
|
+
|
|
2201
|
+
@app.get("/api/v1/runs/{run_id}/documents/metadata")
|
|
2202
|
+
def run_document_metadata(run_id: str, path: str, request: Request):
|
|
2203
|
+
return document_metadata(studio, run_id, path, local=is_local_desktop_request(request))
|
|
2204
|
+
|
|
2205
|
+
@app.post("/api/v1/runs/{run_id}/documents/actions")
|
|
2206
|
+
def run_document_action(run_id: str, payload: NativeDocumentActionRequest, request: Request):
|
|
2207
|
+
return perform_document_action(
|
|
2208
|
+
studio, run_id, payload, local=is_local_desktop_request(request)
|
|
2209
|
+
)
|
|
2210
|
+
|
|
2211
|
+
@app.get("/api/v1/runs/{run_id}/documents/content")
|
|
2212
|
+
def run_document(run_id: str, path: str, preview: bool = False):
|
|
2213
|
+
file_path, content = read_document(studio, run_id, path)
|
|
2214
|
+
if preview:
|
|
2215
|
+
return JSONResponse(
|
|
2216
|
+
{"name": file_path.name, "content": content},
|
|
2217
|
+
headers={"Cache-Control": "no-store"},
|
|
2218
|
+
)
|
|
2219
|
+
return Response(
|
|
2220
|
+
content,
|
|
2221
|
+
media_type="text/markdown",
|
|
2222
|
+
headers={
|
|
2223
|
+
"Content-Disposition": "attachment; filename*=UTF-8''"
|
|
2224
|
+
+ quote(file_path.name),
|
|
2225
|
+
"X-Content-Type-Options": "nosniff",
|
|
2226
|
+
"Cache-Control": "no-store",
|
|
2227
|
+
},
|
|
2228
|
+
)
|
|
2229
|
+
|
|
1547
2230
|
@app.get("/api/v1/runs/{run_id}/events")
|
|
1548
2231
|
async def run_events(
|
|
1549
2232
|
run_id: str,
|
|
@@ -1552,7 +2235,10 @@ def create_studio_app(
|
|
|
1552
2235
|
):
|
|
1553
2236
|
last = request.headers.get("Last-Event-ID")
|
|
1554
2237
|
cursor = int(last) if last and last.isdigit() else after
|
|
1555
|
-
|
|
2238
|
+
runtime = studio.runtime_for_run(run_id)
|
|
2239
|
+
if runtime is None:
|
|
2240
|
+
raise StudioError("RUN_NOT_FOUND", "运行不存在", status_code=404)
|
|
2241
|
+
events = await runtime.run_service.events(run_id, after=cursor)
|
|
1556
2242
|
return _sse(events)
|
|
1557
2243
|
|
|
1558
2244
|
@app.get("/api/v1/traces/overview")
|
|
@@ -1567,6 +2253,10 @@ def create_studio_app(
|
|
|
1567
2253
|
status=status,
|
|
1568
2254
|
)
|
|
1569
2255
|
|
|
2256
|
+
@app.get("/api/v1/workspaces/traces")
|
|
2257
|
+
async def list_workspace_traces():
|
|
2258
|
+
return {"items": studio.all_traces()}
|
|
2259
|
+
|
|
1570
2260
|
@app.get("/api/v1/traces")
|
|
1571
2261
|
async def list_traces(
|
|
1572
2262
|
agent_id: str | None = Query(default=None, alias="agentId"),
|
|
@@ -1668,7 +2358,7 @@ def create_studio_app(
|
|
|
1668
2358
|
async def list_deployments():
|
|
1669
2359
|
"""Read local deployment receipts without implicit cloud refreshes."""
|
|
1670
2360
|
|
|
1671
|
-
return {"items": studio.cloud.list()}
|
|
2361
|
+
return {"items": studio.cloud.list(), "currentIdentity": studio.cloud.cached_identity()}
|
|
1672
2362
|
|
|
1673
2363
|
@app.get("/api/v1/cloud-agents")
|
|
1674
2364
|
async def list_account_cloud_agents(
|
|
@@ -2010,11 +2700,17 @@ def create_studio_app(
|
|
|
2010
2700
|
|
|
2011
2701
|
@app.get("/api/v1/operations/{operation_id}")
|
|
2012
2702
|
async def get_operation(operation_id: str):
|
|
2013
|
-
|
|
2703
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2704
|
+
if runtime is None:
|
|
2705
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2706
|
+
return runtime.operations.get(operation_id)
|
|
2014
2707
|
|
|
2015
2708
|
@app.post("/api/v1/operations/{operation_id}:cancel")
|
|
2016
2709
|
async def cancel_operation(operation_id: str):
|
|
2017
|
-
|
|
2710
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2711
|
+
if runtime is None:
|
|
2712
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2713
|
+
return runtime.operations.cancel(operation_id)
|
|
2018
2714
|
|
|
2019
2715
|
@app.get("/api/v1/operations/{operation_id}/events")
|
|
2020
2716
|
async def operation_events(
|
|
@@ -2024,7 +2720,10 @@ def create_studio_app(
|
|
|
2024
2720
|
):
|
|
2025
2721
|
last = request.headers.get("Last-Event-ID")
|
|
2026
2722
|
cursor = int(last) if last and last.isdigit() else after
|
|
2027
|
-
|
|
2723
|
+
runtime = studio.runtime_for_operation(operation_id)
|
|
2724
|
+
if runtime is None:
|
|
2725
|
+
raise StudioError("OPERATION_NOT_FOUND", "操作不存在", status_code=404)
|
|
2726
|
+
events = runtime.operations.events(operation_id, after=cursor)
|
|
2028
2727
|
if "application/json" in request.headers.get("Accept", ""):
|
|
2029
2728
|
return {"items": events}
|
|
2030
2729
|
return _sse(events)
|
|
@@ -2035,6 +2734,24 @@ def create_studio_app(
|
|
|
2035
2734
|
runtime_model_catalog=runtime_model_catalog,
|
|
2036
2735
|
)
|
|
2037
2736
|
register_memory_routes(app, studio)
|
|
2737
|
+
register_resource_connection_routes(app, studio)
|
|
2038
2738
|
register_plugin_routes(app, studio)
|
|
2739
|
+
async def workspace_plugin_api(scope, receive, send):
|
|
2740
|
+
# The plugin registry belongs to the active workspace. Mounting the
|
|
2741
|
+
# initial service registry directly would keep lifecycle/routes pinned
|
|
2742
|
+
# to the first folder after a workspace switch.
|
|
2743
|
+
await studio.active.workspace_plugins.api(scope, receive, send)
|
|
2744
|
+
|
|
2745
|
+
app.mount("/api/v1", workspace_plugin_api, name="workspace-plugin-api")
|
|
2746
|
+
|
|
2747
|
+
from ksadk.studio.dsh_application import register_dsh_application
|
|
2748
|
+
|
|
2749
|
+
register_dsh_application(
|
|
2750
|
+
app,
|
|
2751
|
+
studio,
|
|
2752
|
+
session_secret=session_secret,
|
|
2753
|
+
security_enabled=security_enabled,
|
|
2754
|
+
fallback_url="/studio-shell/",
|
|
2755
|
+
)
|
|
2039
2756
|
|
|
2040
2757
|
return app
|