synth-ai 0.18.2.dev606__tar.gz → 0.18.2.dev607__tar.gz
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.
- {synth_ai-0.18.2.dev606/synth_ai.egg-info → synth_ai-0.18.2.dev607}/PKG-INFO +1 -1
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/pyproject.toml +1 -1
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/registry.py +5 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/server.py +5 -0
- synth_ai-0.18.2.dev607/synth_ai/mcp/research/tools/visuals.py +491 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/workspace_inputs.py +52 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607/synth_ai.egg-info}/PKG-INFO +1 -1
- synth_ai-0.18.2.dev606/synth_ai/mcp/research/tools/visuals.py +0 -213
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/LICENSE +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/MANIFEST.in +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/setup.cfg +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/__main__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/AGENTS.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/__main__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/main.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/research.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/research_environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/research_image_releases.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/cli/research_projects.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/client.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/auth/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/auth/credentials.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/contracts/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/contracts/json_value.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/contracts/pagination.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/errors.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/async_transport.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/request.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/retry.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/streaming.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/http/transport.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/research/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/utils/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/utils/env.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/utils/log_filter.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/utils/paths.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/core/utils/urls.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/__main__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/objective_tools.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/request_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/approvals.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/artifacts.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/datasets.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/exports.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/factories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/factory_results.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/files.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/image_releases.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/integrations.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/logs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/outputs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/policy_schemas.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/progress.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/project_data.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/projects.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/prs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/readiness.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/repos.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/research_intern.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/resources.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/runs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/trained_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/usage.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/py.typed +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/pagination.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/_internal/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/_internal/crypto.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/_internal/env.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/_internal/urls.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/account.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/advanced.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/advanced_factories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/advanced_swarms.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/artifacts.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/auth.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/client.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/_activity_wire.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/_environment_wire.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/_transcript_wire.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/_wire.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/activity.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/activity_items.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/actor_images.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/billing.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/canonical_usage.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/checkpoints.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/cloud_deployment_claims.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/cloud_deployments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/common.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/dataset_revisions.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/deliveries.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/dev_environment_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/economics.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/environment_manifest.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/factories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/factory_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/factory_lenses.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/factory_operations.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/factory_role_receipts.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/failure.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/image_releases.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/limit_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/local_execution_profile.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/operator_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/project.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/project_data.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/project_runtime.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/project_workspace.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/project_workspace_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/projects.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/promotions.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/research_intern.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_authority.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_control.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_diagnostics.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_events.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_execution.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_launch.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_observability.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_state.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/run_timeline.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/runtime_image.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/runtime_intent.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/runtime_stream.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/runtime_stream_snapshot.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/scientific_integrity.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_actor_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_actor_policy_data.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_agent_harnesses.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_agent_kinds.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_agent_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_branching.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_credential_providers.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_environment_kinds.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_evidence_obligations.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_funding_sources.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_horizons.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_host_kinds.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_inference_providers.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_network_topology.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_providers.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_resource_kinds.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_roles.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_run_policy.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_runbooks.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_runnable_project.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_runtime_kinds.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_tool_providers.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/smr_work_modes.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/status.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/swarms.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/tag.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/traces.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/transcript.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/types.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/usage.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/visuals.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/wire_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/wire_models_README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/work_products.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/contracts/workspaces.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/economics.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/efforts.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/errors.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/events.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/experiments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/facade.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/factories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/factory_storage.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/image_releases.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/knowledge.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/operations.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/project_data.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/project_deliveries.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/project_workspaces.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/projects.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/public.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/readouts.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/research_intern.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/secrets.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/README.md +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/_base.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/_client_helpers.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/_run_authority_mixin.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/approvals.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/billing.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/client.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/cloud_deployments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/config.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/cost.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/datasets.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/dev_environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/environments.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/exports.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/factories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/factory_evidence.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/files.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/github.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/image_releases.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/images.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/logs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/outputs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/progress.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/project.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/projects.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/prs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/readiness.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/repositories.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/runs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/secrets.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/setup.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/tag.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/trained_models.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/transport.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/usage.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/work_products.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/session/workspace_inputs.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/swarms.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/traces.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/transport/__init__.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/transport/http.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/transport/pagination.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/version.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/visuals.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/sdk/research/wiki.py +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai.egg-info/SOURCES.txt +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai.egg-info/dependency_links.txt +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai.egg-info/entry_points.txt +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai.egg-info/requires.txt +0 -0
- {synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai.egg-info/top_level.txt +0 -0
|
@@ -55,6 +55,7 @@ _DEFAULT_REQUIRED_SCOPES_BY_TOOL_NAME: dict[str, tuple[str, ...]] = {
|
|
|
55
55
|
"research_attach_source_repo": WRITE_SCOPES,
|
|
56
56
|
"research_get_workspace_inputs": READ_SCOPES,
|
|
57
57
|
"research_upload_workspace_files": WRITE_SCOPES,
|
|
58
|
+
"research_confirm_workspace_push": WRITE_SCOPES,
|
|
58
59
|
"research_list_project_files": READ_SCOPES,
|
|
59
60
|
"research_create_project_files": WRITE_SCOPES,
|
|
60
61
|
"research_get_project_file": READ_SCOPES,
|
|
@@ -190,6 +191,10 @@ _DEFAULT_REQUIRED_SCOPES_BY_TOOL_NAME: dict[str, tuple[str, ...]] = {
|
|
|
190
191
|
"research_work_repos_list": READ_SCOPES,
|
|
191
192
|
"research_work_repos_attach": WRITE_SCOPES,
|
|
192
193
|
"research_work_repos_detach": WRITE_SCOPES,
|
|
194
|
+
"research_create_visual": WRITE_SCOPES,
|
|
195
|
+
"research_update_visual": WRITE_SCOPES,
|
|
196
|
+
"research_promote_visual": WRITE_SCOPES,
|
|
197
|
+
"research_unpublish_visual": WRITE_SCOPES,
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
|
|
@@ -146,6 +146,10 @@ _STABLE_TOOL_NAMES = frozenset(
|
|
|
146
146
|
"research_get_visual",
|
|
147
147
|
"research_get_visual_content",
|
|
148
148
|
"research_get_visual_preview",
|
|
149
|
+
"research_create_visual",
|
|
150
|
+
"research_update_visual",
|
|
151
|
+
"research_promote_visual",
|
|
152
|
+
"research_unpublish_visual",
|
|
149
153
|
"research_get_run",
|
|
150
154
|
"research_get_run_transcript",
|
|
151
155
|
"research_get_swarm_activity",
|
|
@@ -183,6 +187,7 @@ _STABLE_TOOL_NAMES = frozenset(
|
|
|
183
187
|
"research_update_project_repository",
|
|
184
188
|
"research_upload_project_dataset",
|
|
185
189
|
"research_upload_workspace_files",
|
|
190
|
+
"research_confirm_workspace_push",
|
|
186
191
|
"research_watch_run_events",
|
|
187
192
|
"research_attach_source_repo",
|
|
188
193
|
"research_attach_research_intern_factory",
|
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
"""Stable MCP adapters for first-class Research Visuals.
|
|
2
|
+
|
|
3
|
+
Mutation surface (v1): create, update, promote, unpublish. ``delete`` and
|
|
4
|
+
``restore`` exist in the SDK but are deliberately omitted here — they are
|
|
5
|
+
destructive lifecycle operations and stay SDK-only until an explicit MCP
|
|
6
|
+
ruling admits them.
|
|
7
|
+
|
|
8
|
+
Score-series authority: score-series Visuals are server-authoritative. The
|
|
9
|
+
backend appends score points as results are scored; no MCP mutation path may
|
|
10
|
+
create or rewrite a Visual claiming a score-series kind. See
|
|
11
|
+
:func:`_reject_score_series_kind`.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import base64
|
|
17
|
+
import binascii
|
|
18
|
+
from collections.abc import Callable
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
from synth_ai.core.errors import (
|
|
22
|
+
RetryDirective,
|
|
23
|
+
SynthError,
|
|
24
|
+
SynthErrorCategory,
|
|
25
|
+
SynthErrorCode,
|
|
26
|
+
SynthFailure,
|
|
27
|
+
)
|
|
28
|
+
from synth_ai.mcp.research.registry import (
|
|
29
|
+
READ_SCOPES,
|
|
30
|
+
WRITE_SCOPES,
|
|
31
|
+
JSONDict,
|
|
32
|
+
ToolDefinition,
|
|
33
|
+
tool_schema,
|
|
34
|
+
)
|
|
35
|
+
from synth_ai.mcp.research.request_models import (
|
|
36
|
+
optional_bool,
|
|
37
|
+
optional_int,
|
|
38
|
+
optional_string,
|
|
39
|
+
require_string,
|
|
40
|
+
)
|
|
41
|
+
from synth_ai.sdk.research.client import Client as ResearchClient
|
|
42
|
+
from synth_ai.sdk.research.contracts.common import (
|
|
43
|
+
ArtifactId,
|
|
44
|
+
EffortId,
|
|
45
|
+
FactoryId,
|
|
46
|
+
ProjectId,
|
|
47
|
+
)
|
|
48
|
+
from synth_ai.sdk.research.contracts.visuals import (
|
|
49
|
+
Visual,
|
|
50
|
+
VisualPatch,
|
|
51
|
+
VisualPromotion,
|
|
52
|
+
VisualVisibility,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
CoreClientFactory = Callable[[JSONDict], ResearchClient]
|
|
56
|
+
_MCP_BINARY_CHUNK_BYTES_DEFAULT = 65_536
|
|
57
|
+
_MCP_BINARY_CHUNK_BYTES_MAX = 131_072
|
|
58
|
+
|
|
59
|
+
VISUAL_SCORE_SERIES_ERROR_CODE = "visual_score_series_server_authoritative"
|
|
60
|
+
|
|
61
|
+
_SCORE_SERIES_GUARD_NOTE = (
|
|
62
|
+
"Score-series Visuals are server-authoritative (the backend appends points "
|
|
63
|
+
"on scored results); any visual_kind claiming a score series is refused "
|
|
64
|
+
f"with error code '{VISUAL_SCORE_SERIES_ERROR_CODE}'."
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class VisualScoreSeriesServerAuthoritativeError(SynthError):
|
|
69
|
+
"""Refusal: MCP mutation must never write score-series Visual data.
|
|
70
|
+
|
|
71
|
+
Score series are appended by the backend as results are scored. Allowing
|
|
72
|
+
a client-supplied Visual to claim a score-series kind would let arbitrary
|
|
73
|
+
HTML masquerade as authoritative score data, so the MCP layer refuses the
|
|
74
|
+
payload before any client or network request is constructed.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self, visual_kind: str) -> None:
|
|
78
|
+
detail = (
|
|
79
|
+
f"visual_kind {visual_kind!r} claims a score-series Visual; score "
|
|
80
|
+
"series are server-authoritative (the backend appends points on "
|
|
81
|
+
"scored results) and cannot be created or rewritten through "
|
|
82
|
+
"MCP/SDK visual mutation."
|
|
83
|
+
)
|
|
84
|
+
super().__init__(
|
|
85
|
+
detail,
|
|
86
|
+
failure=SynthFailure(
|
|
87
|
+
code=SynthErrorCode(VISUAL_SCORE_SERIES_ERROR_CODE),
|
|
88
|
+
category=SynthErrorCategory.VALIDATION,
|
|
89
|
+
operation="mutate_visual",
|
|
90
|
+
request_id=None,
|
|
91
|
+
correlation_id=None,
|
|
92
|
+
retry=RetryDirective(retryable=False),
|
|
93
|
+
status=None,
|
|
94
|
+
detail=detail,
|
|
95
|
+
),
|
|
96
|
+
)
|
|
97
|
+
self.visual_kind = visual_kind
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _reject_score_series_kind(visual_kind: str | None) -> None:
|
|
101
|
+
"""Refuse any visual_kind that claims score-series authority.
|
|
102
|
+
|
|
103
|
+
Separator- and case-insensitive: ``score_series``, ``score-series``,
|
|
104
|
+
``Score Series``, ``scoreSeries``, and namespaced spellings such as
|
|
105
|
+
``factory.score_series`` all collapse to the same claim and are refused.
|
|
106
|
+
"""
|
|
107
|
+
if visual_kind is None:
|
|
108
|
+
return
|
|
109
|
+
collapsed = "".join(char for char in visual_kind.lower() if char.isalnum())
|
|
110
|
+
if "scoreseries" in collapsed:
|
|
111
|
+
raise VisualScoreSeriesServerAuthoritativeError(visual_kind)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _optional_visibility(args: JSONDict) -> VisualVisibility | None:
|
|
115
|
+
value = optional_string(args, "visibility")
|
|
116
|
+
return VisualVisibility(value) if value is not None else None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _optional_metadata(args: JSONDict) -> dict[str, Any] | None:
|
|
120
|
+
value = args.get("metadata")
|
|
121
|
+
if value is None:
|
|
122
|
+
return None
|
|
123
|
+
if not isinstance(value, dict):
|
|
124
|
+
raise ValueError("'metadata' must be an object when provided")
|
|
125
|
+
return value
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _optional_string_array(args: JSONDict, key: str) -> tuple[str, ...]:
|
|
129
|
+
value = args.get(key)
|
|
130
|
+
if value is None:
|
|
131
|
+
return ()
|
|
132
|
+
if not isinstance(value, list) or not all(
|
|
133
|
+
isinstance(item, str) and item.strip() for item in value
|
|
134
|
+
):
|
|
135
|
+
raise ValueError(f"'{key}' must be an array of non-empty strings when provided")
|
|
136
|
+
return tuple(item.strip() for item in value)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _optional_base64_bytes(args: JSONDict, key: str) -> bytes | None:
|
|
140
|
+
value = optional_string(args, key)
|
|
141
|
+
if value is None:
|
|
142
|
+
return None
|
|
143
|
+
try:
|
|
144
|
+
return base64.b64decode(value, validate=True)
|
|
145
|
+
except (binascii.Error, ValueError) as exc:
|
|
146
|
+
raise ValueError(f"'{key}' must be valid base64 when provided") from exc
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _content_payload(
|
|
150
|
+
visual: Visual,
|
|
151
|
+
content: bytes,
|
|
152
|
+
*,
|
|
153
|
+
content_type: str,
|
|
154
|
+
offset: int,
|
|
155
|
+
max_bytes: int,
|
|
156
|
+
include_content_digest: bool,
|
|
157
|
+
) -> JSONDict:
|
|
158
|
+
if offset < 0:
|
|
159
|
+
raise ValueError("offset must be a non-negative integer")
|
|
160
|
+
if max_bytes < 1 or max_bytes > _MCP_BINARY_CHUNK_BYTES_MAX:
|
|
161
|
+
raise ValueError(f"max_bytes must be between 1 and {_MCP_BINARY_CHUNK_BYTES_MAX}")
|
|
162
|
+
chunk = content[offset : offset + max_bytes]
|
|
163
|
+
next_offset = offset + len(chunk)
|
|
164
|
+
payload: JSONDict = {
|
|
165
|
+
"schema_version": "visual-content-chunk-v1",
|
|
166
|
+
"hosted_artifact_id": str(visual.hosted_artifact_id),
|
|
167
|
+
"root_artifact_id": str(visual.root_artifact_id),
|
|
168
|
+
"project_id": str(visual.project_id),
|
|
169
|
+
"artifact_version": visual.artifact_version,
|
|
170
|
+
"content_type": content_type,
|
|
171
|
+
"encoding": "base64",
|
|
172
|
+
"content_base64": base64.b64encode(chunk).decode("ascii"),
|
|
173
|
+
"size_bytes": len(content),
|
|
174
|
+
"offset": offset,
|
|
175
|
+
"bytes_returned": len(chunk),
|
|
176
|
+
"eof": next_offset >= len(content),
|
|
177
|
+
"next_offset": next_offset if next_offset < len(content) else None,
|
|
178
|
+
}
|
|
179
|
+
if include_content_digest:
|
|
180
|
+
payload["content_digest"] = visual.content_digest
|
|
181
|
+
return payload
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def _chunk_request(args: JSONDict) -> tuple[int, int]:
|
|
185
|
+
offset = optional_int(args, "offset")
|
|
186
|
+
max_bytes = optional_int(args, "max_bytes")
|
|
187
|
+
return (
|
|
188
|
+
offset if offset is not None else 0,
|
|
189
|
+
max_bytes if max_bytes is not None else _MCP_BINARY_CHUNK_BYTES_DEFAULT,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def build_visual_tools(
|
|
194
|
+
client_from_args: CoreClientFactory,
|
|
195
|
+
) -> list[ToolDefinition]:
|
|
196
|
+
"""Build the stable authenticated Visual read and mutate adapters."""
|
|
197
|
+
|
|
198
|
+
def list_visuals(args: JSONDict) -> JSONDict:
|
|
199
|
+
project_id = ProjectId(require_string(args, "project_id"))
|
|
200
|
+
factory_id = optional_string(args, "factory_id")
|
|
201
|
+
effort_id = optional_string(args, "effort_id")
|
|
202
|
+
limit = optional_int(args, "limit")
|
|
203
|
+
with client_from_args(args) as client:
|
|
204
|
+
return client.visuals.list(
|
|
205
|
+
project_id,
|
|
206
|
+
visual_kind=optional_string(args, "visual_kind"),
|
|
207
|
+
visibility=_optional_visibility(args),
|
|
208
|
+
factory_id=FactoryId(factory_id) if factory_id is not None else None,
|
|
209
|
+
effort_id=EffortId(effort_id) if effort_id is not None else None,
|
|
210
|
+
include_deleted=optional_bool(args, "include_deleted"),
|
|
211
|
+
cursor=optional_string(args, "cursor"),
|
|
212
|
+
limit=limit if limit is not None else 100,
|
|
213
|
+
).to_wire()
|
|
214
|
+
|
|
215
|
+
def get_visual(args: JSONDict) -> JSONDict:
|
|
216
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
217
|
+
with client_from_args(args) as client:
|
|
218
|
+
return client.visuals.retrieve(visual_id).to_wire()
|
|
219
|
+
|
|
220
|
+
def get_visual_content(args: JSONDict) -> JSONDict:
|
|
221
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
222
|
+
offset, max_bytes = _chunk_request(args)
|
|
223
|
+
with client_from_args(args) as client:
|
|
224
|
+
visual = client.visuals.retrieve(visual_id)
|
|
225
|
+
content = client.visuals.retrieve_content(visual_id)
|
|
226
|
+
return _content_payload(
|
|
227
|
+
visual,
|
|
228
|
+
content,
|
|
229
|
+
content_type="text/html",
|
|
230
|
+
offset=offset,
|
|
231
|
+
max_bytes=max_bytes,
|
|
232
|
+
include_content_digest=True,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
def get_visual_preview(args: JSONDict) -> JSONDict:
|
|
236
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
237
|
+
offset, max_bytes = _chunk_request(args)
|
|
238
|
+
with client_from_args(args) as client:
|
|
239
|
+
visual = client.visuals.retrieve(visual_id)
|
|
240
|
+
content = client.visuals.retrieve_preview(visual_id)
|
|
241
|
+
return _content_payload(
|
|
242
|
+
visual,
|
|
243
|
+
content,
|
|
244
|
+
content_type="image/png",
|
|
245
|
+
offset=offset,
|
|
246
|
+
max_bytes=max_bytes,
|
|
247
|
+
include_content_digest=False,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def create_visual(args: JSONDict) -> JSONDict:
|
|
251
|
+
project_id = ProjectId(require_string(args, "project_id"))
|
|
252
|
+
title = require_string(args, "title")
|
|
253
|
+
html = require_string(args, "html")
|
|
254
|
+
visual_kind = optional_string(args, "visual_kind") or "research_visual"
|
|
255
|
+
_reject_score_series_kind(visual_kind)
|
|
256
|
+
summary = optional_string(args, "summary")
|
|
257
|
+
source_run_ids = _optional_string_array(args, "source_run_ids")
|
|
258
|
+
metadata = _optional_metadata(args)
|
|
259
|
+
root_artifact_id = optional_string(args, "root_artifact_id")
|
|
260
|
+
preview_png = _optional_base64_bytes(args, "preview_png_base64")
|
|
261
|
+
with client_from_args(args) as client:
|
|
262
|
+
return client.visuals.create(
|
|
263
|
+
project_id,
|
|
264
|
+
title=title,
|
|
265
|
+
summary=summary,
|
|
266
|
+
html=html,
|
|
267
|
+
visual_kind=visual_kind,
|
|
268
|
+
source_run_ids=source_run_ids,
|
|
269
|
+
metadata=metadata,
|
|
270
|
+
root_artifact_id=(
|
|
271
|
+
ArtifactId(root_artifact_id) if root_artifact_id is not None else None
|
|
272
|
+
),
|
|
273
|
+
preview_png=preview_png,
|
|
274
|
+
).to_wire()
|
|
275
|
+
|
|
276
|
+
def update_visual(args: JSONDict) -> JSONDict:
|
|
277
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
278
|
+
visual_kind = optional_string(args, "visual_kind")
|
|
279
|
+
_reject_score_series_kind(visual_kind)
|
|
280
|
+
patch = VisualPatch(
|
|
281
|
+
title=optional_string(args, "title"),
|
|
282
|
+
summary=optional_string(args, "summary"),
|
|
283
|
+
visual_kind=visual_kind,
|
|
284
|
+
)
|
|
285
|
+
if patch.title is None and patch.summary is None and patch.visual_kind is None:
|
|
286
|
+
raise ValueError("update must change at least one of 'title', 'summary', 'visual_kind'")
|
|
287
|
+
with client_from_args(args) as client:
|
|
288
|
+
return client.visuals.update(visual_id, patch).to_wire()
|
|
289
|
+
|
|
290
|
+
def promote_visual(args: JSONDict) -> JSONDict:
|
|
291
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
292
|
+
promotion = VisualPromotion(slug=require_string(args, "slug"))
|
|
293
|
+
with client_from_args(args) as client:
|
|
294
|
+
return client.visuals.promote(visual_id, promotion).to_wire()
|
|
295
|
+
|
|
296
|
+
def unpublish_visual(args: JSONDict) -> JSONDict:
|
|
297
|
+
visual_id = ArtifactId(require_string(args, "visual_id"))
|
|
298
|
+
with client_from_args(args) as client:
|
|
299
|
+
return client.visuals.unpublish(visual_id).to_wire()
|
|
300
|
+
|
|
301
|
+
visual_id_schema = {
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "Stable hosted artifact identifier for one Visual version.",
|
|
304
|
+
}
|
|
305
|
+
chunk_schema = {
|
|
306
|
+
"offset": {
|
|
307
|
+
"type": "integer",
|
|
308
|
+
"minimum": 0,
|
|
309
|
+
"default": 0,
|
|
310
|
+
},
|
|
311
|
+
"max_bytes": {
|
|
312
|
+
"type": "integer",
|
|
313
|
+
"minimum": 1,
|
|
314
|
+
"maximum": _MCP_BINARY_CHUNK_BYTES_MAX,
|
|
315
|
+
"default": _MCP_BINARY_CHUNK_BYTES_DEFAULT,
|
|
316
|
+
},
|
|
317
|
+
}
|
|
318
|
+
return [
|
|
319
|
+
ToolDefinition(
|
|
320
|
+
name="research_list_visuals",
|
|
321
|
+
description="List one cursor-paginated page of project Visuals.",
|
|
322
|
+
input_schema=tool_schema(
|
|
323
|
+
{
|
|
324
|
+
"project_id": {"type": "string"},
|
|
325
|
+
"visual_kind": {"type": "string"},
|
|
326
|
+
"visibility": {
|
|
327
|
+
"type": "string",
|
|
328
|
+
"enum": [visibility.value for visibility in VisualVisibility],
|
|
329
|
+
},
|
|
330
|
+
"factory_id": {"type": "string"},
|
|
331
|
+
"effort_id": {"type": "string"},
|
|
332
|
+
"include_deleted": {"type": "boolean"},
|
|
333
|
+
"cursor": {"type": "string"},
|
|
334
|
+
"limit": {"type": "integer", "minimum": 1, "maximum": 250},
|
|
335
|
+
},
|
|
336
|
+
required=["project_id"],
|
|
337
|
+
),
|
|
338
|
+
handler=list_visuals,
|
|
339
|
+
required_scopes=READ_SCOPES,
|
|
340
|
+
),
|
|
341
|
+
ToolDefinition(
|
|
342
|
+
name="research_get_visual",
|
|
343
|
+
description="Retrieve authenticated metadata for one Visual version.",
|
|
344
|
+
input_schema=tool_schema(
|
|
345
|
+
{"visual_id": visual_id_schema},
|
|
346
|
+
required=["visual_id"],
|
|
347
|
+
),
|
|
348
|
+
handler=get_visual,
|
|
349
|
+
required_scopes=READ_SCOPES,
|
|
350
|
+
),
|
|
351
|
+
ToolDefinition(
|
|
352
|
+
name="research_get_visual_content",
|
|
353
|
+
description="Read one bounded base64 chunk of authenticated Visual HTML.",
|
|
354
|
+
input_schema=tool_schema(
|
|
355
|
+
{"visual_id": visual_id_schema, **chunk_schema},
|
|
356
|
+
required=["visual_id"],
|
|
357
|
+
),
|
|
358
|
+
handler=get_visual_content,
|
|
359
|
+
required_scopes=READ_SCOPES,
|
|
360
|
+
),
|
|
361
|
+
ToolDefinition(
|
|
362
|
+
name="research_get_visual_preview",
|
|
363
|
+
description="Read one bounded base64 chunk of an authenticated Visual PNG preview.",
|
|
364
|
+
input_schema=tool_schema(
|
|
365
|
+
{"visual_id": visual_id_schema, **chunk_schema},
|
|
366
|
+
required=["visual_id"],
|
|
367
|
+
),
|
|
368
|
+
handler=get_visual_preview,
|
|
369
|
+
required_scopes=READ_SCOPES,
|
|
370
|
+
),
|
|
371
|
+
ToolDefinition(
|
|
372
|
+
name="research_create_visual",
|
|
373
|
+
description=(
|
|
374
|
+
"Publish a project-owned Visual from self-contained HTML. "
|
|
375
|
+
f"{_SCORE_SERIES_GUARD_NOTE}"
|
|
376
|
+
),
|
|
377
|
+
input_schema=tool_schema(
|
|
378
|
+
{
|
|
379
|
+
"project_id": {
|
|
380
|
+
"type": "string",
|
|
381
|
+
"description": "Research project ID that owns the Visual.",
|
|
382
|
+
},
|
|
383
|
+
"title": {
|
|
384
|
+
"type": "string",
|
|
385
|
+
"minLength": 1,
|
|
386
|
+
"description": "Human-readable Visual title.",
|
|
387
|
+
},
|
|
388
|
+
"summary": {
|
|
389
|
+
"type": "string",
|
|
390
|
+
"description": "Optional short summary.",
|
|
391
|
+
},
|
|
392
|
+
"html": {
|
|
393
|
+
"type": "string",
|
|
394
|
+
"minLength": 1,
|
|
395
|
+
"description": "Complete self-contained HTML document (UTF-8).",
|
|
396
|
+
},
|
|
397
|
+
"visual_kind": {
|
|
398
|
+
"type": "string",
|
|
399
|
+
"default": "research_visual",
|
|
400
|
+
"description": (
|
|
401
|
+
"Visual kind label. Score-series kinds are refused; "
|
|
402
|
+
"score series are server-authoritative."
|
|
403
|
+
),
|
|
404
|
+
},
|
|
405
|
+
"source_run_ids": {
|
|
406
|
+
"type": "array",
|
|
407
|
+
"items": {"type": "string"},
|
|
408
|
+
"description": "Run IDs whose evidence backs this Visual.",
|
|
409
|
+
},
|
|
410
|
+
"metadata": {
|
|
411
|
+
"type": "object",
|
|
412
|
+
"description": "Optional JSON metadata for the Visual.",
|
|
413
|
+
},
|
|
414
|
+
"root_artifact_id": {
|
|
415
|
+
"type": "string",
|
|
416
|
+
"description": (
|
|
417
|
+
"Existing root artifact ID to publish a new version under."
|
|
418
|
+
),
|
|
419
|
+
},
|
|
420
|
+
"preview_png_base64": {
|
|
421
|
+
"type": "string",
|
|
422
|
+
"description": "Optional base64-encoded PNG preview image.",
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
required=["project_id", "title", "html"],
|
|
426
|
+
),
|
|
427
|
+
handler=create_visual,
|
|
428
|
+
required_scopes=WRITE_SCOPES,
|
|
429
|
+
),
|
|
430
|
+
ToolDefinition(
|
|
431
|
+
name="research_update_visual",
|
|
432
|
+
description=(
|
|
433
|
+
"Update the mutable metadata (title, summary, visual_kind) of one "
|
|
434
|
+
f"Visual. {_SCORE_SERIES_GUARD_NOTE}"
|
|
435
|
+
),
|
|
436
|
+
input_schema=tool_schema(
|
|
437
|
+
{
|
|
438
|
+
"visual_id": visual_id_schema,
|
|
439
|
+
"title": {"type": "string", "minLength": 1},
|
|
440
|
+
"summary": {"type": "string"},
|
|
441
|
+
"visual_kind": {
|
|
442
|
+
"type": "string",
|
|
443
|
+
"description": (
|
|
444
|
+
"New visual kind label. Score-series kinds are refused; "
|
|
445
|
+
"score series are server-authoritative."
|
|
446
|
+
),
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
required=["visual_id"],
|
|
450
|
+
),
|
|
451
|
+
handler=update_visual,
|
|
452
|
+
required_scopes=WRITE_SCOPES,
|
|
453
|
+
),
|
|
454
|
+
ToolDefinition(
|
|
455
|
+
name="research_promote_visual",
|
|
456
|
+
description=(
|
|
457
|
+
"Promote a Visual to a stable public slug through the backend's "
|
|
458
|
+
"ADMIN/OWNER authority."
|
|
459
|
+
),
|
|
460
|
+
input_schema=tool_schema(
|
|
461
|
+
{
|
|
462
|
+
"visual_id": visual_id_schema,
|
|
463
|
+
"slug": {
|
|
464
|
+
"type": "string",
|
|
465
|
+
"minLength": 1,
|
|
466
|
+
"description": "Requested stable public slug.",
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
required=["visual_id", "slug"],
|
|
470
|
+
),
|
|
471
|
+
handler=promote_visual,
|
|
472
|
+
required_scopes=WRITE_SCOPES,
|
|
473
|
+
),
|
|
474
|
+
ToolDefinition(
|
|
475
|
+
name="research_unpublish_visual",
|
|
476
|
+
description="Remove a Visual from its published public surface.",
|
|
477
|
+
input_schema=tool_schema(
|
|
478
|
+
{"visual_id": visual_id_schema},
|
|
479
|
+
required=["visual_id"],
|
|
480
|
+
),
|
|
481
|
+
handler=unpublish_visual,
|
|
482
|
+
required_scopes=WRITE_SCOPES,
|
|
483
|
+
),
|
|
484
|
+
]
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
__all__ = [
|
|
488
|
+
"VISUAL_SCORE_SERIES_ERROR_CODE",
|
|
489
|
+
"VisualScoreSeriesServerAuthoritativeError",
|
|
490
|
+
"build_visual_tools",
|
|
491
|
+
]
|
{synth_ai-0.18.2.dev606 → synth_ai-0.18.2.dev607}/synth_ai/mcp/research/tools/workspace_inputs.py
RENAMED
|
@@ -105,6 +105,19 @@ def build_workspace_input_tools(
|
|
|
105
105
|
request,
|
|
106
106
|
).to_wire()
|
|
107
107
|
|
|
108
|
+
def confirm_workspace_push(args: JSONDict) -> JSONDict:
|
|
109
|
+
project_id = ProjectId(require_string(args, "project_id"))
|
|
110
|
+
commit_sha = require_string(args, "commit_sha")
|
|
111
|
+
archive_key = require_string(args, "archive_key")
|
|
112
|
+
run_id = require_string(args, "run_id")
|
|
113
|
+
with client_from_args(args) as client:
|
|
114
|
+
return client.projects.workspace.confirm_push(
|
|
115
|
+
project_id,
|
|
116
|
+
commit_sha=commit_sha,
|
|
117
|
+
archive_key=archive_key,
|
|
118
|
+
run_id=run_id,
|
|
119
|
+
).to_wire()
|
|
120
|
+
|
|
108
121
|
return [
|
|
109
122
|
ToolDefinition(
|
|
110
123
|
name="research_attach_source_repo",
|
|
@@ -193,6 +206,45 @@ def build_workspace_input_tools(
|
|
|
193
206
|
handler=upload_workspace_files,
|
|
194
207
|
required_scopes=WRITE_SCOPES,
|
|
195
208
|
),
|
|
209
|
+
ToolDefinition(
|
|
210
|
+
name="research_confirm_workspace_push",
|
|
211
|
+
description=(
|
|
212
|
+
"Confirm an already-pushed workspace commit through project "
|
|
213
|
+
"authority and return the typed WorkspacePushConfirmationReceipt "
|
|
214
|
+
"-- the done signal for coding agents driving workspace ingress "
|
|
215
|
+
"over MCP. If the project is bound to an open Sync session, the "
|
|
216
|
+
"backend also auto-records a kit-association receipt server-side."
|
|
217
|
+
),
|
|
218
|
+
input_schema=tool_schema(
|
|
219
|
+
{
|
|
220
|
+
"project_id": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"description": "Research project ID.",
|
|
223
|
+
},
|
|
224
|
+
"commit_sha": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"pattern": "^[0-9a-f]{40}$",
|
|
227
|
+
"description": (
|
|
228
|
+
"Exact 40-hex lowercase commit SHA pushed to the "
|
|
229
|
+
"internal workspace git server."
|
|
230
|
+
),
|
|
231
|
+
},
|
|
232
|
+
"archive_key": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"minLength": 1,
|
|
235
|
+
"description": "Immutable workspace archive object key.",
|
|
236
|
+
},
|
|
237
|
+
"run_id": {
|
|
238
|
+
"type": "string",
|
|
239
|
+
"minLength": 1,
|
|
240
|
+
"description": "Run ID the pushed workspace belongs to.",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
required=["project_id", "commit_sha", "archive_key", "run_id"],
|
|
244
|
+
),
|
|
245
|
+
handler=confirm_workspace_push,
|
|
246
|
+
required_scopes=WRITE_SCOPES,
|
|
247
|
+
),
|
|
196
248
|
]
|
|
197
249
|
|
|
198
250
|
|