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
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
"""Human-readable activity drilldown derived from durable execution evidence.
|
|
2
|
+
|
|
3
|
+
This projection never reads model reasoning or tool arguments/results. Old
|
|
4
|
+
records retain honest action counts; richer records may attach an explicitly
|
|
5
|
+
public action description. Neither path rewrites the canonical event log.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import ipaddress
|
|
11
|
+
import json
|
|
12
|
+
import re
|
|
13
|
+
import time
|
|
14
|
+
from collections import OrderedDict
|
|
15
|
+
from typing import Any
|
|
16
|
+
from urllib.parse import urlsplit, urlunsplit
|
|
17
|
+
|
|
18
|
+
_TERMINAL = {"completed", "failed", "cancelled", "interrupted", "timed_out"}
|
|
19
|
+
_STATUS = {
|
|
20
|
+
"accepted": "running",
|
|
21
|
+
"started": "running",
|
|
22
|
+
"running": "running",
|
|
23
|
+
"in_progress": "running",
|
|
24
|
+
"succeeded": "completed",
|
|
25
|
+
"completed": "completed",
|
|
26
|
+
"done": "completed",
|
|
27
|
+
"failed": "failed",
|
|
28
|
+
"error": "failed",
|
|
29
|
+
"canceled": "cancelled",
|
|
30
|
+
"cancelled": "cancelled",
|
|
31
|
+
"interrupted": "unknown",
|
|
32
|
+
}
|
|
33
|
+
_ACTIONS = {
|
|
34
|
+
"web_search": ("search", "搜索资料"),
|
|
35
|
+
"web_fetch": ("fetch", "查看资料"),
|
|
36
|
+
"read_workspace_file": ("read", "读取文件"),
|
|
37
|
+
"list_workspace_files": ("read", "查看工作区"),
|
|
38
|
+
"write_workspace_file": ("write", "编辑并保存文件"),
|
|
39
|
+
"execute_command": ("command", "运行命令"),
|
|
40
|
+
"run_command": ("command", "运行命令"),
|
|
41
|
+
"exec_command": ("command", "运行命令"),
|
|
42
|
+
"run_workspace_command": ("command", "运行命令"),
|
|
43
|
+
"edit_workspace_file": ("write", "编辑并保存文件"),
|
|
44
|
+
# Codex native item kinds share the same activity vocabulary.
|
|
45
|
+
"commandExecution": ("command", "运行命令"),
|
|
46
|
+
"mcpToolCall": ("tool", "调用工具"),
|
|
47
|
+
"dynamicToolCall": ("tool", "调用工具"),
|
|
48
|
+
"webSearch": ("search", "搜索资料"),
|
|
49
|
+
"fileChange": ("write", "编辑并保存文件"),
|
|
50
|
+
}
|
|
51
|
+
# Codex canonical items keep their native kind only in source metadata; the
|
|
52
|
+
# projection reads the kind and timestamps, never item content (no tool
|
|
53
|
+
# arguments, no results, no reasoning text).
|
|
54
|
+
_CODEX_TOOL_ITEMS = frozenset(
|
|
55
|
+
{"commandExecution", "mcpToolCall", "dynamicToolCall", "webSearch", "fileChange"}
|
|
56
|
+
)
|
|
57
|
+
_TOOL_GROUP_KEYS = frozenset({"search", "fetch", "read", "write", "command", "tool"})
|
|
58
|
+
_SECRET = re.compile(
|
|
59
|
+
r"(?i)\b(?:[\w-]*(?:api[_-]?key|token|secret|password|authorization|cookie)[\w-]*)"
|
|
60
|
+
r"\s*(?:[:=]\s*|\s+)(?:[\"'][^\"'\n]*[\"']|[^\s,;]+)"
|
|
61
|
+
)
|
|
62
|
+
_BEARER = re.compile(r"(?i)\bBearer\s+[^\s,;]+")
|
|
63
|
+
_KEY = re.compile(r"\b(?:sk-[A-Za-z0-9_-]{12,}|[A-Za-z0-9_-]{40,})\b")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _retry_summary(detail: dict[str, Any]) -> str:
|
|
67
|
+
def number(key: str) -> int | None:
|
|
68
|
+
value = detail.get(key)
|
|
69
|
+
return (
|
|
70
|
+
value if isinstance(value, int) and not isinstance(value, bool) and value >= 0 else None
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
attempt = number("next_attempt")
|
|
74
|
+
previous_attempt = number("model_attempt")
|
|
75
|
+
if attempt is None and previous_attempt is not None:
|
|
76
|
+
attempt = previous_attempt + 1
|
|
77
|
+
maximum = number("max_attempts")
|
|
78
|
+
delay = number("delay_ms") or number("retry_delay_ms")
|
|
79
|
+
wait = f",{delay / 1000:g} 秒后" if delay else ",即将"
|
|
80
|
+
if attempt is not None and maximum is not None:
|
|
81
|
+
suffix = f"(第 {attempt}/{max(attempt, maximum)} 次)"
|
|
82
|
+
else:
|
|
83
|
+
suffix = f"(第 {attempt} 次)" if attempt is not None else ""
|
|
84
|
+
return f"模型服务繁忙{wait}自动重试{suffix}"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def safe_activity_url(value: Any) -> str | None:
|
|
88
|
+
"""Keep public HTTP links, without credentials, fragments or query secrets."""
|
|
89
|
+
if not isinstance(value, str) or len(value) > 2048:
|
|
90
|
+
return None
|
|
91
|
+
try:
|
|
92
|
+
parsed = urlsplit(value)
|
|
93
|
+
host = (parsed.hostname or "").lower().rstrip(".")
|
|
94
|
+
if (
|
|
95
|
+
parsed.scheme not in {"http", "https"}
|
|
96
|
+
or not host
|
|
97
|
+
or "." not in host
|
|
98
|
+
or parsed.username
|
|
99
|
+
or parsed.password
|
|
100
|
+
or host.endswith((".localhost", ".local", ".internal", ".lan"))
|
|
101
|
+
or host == "localhost"
|
|
102
|
+
):
|
|
103
|
+
return None
|
|
104
|
+
try:
|
|
105
|
+
if not ipaddress.ip_address(host).is_global:
|
|
106
|
+
return None
|
|
107
|
+
except ValueError:
|
|
108
|
+
pass
|
|
109
|
+
# Validate the port too; malformed netlocs must not survive rendering.
|
|
110
|
+
port = parsed.port
|
|
111
|
+
authority = host if port is None else f"{host}:{port}"
|
|
112
|
+
return urlunsplit((parsed.scheme, authority, parsed.path, "", ""))
|
|
113
|
+
except ValueError:
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _safe_text(value: Any) -> str:
|
|
118
|
+
if not isinstance(value, str):
|
|
119
|
+
return ""
|
|
120
|
+
text = " ".join(value.split())
|
|
121
|
+
text = re.sub(
|
|
122
|
+
r"https?://[^\s<>]+",
|
|
123
|
+
lambda match: safe_activity_url(match.group()) or "[链接已隐藏]",
|
|
124
|
+
text,
|
|
125
|
+
)
|
|
126
|
+
text = _SECRET.sub("[敏感信息已隐藏]", text)
|
|
127
|
+
text = _BEARER.sub("Bearer [已隐藏]", text)
|
|
128
|
+
return _KEY.sub("[已隐藏]", text)[:280]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _safe_commentary_text(value: Any) -> str:
|
|
132
|
+
"""Sanitize public progress and drop empty streaming fragments.
|
|
133
|
+
|
|
134
|
+
Older persisted runs can contain a punctuation-only trailing chunk even
|
|
135
|
+
after the runtime-side filter is tightened. The activity projection is
|
|
136
|
+
intentionally defensive so both old and new sessions render cleanly.
|
|
137
|
+
"""
|
|
138
|
+
text = _safe_text(value)
|
|
139
|
+
return text if re.search(r"[A-Za-z0-9\u3400-\u9fff]", text) else ""
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _records(events: list[Any]) -> list[dict[str, Any]]:
|
|
143
|
+
records = []
|
|
144
|
+
seen = set()
|
|
145
|
+
for event in events:
|
|
146
|
+
data = event.get("data", {}) if isinstance(event, dict) else event.data
|
|
147
|
+
if not isinstance(data, dict):
|
|
148
|
+
continue
|
|
149
|
+
native = data.get("runtimeEvent") or data.get("runtime_event") or {}
|
|
150
|
+
if not isinstance(native, dict):
|
|
151
|
+
continue
|
|
152
|
+
source = native.get("source") or {}
|
|
153
|
+
source = source if isinstance(source, dict) else {}
|
|
154
|
+
metadata = source.get("metadata") or {}
|
|
155
|
+
metadata = metadata if isinstance(metadata, dict) else {}
|
|
156
|
+
native_run = str(source.get("native_run_id") or native.get("run_id") or "")
|
|
157
|
+
# The same rich event can produce started/updated/completed canonical
|
|
158
|
+
# items. A retry must be shown once, not as three separate attempts.
|
|
159
|
+
identity = str(
|
|
160
|
+
source.get("native_event_id") or native.get("event_id") or f"row-{len(records)}"
|
|
161
|
+
)
|
|
162
|
+
seen_key = (native_run, identity)
|
|
163
|
+
if seen_key in seen:
|
|
164
|
+
continue
|
|
165
|
+
base = {
|
|
166
|
+
"run": native_run,
|
|
167
|
+
"scope": native.get("scope_id") or "",
|
|
168
|
+
"id": identity,
|
|
169
|
+
"session": metadata.get("session_id"),
|
|
170
|
+
"framework": str(source.get("framework") or ""),
|
|
171
|
+
"ts": native.get("timestamp")
|
|
172
|
+
if isinstance(native.get("timestamp"), (int, float))
|
|
173
|
+
else None,
|
|
174
|
+
}
|
|
175
|
+
parts = []
|
|
176
|
+
for field in ("snapshot", "initial"):
|
|
177
|
+
content = native.get(field)
|
|
178
|
+
if isinstance(content, dict) and isinstance(content.get("parts"), list):
|
|
179
|
+
parts.extend(content["parts"])
|
|
180
|
+
if isinstance(native.get("update"), dict):
|
|
181
|
+
parts.append(native["update"])
|
|
182
|
+
if native.get("item_kind") in {"message", "reasoning"}:
|
|
183
|
+
if (
|
|
184
|
+
native.get("item_kind") == "message"
|
|
185
|
+
and metadata.get("native_event_type") == "text.completed"
|
|
186
|
+
and metadata.get("phase") == "commentary"
|
|
187
|
+
):
|
|
188
|
+
for part in parts:
|
|
189
|
+
text = _safe_commentary_text(
|
|
190
|
+
part.get("text") if isinstance(part, dict) else None
|
|
191
|
+
)
|
|
192
|
+
if text:
|
|
193
|
+
records.append(
|
|
194
|
+
{
|
|
195
|
+
**base,
|
|
196
|
+
"type": "public.commentary",
|
|
197
|
+
"details": {"text": text},
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
seen.add(seen_key)
|
|
201
|
+
break
|
|
202
|
+
continue
|
|
203
|
+
if metadata.get("native_event_type") not in {"model.call.failed", "run.progress"}:
|
|
204
|
+
continue
|
|
205
|
+
for part in parts:
|
|
206
|
+
text = part.get("text") if isinstance(part, dict) else None
|
|
207
|
+
# This is the fixed public retry summary, never provider
|
|
208
|
+
# reasoning, error bodies, payloads or arbitrary output text.
|
|
209
|
+
if isinstance(text, str) and re.fullmatch(
|
|
210
|
+
r"模型服务繁忙(?:([^\n]{0,120}))?(?:,[\d.]+ 秒后)?"
|
|
211
|
+
r"自动重试(第 \d+/\d+ 次)",
|
|
212
|
+
text,
|
|
213
|
+
):
|
|
214
|
+
records.append(
|
|
215
|
+
{
|
|
216
|
+
**base,
|
|
217
|
+
"type": "provider.retry",
|
|
218
|
+
"details": {"text": _safe_text(text)},
|
|
219
|
+
}
|
|
220
|
+
)
|
|
221
|
+
seen.add(seen_key)
|
|
222
|
+
break
|
|
223
|
+
continue
|
|
224
|
+
if native.get("item_kind") in {"tool_call", "data"}:
|
|
225
|
+
# Non-harness runtimes (Codex) publish execution facts as canonical
|
|
226
|
+
# tool/data items; their native kind survives in source metadata.
|
|
227
|
+
# Translate them into the same record vocabulary as Harness so the
|
|
228
|
+
# projection below stays runtime-agnostic.
|
|
229
|
+
native_kind = str(metadata.get("native_item_kind") or "")
|
|
230
|
+
native_event = str(native.get("event_type") or "")
|
|
231
|
+
native_item = str(source.get("native_item_id") or identity)
|
|
232
|
+
if native_kind in _CODEX_TOOL_ITEMS:
|
|
233
|
+
if native_event == "item.started":
|
|
234
|
+
status = "running"
|
|
235
|
+
elif native_event == "item.completed":
|
|
236
|
+
status = "succeeded"
|
|
237
|
+
elif native_event in {"item.failed", "item.updated"}:
|
|
238
|
+
status = "failed" if native_event == "item.failed" else None
|
|
239
|
+
else:
|
|
240
|
+
status = None
|
|
241
|
+
if status is not None:
|
|
242
|
+
records.append(
|
|
243
|
+
{
|
|
244
|
+
**base,
|
|
245
|
+
"type": "tool.call.begin" if status == "running" else "tool.call.end",
|
|
246
|
+
"details": {
|
|
247
|
+
"name": native_kind,
|
|
248
|
+
"call_id": native_item,
|
|
249
|
+
"status": status,
|
|
250
|
+
},
|
|
251
|
+
}
|
|
252
|
+
)
|
|
253
|
+
seen.add(seen_key)
|
|
254
|
+
continue
|
|
255
|
+
if native_kind == "contextCompaction":
|
|
256
|
+
if native_event == "item.started":
|
|
257
|
+
records.append({**base, "type": "context.compaction.started", "details": {}})
|
|
258
|
+
seen.add(seen_key)
|
|
259
|
+
elif native_event == "item.completed":
|
|
260
|
+
records.append({**base, "type": "context.compaction.completed", "details": {}})
|
|
261
|
+
seen.add(seen_key)
|
|
262
|
+
continue
|
|
263
|
+
continue
|
|
264
|
+
if native.get("item_kind") != "status":
|
|
265
|
+
continue
|
|
266
|
+
for part in parts:
|
|
267
|
+
if not isinstance(part, dict) or not isinstance(part.get("text"), str):
|
|
268
|
+
continue
|
|
269
|
+
try:
|
|
270
|
+
payload = json.loads(part["text"])
|
|
271
|
+
except (ValueError, TypeError):
|
|
272
|
+
continue
|
|
273
|
+
if not isinstance(payload, dict) or not isinstance(payload.get("details"), dict):
|
|
274
|
+
continue
|
|
275
|
+
if payload.get("event") not in {
|
|
276
|
+
"tool.call.begin",
|
|
277
|
+
"tool.call.end",
|
|
278
|
+
"model.call.started",
|
|
279
|
+
"model.call.completed",
|
|
280
|
+
"model.call.failed",
|
|
281
|
+
"agent.started",
|
|
282
|
+
"agent.completed",
|
|
283
|
+
"context.compaction.started",
|
|
284
|
+
"context.compaction.completed",
|
|
285
|
+
"run.progress",
|
|
286
|
+
"text.completed",
|
|
287
|
+
}:
|
|
288
|
+
continue
|
|
289
|
+
event_type, detail = payload["event"], payload["details"]
|
|
290
|
+
if event_type == "text.completed":
|
|
291
|
+
text = _safe_commentary_text(detail.get("text"))
|
|
292
|
+
if metadata.get("phase") == "commentary" and text:
|
|
293
|
+
records.append(
|
|
294
|
+
{
|
|
295
|
+
**base,
|
|
296
|
+
"type": "public.commentary",
|
|
297
|
+
"details": {"text": text},
|
|
298
|
+
}
|
|
299
|
+
)
|
|
300
|
+
seen.add(seen_key)
|
|
301
|
+
break
|
|
302
|
+
if (event_type == "run.progress" and detail.get("kind") == "provider.retry") or (
|
|
303
|
+
event_type == "model.call.failed" and detail.get("action") == "retry_same_model"
|
|
304
|
+
):
|
|
305
|
+
event_type, detail = "provider.retry", {"text": _retry_summary(detail)}
|
|
306
|
+
records.append(
|
|
307
|
+
{
|
|
308
|
+
**base,
|
|
309
|
+
"type": event_type,
|
|
310
|
+
"details": detail,
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
seen.add(seen_key)
|
|
314
|
+
break
|
|
315
|
+
return records
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def project_run_activities(run: Any, events: list[Any]) -> dict[str, Any]:
|
|
319
|
+
status = str(getattr(run.status, "value", run.status)).lower()
|
|
320
|
+
observed_at = time.time()
|
|
321
|
+
result = {"runId": run.id, "status": status, "activities": []}
|
|
322
|
+
records = _records(events)
|
|
323
|
+
handle = getattr(run, "runtime_handle", {})
|
|
324
|
+
handle = handle if isinstance(handle, dict) else {}
|
|
325
|
+
own_runs = {
|
|
326
|
+
value for value in (run.id, handle.get("run_id")) if isinstance(value, str) and value
|
|
327
|
+
}
|
|
328
|
+
own_session = getattr(run, "session_id", None)
|
|
329
|
+
records = [
|
|
330
|
+
record
|
|
331
|
+
for record in records
|
|
332
|
+
if (
|
|
333
|
+
not record["run"]
|
|
334
|
+
# Provider-native run ids (e.g. Codex turn ids) are not Studio run
|
|
335
|
+
# identities; the per-run event fetch already scopes their events.
|
|
336
|
+
or record.get("framework") not in (None, "", "harness")
|
|
337
|
+
or any(
|
|
338
|
+
record["run"] == root or record["run"].startswith(f"{root}:sub:")
|
|
339
|
+
for root in own_runs
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
and (not own_session or not record["session"] or record["session"] == own_session)
|
|
343
|
+
]
|
|
344
|
+
children: dict[str, dict[str, Any]] = {}
|
|
345
|
+
# Lifecycle notices can arrive after a child's tools. Resolve labels first.
|
|
346
|
+
for record in records:
|
|
347
|
+
detail = record["details"]
|
|
348
|
+
if record["type"] == "run.progress" and detail.get("kind") in {
|
|
349
|
+
"subagent.event",
|
|
350
|
+
"delegation.route",
|
|
351
|
+
}:
|
|
352
|
+
call_id = str(detail.get("call_id") or "")
|
|
353
|
+
if not call_id:
|
|
354
|
+
continue
|
|
355
|
+
child = children.setdefault(call_id, {})
|
|
356
|
+
label = _safe_text(detail.get("label"))
|
|
357
|
+
if label:
|
|
358
|
+
child["label"] = label
|
|
359
|
+
if record.get("ts") is not None:
|
|
360
|
+
if child.get("ts_begin") is None:
|
|
361
|
+
child["ts_begin"] = record["ts"]
|
|
362
|
+
child["ts_last"] = record["ts"]
|
|
363
|
+
provider_ref = str(detail.get("provider_ref") or "")
|
|
364
|
+
if provider_ref:
|
|
365
|
+
child["provider"] = "Codex" if "codex" in provider_ref else "Harness"
|
|
366
|
+
if detail.get("status"):
|
|
367
|
+
next_status = _STATUS.get(str(detail["status"]).lower(), "unknown")
|
|
368
|
+
if child.get("status") not in {"completed", "failed", "cancelled"}:
|
|
369
|
+
child["status"] = next_status
|
|
370
|
+
if next_status in {"completed", "failed", "cancelled"}:
|
|
371
|
+
child["ts_end"] = record.get("ts")
|
|
372
|
+
elif detail.get("kind") == "delegation.route":
|
|
373
|
+
child.setdefault("status", "running")
|
|
374
|
+
summary = _safe_text(detail.get("public_summary"))
|
|
375
|
+
if summary:
|
|
376
|
+
child["summary"] = summary
|
|
377
|
+
child["summary_ts"] = record.get("ts")
|
|
378
|
+
owners: OrderedDict[str, dict[str, Any]] = OrderedDict()
|
|
379
|
+
owners[""] = {"groups": OrderedDict()}
|
|
380
|
+
|
|
381
|
+
def owner_of(record: dict[str, Any]) -> str:
|
|
382
|
+
return owner_of_record_run(record)
|
|
383
|
+
|
|
384
|
+
for record in records:
|
|
385
|
+
detail, event_type = record["details"], record["type"]
|
|
386
|
+
owner_id = owner_of(record)
|
|
387
|
+
owner = owners.setdefault(owner_id, {"groups": OrderedDict()})
|
|
388
|
+
if record.get("ts") is not None:
|
|
389
|
+
owner["ts_last"] = max(record["ts"], owner.get("ts_last") or record["ts"])
|
|
390
|
+
if event_type == "agent.started":
|
|
391
|
+
owner["status"] = "running"
|
|
392
|
+
if event_type == "agent.completed":
|
|
393
|
+
owner["status"] = _STATUS.get(str(detail.get("status")), "unknown")
|
|
394
|
+
if event_type == "provider.retry":
|
|
395
|
+
group = owner["groups"].setdefault(
|
|
396
|
+
"retry", {"label": "自动重试", "calls": OrderedDict()}
|
|
397
|
+
)
|
|
398
|
+
group["calls"][record["id"]] = {
|
|
399
|
+
"status": "running",
|
|
400
|
+
"label": "自动重试",
|
|
401
|
+
"text": detail["text"],
|
|
402
|
+
"retry": True,
|
|
403
|
+
}
|
|
404
|
+
# The event proves the current model attempt failed; keep that
|
|
405
|
+
# evidence instead of leaving its started record running forever.
|
|
406
|
+
active_model = owner.setdefault("active_phases", {}).pop("model", None)
|
|
407
|
+
model_group = owner["groups"].get("model")
|
|
408
|
+
if active_model and model_group:
|
|
409
|
+
model_group["calls"][active_model]["status"] = "failed"
|
|
410
|
+
continue
|
|
411
|
+
if event_type == "public.commentary":
|
|
412
|
+
commentary = {
|
|
413
|
+
"id": f"{run.id}:commentary:{record['id']}",
|
|
414
|
+
"kind": "commentary",
|
|
415
|
+
"label": "公开进展",
|
|
416
|
+
"status": "completed",
|
|
417
|
+
"text": detail["text"],
|
|
418
|
+
"details": [],
|
|
419
|
+
"_sortTs": (
|
|
420
|
+
record["ts"]
|
|
421
|
+
if isinstance(record.get("ts"), (int, float))
|
|
422
|
+
else float("inf")
|
|
423
|
+
),
|
|
424
|
+
}
|
|
425
|
+
if owner_id:
|
|
426
|
+
# Child progress belongs behind that child's Details affordance.
|
|
427
|
+
# Publishing every child checkpoint in the parent timeline turns
|
|
428
|
+
# a three-worker task into a wall of status text and makes it
|
|
429
|
+
# indistinguishable from the parent's own stage updates.
|
|
430
|
+
owner.setdefault("commentary", []).append(commentary)
|
|
431
|
+
else:
|
|
432
|
+
result["activities"].append(commentary)
|
|
433
|
+
continue
|
|
434
|
+
phase = {
|
|
435
|
+
"model.call.started": ("model", "running"),
|
|
436
|
+
"model.call.completed": ("model", "completed"),
|
|
437
|
+
"model.call.failed": ("model", "failed"),
|
|
438
|
+
"context.compaction.started": ("context", "running"),
|
|
439
|
+
"context.compaction.completed": ("context", "completed"),
|
|
440
|
+
}.get(event_type)
|
|
441
|
+
if phase:
|
|
442
|
+
base_key, phase_status = phase
|
|
443
|
+
# Deterministic phase titles derived from observed execution
|
|
444
|
+
# order: a model phase before any tool work is task analysis;
|
|
445
|
+
# after tool work it is result synthesis. The model never
|
|
446
|
+
# invents its own status labels.
|
|
447
|
+
if base_key == "model" and (
|
|
448
|
+
owner.get("tool_seen")
|
|
449
|
+
or any(group_key in owner["groups"] for group_key in _TOOL_GROUP_KEYS)
|
|
450
|
+
):
|
|
451
|
+
key, label = "model:summary", "汇总结果"
|
|
452
|
+
else:
|
|
453
|
+
key = base_key
|
|
454
|
+
label = "分析任务" if base_key == "model" else "压缩上下文"
|
|
455
|
+
group = owner["groups"].setdefault(key, {"label": label, "calls": OrderedDict()})
|
|
456
|
+
active = owner.setdefault("active_phases", {})
|
|
457
|
+
if phase_status == "running" or key not in active:
|
|
458
|
+
active[key] = record["id"]
|
|
459
|
+
call = group["calls"].setdefault(active[key], {"label": label})
|
|
460
|
+
call["status"] = phase_status
|
|
461
|
+
# These are deterministic execution summaries, not model chain of
|
|
462
|
+
# thought. They give the expandable row a useful human-facing
|
|
463
|
+
# explanation without exposing prompts, parameters or outputs.
|
|
464
|
+
call["text"] = {
|
|
465
|
+
"model": "理解任务并确定执行步骤",
|
|
466
|
+
"model:summary": "整理已完成的执行结果",
|
|
467
|
+
"context": "整理并压缩较早的上下文,关键执行状态继续保留",
|
|
468
|
+
}[key]
|
|
469
|
+
if record.get("ts") is not None:
|
|
470
|
+
if phase_status == "running":
|
|
471
|
+
call["ts_begin"] = record["ts"]
|
|
472
|
+
else:
|
|
473
|
+
call["ts_end"] = record["ts"]
|
|
474
|
+
call.setdefault("ts_begin", record["ts"])
|
|
475
|
+
if phase_status != "running":
|
|
476
|
+
active.pop(key, None)
|
|
477
|
+
if base_key == "model" and phase_status in {"completed", "failed"}:
|
|
478
|
+
for retry in owner["groups"].get("retry", {}).get("calls", {}).values():
|
|
479
|
+
if retry["status"] == "running":
|
|
480
|
+
retry["status"] = phase_status
|
|
481
|
+
retry["outcome"] = (
|
|
482
|
+
"重试后已恢复" if phase_status == "completed" else "重试后仍未成功"
|
|
483
|
+
)
|
|
484
|
+
continue
|
|
485
|
+
if event_type not in {"tool.call.begin", "tool.call.end"}:
|
|
486
|
+
continue
|
|
487
|
+
name = str(detail.get("name") or "tool")
|
|
488
|
+
# Delegation is rendered as a sub-agent row instead of a generic tool
|
|
489
|
+
# row, but it still separates the analysis model turn from the later
|
|
490
|
+
# result-synthesis turn.
|
|
491
|
+
owner["tool_seen"] = True
|
|
492
|
+
if name == "delegate_task":
|
|
493
|
+
continue
|
|
494
|
+
key, label = _ACTIONS.get(name, ("tool", "使用工具处理任务"))
|
|
495
|
+
group = owner["groups"].setdefault(key, {"label": label, "calls": OrderedDict()})
|
|
496
|
+
call_id = f"{record['scope']}:{detail.get('call_id') or record['id']}"
|
|
497
|
+
call = group["calls"].setdefault(call_id, {"status": "unknown", "label": label})
|
|
498
|
+
call["status"] = _STATUS.get(str(detail.get("status")), "unknown")
|
|
499
|
+
if record.get("ts") is not None:
|
|
500
|
+
if record["type"] == "tool.call.begin":
|
|
501
|
+
call.setdefault("ts_begin", record["ts"])
|
|
502
|
+
else:
|
|
503
|
+
call["ts_end"] = record["ts"]
|
|
504
|
+
call.setdefault("ts_begin", record["ts"])
|
|
505
|
+
action = detail.get("public_action")
|
|
506
|
+
if isinstance(action, dict):
|
|
507
|
+
text = _safe_text(action.get("text"))
|
|
508
|
+
if text:
|
|
509
|
+
call["text"] = text
|
|
510
|
+
href = safe_activity_url(action.get("href"))
|
|
511
|
+
if href:
|
|
512
|
+
call["href"] = href
|
|
513
|
+
|
|
514
|
+
def render_groups(owner_id: str, owner: dict[str, Any]) -> list[dict[str, Any]]:
|
|
515
|
+
groups = []
|
|
516
|
+
for key, group in owner["groups"].items():
|
|
517
|
+
details = []
|
|
518
|
+
statuses = []
|
|
519
|
+
generic: OrderedDict[tuple[str, str], list[dict[str, str]]] = OrderedDict()
|
|
520
|
+
# A retried public action is often recorded as two independent
|
|
521
|
+
# tool calls. Keep the failed attempt in the drilldown, but do
|
|
522
|
+
# not let it poison the whole group once a later call for the
|
|
523
|
+
# exact same public target succeeds. Calls without a public
|
|
524
|
+
# target remain conservative: their failure cannot be inferred
|
|
525
|
+
# away from labels or private arguments/results.
|
|
526
|
+
recovered_failures: set[str] = set()
|
|
527
|
+
completed_targets: set[tuple[str, str]] = set()
|
|
528
|
+
for call_id, call in reversed(group["calls"].items()):
|
|
529
|
+
target = (
|
|
530
|
+
("href", call["href"])
|
|
531
|
+
if call.get("href")
|
|
532
|
+
else (("text", call["text"]) if call.get("text") else None)
|
|
533
|
+
)
|
|
534
|
+
if key in _TOOL_GROUP_KEYS and call["status"] == "completed" and target:
|
|
535
|
+
completed_targets.add(target)
|
|
536
|
+
elif (
|
|
537
|
+
key in _TOOL_GROUP_KEYS
|
|
538
|
+
and call["status"] == "failed"
|
|
539
|
+
and target in completed_targets
|
|
540
|
+
):
|
|
541
|
+
recovered_failures.add(call_id)
|
|
542
|
+
calls_in_order = list(group["calls"].items())
|
|
543
|
+
if (
|
|
544
|
+
key == "write"
|
|
545
|
+
and calls_in_order
|
|
546
|
+
and calls_in_order[-1][1]["status"] == "completed"
|
|
547
|
+
):
|
|
548
|
+
# A malformed/truncated model tool call can fail before its
|
|
549
|
+
# arguments are safe enough to expose. If this same document
|
|
550
|
+
# delivery phase ends with an observed successful write, the
|
|
551
|
+
# earlier anonymous write failures are retry history, not the
|
|
552
|
+
# outcome of the phase. Keep them in the drilldown but do not
|
|
553
|
+
# paint the successfully delivered artifact red.
|
|
554
|
+
recovered_failures.update(
|
|
555
|
+
call_id
|
|
556
|
+
for call_id, call in calls_in_order[:-1]
|
|
557
|
+
if call["status"] == "failed" and not call.get("text")
|
|
558
|
+
)
|
|
559
|
+
for index, (call_id, call) in enumerate(group["calls"].items(), 1):
|
|
560
|
+
state = call["status"]
|
|
561
|
+
owner_status = children.get(owner_id, {}).get("status") or owner.get("status")
|
|
562
|
+
if state == "running" and (status in _TERMINAL or owner_status in _TERMINAL):
|
|
563
|
+
# The provider may omit a final model.call.completed after
|
|
564
|
+
# an approval resume. A canonical agent.completed event is
|
|
565
|
+
# positive evidence that the still-open model phase did
|
|
566
|
+
# finish; it is not enough to invent completion for tools.
|
|
567
|
+
if key.startswith("model") and owner_status == "completed":
|
|
568
|
+
state = "completed"
|
|
569
|
+
else:
|
|
570
|
+
state = (
|
|
571
|
+
"cancelled"
|
|
572
|
+
if status == "cancelled" or owner_status == "cancelled"
|
|
573
|
+
else "unknown"
|
|
574
|
+
)
|
|
575
|
+
effective_state = "completed" if call_id in recovered_failures else state
|
|
576
|
+
statuses.append(effective_state)
|
|
577
|
+
description = call.get("text") or f"第 {index} 次{call['label']}"
|
|
578
|
+
prefix = {
|
|
579
|
+
"running": "正在",
|
|
580
|
+
"completed": "已完成",
|
|
581
|
+
"failed": "未完成",
|
|
582
|
+
"cancelled": "已取消",
|
|
583
|
+
"unknown": "未确认完成",
|
|
584
|
+
}[state]
|
|
585
|
+
item = {"id": call_id, "text": f"{prefix}:{description}"}
|
|
586
|
+
if call_id in recovered_failures:
|
|
587
|
+
item["text"] = f"已重试:{description};后续已成功"
|
|
588
|
+
if call.get("retry"):
|
|
589
|
+
item["text"] = description
|
|
590
|
+
if call.get("outcome"):
|
|
591
|
+
item["text"] += f";{call['outcome']}"
|
|
592
|
+
elif state == "unknown":
|
|
593
|
+
item["text"] += ";未记录重试结果"
|
|
594
|
+
if call.get("href"):
|
|
595
|
+
item["href"] = call["href"]
|
|
596
|
+
details.append(item)
|
|
597
|
+
if not call.get("text"):
|
|
598
|
+
generic.setdefault((state, call["label"]), []).append(item)
|
|
599
|
+
# Older events have only action names. Forty-seven identical
|
|
600
|
+
# numbered rows add no evidence; summarize their real count while
|
|
601
|
+
# keeping failed/cancelled/unfinished calls separately visible.
|
|
602
|
+
for (state, label), items in generic.items():
|
|
603
|
+
if len(items) < 4:
|
|
604
|
+
continue
|
|
605
|
+
first = items[0]
|
|
606
|
+
prefix = {
|
|
607
|
+
"running": "正在执行",
|
|
608
|
+
"completed": "已完成",
|
|
609
|
+
"failed": "未完成",
|
|
610
|
+
"cancelled": "已取消",
|
|
611
|
+
"unknown": "未确认完成",
|
|
612
|
+
}[state]
|
|
613
|
+
first["text"] = f"{prefix} {len(items)} 次{label}(历史记录未保存更细的操作描述)"
|
|
614
|
+
other_ids = {item["id"] for item in items[1:]}
|
|
615
|
+
details = [item for item in details if item["id"] not in other_ids]
|
|
616
|
+
group_status = next(
|
|
617
|
+
(
|
|
618
|
+
value
|
|
619
|
+
for value in ("running", "failed", "unknown", "cancelled")
|
|
620
|
+
if value in statuses
|
|
621
|
+
),
|
|
622
|
+
"completed",
|
|
623
|
+
)
|
|
624
|
+
owner_status = children.get(owner_id, {}).get("status") or owner.get("status")
|
|
625
|
+
if group_status == "failed" and owner_status in {"running", "completed"}:
|
|
626
|
+
# A failed search/fetch attempt is not the outcome of a child
|
|
627
|
+
# that is still working or has ultimately completed. Keep the
|
|
628
|
+
# failed attempts visible in drilldown, but present the group
|
|
629
|
+
# as partial evidence rather than declaring the whole
|
|
630
|
+
# sub-agent execution failed.
|
|
631
|
+
group_status = "partial"
|
|
632
|
+
if key == "model" and statuses and statuses[-1] == "completed":
|
|
633
|
+
# A recovered model phase may include an earlier failed
|
|
634
|
+
# attempt. Preserve that detail but don't label the entire
|
|
635
|
+
# phase failed after an observed successful retry.
|
|
636
|
+
if "running" not in statuses and "unknown" not in statuses:
|
|
637
|
+
group_status = "completed"
|
|
638
|
+
if key in {"model", "model:summary", "context"} and details:
|
|
639
|
+
# Internal model turns are implementation detail. A phase
|
|
640
|
+
# may contain many calls, but users need one truthful phase
|
|
641
|
+
# summary rather than seven identical rows and a "7 次"
|
|
642
|
+
# counter. Retry evidence remains separately visible in the
|
|
643
|
+
# dedicated retry activity.
|
|
644
|
+
description = next(
|
|
645
|
+
(
|
|
646
|
+
call.get("text")
|
|
647
|
+
for call in reversed(group["calls"].values())
|
|
648
|
+
if call.get("text")
|
|
649
|
+
),
|
|
650
|
+
group["label"],
|
|
651
|
+
)
|
|
652
|
+
prefix = {
|
|
653
|
+
"running": "正在",
|
|
654
|
+
"completed": "已完成",
|
|
655
|
+
"failed": "未完成",
|
|
656
|
+
"cancelled": "已取消",
|
|
657
|
+
"unknown": "未确认完成",
|
|
658
|
+
}[group_status]
|
|
659
|
+
details = [
|
|
660
|
+
{
|
|
661
|
+
"id": f"{run.id}:{owner_id or 'parent'}:{key}:summary",
|
|
662
|
+
"text": f"{prefix}:{description}",
|
|
663
|
+
}
|
|
664
|
+
]
|
|
665
|
+
begins = [
|
|
666
|
+
call["ts_begin"]
|
|
667
|
+
for call in group["calls"].values()
|
|
668
|
+
if isinstance(call.get("ts_begin"), (int, float))
|
|
669
|
+
]
|
|
670
|
+
ends = [
|
|
671
|
+
call["ts_end"]
|
|
672
|
+
for call in group["calls"].values()
|
|
673
|
+
if isinstance(call.get("ts_end"), (int, float))
|
|
674
|
+
]
|
|
675
|
+
duration_ms = None
|
|
676
|
+
if begins:
|
|
677
|
+
owner_status = children.get(owner_id, {}).get("status") or owner.get("status")
|
|
678
|
+
still_running = (
|
|
679
|
+
"running" in statuses
|
|
680
|
+
and status not in _TERMINAL
|
|
681
|
+
and owner_status not in _TERMINAL
|
|
682
|
+
)
|
|
683
|
+
latest_end = (
|
|
684
|
+
observed_at if still_running else (max(ends) if ends else owner.get("ts_last"))
|
|
685
|
+
)
|
|
686
|
+
if isinstance(latest_end, (int, float)) and latest_end >= min(begins):
|
|
687
|
+
duration_ms = int((latest_end - min(begins)) * 1000)
|
|
688
|
+
groups.append(
|
|
689
|
+
{
|
|
690
|
+
"id": f"{run.id}:{owner_id or 'parent'}:{key}",
|
|
691
|
+
"kind": "step",
|
|
692
|
+
"label": group["label"],
|
|
693
|
+
"status": group_status,
|
|
694
|
+
"details": details,
|
|
695
|
+
**(
|
|
696
|
+
{}
|
|
697
|
+
if key in {"model", "model:summary", "context"}
|
|
698
|
+
else {"count": len(group["calls"])}
|
|
699
|
+
),
|
|
700
|
+
**({"durationMs": duration_ms} if duration_ms is not None else {}),
|
|
701
|
+
"_sortTs": min(begins) if begins else float("inf"),
|
|
702
|
+
}
|
|
703
|
+
)
|
|
704
|
+
return groups
|
|
705
|
+
|
|
706
|
+
result["activities"].extend(render_groups("", owners[""]))
|
|
707
|
+
# A lifecycle-only child must remain visible even without tool records.
|
|
708
|
+
for child_id in children:
|
|
709
|
+
owners.setdefault(child_id, {"groups": OrderedDict()})
|
|
710
|
+
for child_id, owner in owners.items():
|
|
711
|
+
if not child_id:
|
|
712
|
+
continue
|
|
713
|
+
metadata = children.get(child_id, {})
|
|
714
|
+
child_status = metadata.get("status") or owner.get("status") or "unknown"
|
|
715
|
+
if child_status == "running" and status in _TERMINAL:
|
|
716
|
+
child_status = "cancelled" if status == "cancelled" else "unknown"
|
|
717
|
+
groups = render_groups(child_id, owner)
|
|
718
|
+
summaries = (
|
|
719
|
+
[] if groups else [{"id": f"{child_id}:no-detail", "text": "暂未记录可展示的操作步骤"}]
|
|
720
|
+
)
|
|
721
|
+
duration_ms = None
|
|
722
|
+
ts_begin, ts_end = metadata.get("ts_begin"), metadata.get("ts_end")
|
|
723
|
+
if isinstance(ts_begin, (int, float)):
|
|
724
|
+
latest = (
|
|
725
|
+
observed_at
|
|
726
|
+
if child_status == "running" and status not in _TERMINAL
|
|
727
|
+
else ts_end
|
|
728
|
+
if isinstance(ts_end, (int, float))
|
|
729
|
+
else owner.get("ts_last")
|
|
730
|
+
)
|
|
731
|
+
if isinstance(latest, (int, float)) and latest >= ts_begin:
|
|
732
|
+
duration_ms = int((latest - ts_begin) * 1000)
|
|
733
|
+
entry: dict[str, Any] = {
|
|
734
|
+
"id": f"{run.id}:child:{child_id}",
|
|
735
|
+
"kind": "subagent",
|
|
736
|
+
"label": metadata.get("label") or "子智能体",
|
|
737
|
+
"status": child_status,
|
|
738
|
+
"details": summaries,
|
|
739
|
+
"children": groups,
|
|
740
|
+
"callId": child_id,
|
|
741
|
+
"_sortTs": (
|
|
742
|
+
ts_begin
|
|
743
|
+
if isinstance(ts_begin, (int, float))
|
|
744
|
+
else owner.get("ts_last", float("inf"))
|
|
745
|
+
),
|
|
746
|
+
}
|
|
747
|
+
if duration_ms is not None:
|
|
748
|
+
entry["durationMs"] = duration_ms
|
|
749
|
+
if metadata.get("provider"):
|
|
750
|
+
entry["provider"] = metadata["provider"]
|
|
751
|
+
result["activities"].append(entry)
|
|
752
|
+
# Parent phases, tools and delegated work are projected in their observed
|
|
753
|
+
# execution order. This lets a live timeline naturally read as
|
|
754
|
+
# analysis → sub-agent/tool work → optional compaction → result synthesis,
|
|
755
|
+
# rather than putting every child after all parent phases.
|
|
756
|
+
result["activities"].sort(key=lambda activity: activity.get("_sortTs", float("inf")))
|
|
757
|
+
for activity in result["activities"]:
|
|
758
|
+
activity.pop("_sortTs", None)
|
|
759
|
+
return result
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def _subagent_detail(run: Any, events: list[Any], call_id: str) -> dict[str, Any]:
|
|
763
|
+
"""Curated sub-agent facts for the detail panel.
|
|
764
|
+
|
|
765
|
+
Same evidence rules as the parent projection: lifecycle metadata and
|
|
766
|
+
public action descriptions only — never tool arguments, results or
|
|
767
|
+
model reasoning.
|
|
768
|
+
"""
|
|
769
|
+
|
|
770
|
+
projection = project_run_activities(run, events)
|
|
771
|
+
entry = next(
|
|
772
|
+
(
|
|
773
|
+
activity
|
|
774
|
+
for activity in projection["activities"]
|
|
775
|
+
if activity.get("kind") == "subagent" and activity.get("callId") == call_id
|
|
776
|
+
),
|
|
777
|
+
None,
|
|
778
|
+
)
|
|
779
|
+
if entry is None:
|
|
780
|
+
return {}
|
|
781
|
+
models = []
|
|
782
|
+
own_session = getattr(run, "session_id", None)
|
|
783
|
+
child_sessions = []
|
|
784
|
+
for record in _records(events):
|
|
785
|
+
if owner_of_record_run(record) != call_id:
|
|
786
|
+
continue
|
|
787
|
+
model = record["details"].get("model") if record["type"].startswith("model.call") else None
|
|
788
|
+
if model:
|
|
789
|
+
model = _safe_text(model)
|
|
790
|
+
if model and model not in models:
|
|
791
|
+
models.append(model)
|
|
792
|
+
if (
|
|
793
|
+
record.get("session")
|
|
794
|
+
and own_session
|
|
795
|
+
and record["session"] != own_session
|
|
796
|
+
and record["session"] not in child_sessions
|
|
797
|
+
):
|
|
798
|
+
child_sessions.append(record["session"])
|
|
799
|
+
child_progress = []
|
|
800
|
+
for record in _records(events):
|
|
801
|
+
if owner_of_record_run(record) != call_id or record["type"] != "public.commentary":
|
|
802
|
+
continue
|
|
803
|
+
child_progress.append(
|
|
804
|
+
{
|
|
805
|
+
"id": f"{run.id}:child:{call_id}:progress:{record['id']}",
|
|
806
|
+
"kind": "commentary",
|
|
807
|
+
"label": "阶段进展",
|
|
808
|
+
"status": "completed",
|
|
809
|
+
"text": record["details"]["text"],
|
|
810
|
+
"details": [],
|
|
811
|
+
}
|
|
812
|
+
)
|
|
813
|
+
# Keep the detail panel useful without replaying the child's entire chat.
|
|
814
|
+
# The first checkpoint explains the approach and the last two show the
|
|
815
|
+
# latest work; tool groups below retain the concrete execution evidence.
|
|
816
|
+
if len(child_progress) > 3:
|
|
817
|
+
child_progress = [child_progress[0], *child_progress[-2:]]
|
|
818
|
+
execution_facts = entry.get("children") or ([] if child_progress else entry["details"])
|
|
819
|
+
detail = {
|
|
820
|
+
"runId": run.id,
|
|
821
|
+
"callId": call_id,
|
|
822
|
+
"label": entry["label"],
|
|
823
|
+
"status": entry["status"],
|
|
824
|
+
"facts": [*child_progress, *execution_facts],
|
|
825
|
+
"parentStatus": projection["status"],
|
|
826
|
+
}
|
|
827
|
+
for key in ("durationMs", "provider"):
|
|
828
|
+
if entry.get(key) is not None:
|
|
829
|
+
detail[key] = entry[key]
|
|
830
|
+
if models:
|
|
831
|
+
detail["models"] = models
|
|
832
|
+
if child_sessions:
|
|
833
|
+
detail["sessionId"] = child_sessions[0]
|
|
834
|
+
return detail
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
def owner_of_record_run(record: dict[str, Any]) -> str:
|
|
838
|
+
# Scope hashes include the child's run ID, so parent_scope_id is not
|
|
839
|
+
# comparable to the parent's scope. The native child run suffix is the
|
|
840
|
+
# delegate call ID emitted by Harness and shared by lifecycle notices.
|
|
841
|
+
native_run = str(record["run"])
|
|
842
|
+
if ":sub:" not in native_run:
|
|
843
|
+
return ""
|
|
844
|
+
return native_run.rsplit(":", 1)[-1]
|
|
845
|
+
|
|
846
|
+
|
|
847
|
+
def register_activity_routes(app: Any, studio: Any, *, resolve_run_id: Any = None) -> None:
|
|
848
|
+
"""Use the Studio app's existing session/CSRF security middleware."""
|
|
849
|
+
|
|
850
|
+
@app.get("/api/v1/runs/{run_id}/activities")
|
|
851
|
+
async def run_activities(run_id: str):
|
|
852
|
+
from fastapi.responses import JSONResponse
|
|
853
|
+
|
|
854
|
+
resolved_id = resolve_run_id(run_id) if resolve_run_id else run_id
|
|
855
|
+
resolve_owner = getattr(studio, "runtime_for_run", None)
|
|
856
|
+
owner = resolve_owner(resolved_id) if callable(resolve_owner) else studio
|
|
857
|
+
if owner is None:
|
|
858
|
+
from ksadk.studio.errors import not_found
|
|
859
|
+
|
|
860
|
+
raise not_found("run", resolved_id)
|
|
861
|
+
run = owner.event_store.get(resolved_id)
|
|
862
|
+
events = await owner.run_service.events(resolved_id)
|
|
863
|
+
return JSONResponse(
|
|
864
|
+
project_run_activities(run, events), headers={"Cache-Control": "no-store"}
|
|
865
|
+
)
|
|
866
|
+
|
|
867
|
+
@app.get("/api/v1/runs/{run_id}/subagents/{call_id}")
|
|
868
|
+
async def run_subagent(run_id: str, call_id: str):
|
|
869
|
+
from fastapi.responses import JSONResponse
|
|
870
|
+
|
|
871
|
+
from ksadk.studio.errors import not_found
|
|
872
|
+
|
|
873
|
+
resolved_id = resolve_run_id(run_id) if resolve_run_id else run_id
|
|
874
|
+
resolve_owner = getattr(studio, "runtime_for_run", None)
|
|
875
|
+
owner = resolve_owner(resolved_id) if callable(resolve_owner) else studio
|
|
876
|
+
if owner is None:
|
|
877
|
+
error = not_found("run", resolved_id)
|
|
878
|
+
else:
|
|
879
|
+
run = owner.event_store.get(resolved_id)
|
|
880
|
+
events = await owner.run_service.events(resolved_id)
|
|
881
|
+
detail = _subagent_detail(run, events, call_id)
|
|
882
|
+
if detail:
|
|
883
|
+
return JSONResponse(detail, headers={"Cache-Control": "no-store"})
|
|
884
|
+
error = not_found("subagent", call_id)
|
|
885
|
+
return JSONResponse(
|
|
886
|
+
{
|
|
887
|
+
"error": {
|
|
888
|
+
"code": error.code,
|
|
889
|
+
"message": error.message,
|
|
890
|
+
"details": error.details or {},
|
|
891
|
+
}
|
|
892
|
+
},
|
|
893
|
+
status_code=error.status_code,
|
|
894
|
+
headers={"Cache-Control": "no-store"},
|
|
895
|
+
)
|