synth-ai 0.20.2.dev643__tar.gz → 0.21.0.dev647__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.20.2.dev643/synth_ai.egg-info → synth_ai-0.21.0.dev647}/PKG-INFO +25 -2
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/README.md +24 -1
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/pyproject.toml +1 -1
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_projects.py +2 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/README.md +4 -2
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/server.py +3 -2
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/index.py +187 -13
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/workspace_inputs.py +13 -1
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/AGENT_SETUP_PROMPT.md +16 -12
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/README.md +91 -23
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/__init__.py +64 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/catalog.py +52 -1
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/client.py +16 -6
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/errors.py +14 -0
- synth_ai-0.21.0.dev647/synth_ai/sdk/index/public_search.py +873 -0
- synth_ai-0.21.0.dev647/synth_ai/sdk/index/wallet_search.py +174 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/workspaces.py +6 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647/synth_ai.egg-info}/PKG-INFO +25 -2
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/SOURCES.txt +2 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/LICENSE +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/MANIFEST.in +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/index-v1.json +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/messaging-v1.json +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/research-v1.json +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/setup.cfg +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/setup.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/__main__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/AGENTS.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/__main__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/index.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/main.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_image_releases.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/client.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/auth/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/auth/credentials.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/json_value.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/pagination.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/errors.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/async_transport.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/request.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/retry.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/streaming.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/transport.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/research/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/env.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/log_filter.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/paths.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/urls.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/__main__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/objective_tools.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/registry.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/request_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/approvals.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/artifacts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/datasets.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/exports.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/factories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/factory_results.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/files.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/image_releases.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/integrations.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/intern_program.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/local_files.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/logs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/outputs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/policy_schemas.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/progress.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/project_data.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/projects.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/prs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/readiness.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/repos.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/research_intern.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/resources.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/runs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/trained_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/usage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/visuals.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/pools.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/py.typed +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/agent_policy.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/answer.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/artifacts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/contracts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/contributions.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/lifecycle.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/package.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/public.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/research_intake.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/retry.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/search.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/submission.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/timeouts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/transfer.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/usage_accounting.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/client.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/contracts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/client.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/contracts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/pagination.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/crypto.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/env.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/urls.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/account.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced_factories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced_swarms.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/artifacts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/auth.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/client.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/api.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/contracts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/operations.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/packaging.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_activity_wire.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_environment_wire.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_transcript_wire.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_wire.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/activity.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/activity_items.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/actor_images.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/billing.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/canonical_usage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/checkpoints.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/cloud_deployment_claims.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/cloud_deployments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/common.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/dataset_revisions.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/deliveries.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/dev_environment_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/economics.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/environment_manifest.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_lenses.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_operations.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_role_receipts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/failure.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/image_releases.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_blockers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_grants.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_program.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_resources.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_usage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/limit_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/local_execution_profile.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/operator_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_data.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_runtime.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_workspace.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_workspace_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/projects.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/promotions.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/research_intern.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/resource_settlement.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_authority.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_control.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_diagnostics.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_events.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_execution.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_launch.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_observability.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_state.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_timeline.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_image.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_intent.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_stream.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_stream_snapshot.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/scientific_integrity.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_actor_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_actor_policy_data.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_harnesses.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_kinds.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_branching.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_credential_providers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_environment_kinds.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_evidence_obligations.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_funding_sources.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_horizons.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_host_kinds.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_inference_providers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_network_topology.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_providers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_resource_kinds.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_roles.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_run_policy.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runbooks.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runnable_project.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runtime_kinds.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_tool_providers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_work_modes.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/status.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/swarm_rollouts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/swarms.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/tag.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/traces.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/transcript.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/types.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/usage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/visuals.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/wire_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/wire_models_README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/work_products.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/economics.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/efforts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/errors.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/events.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/experiments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/facade.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/factories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/factory_storage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/image_releases.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/intern_blockers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/intern_program.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/knowledge.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/operations.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_data.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_deliveries.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_workspaces.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/projects.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/public.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/readouts.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/research_intern.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/secrets.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/README.md +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_base.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_client_helpers.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_run_authority_mixin.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/approvals.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/billing.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/client.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/cloud_deployments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/config.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/cost.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/datasets.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/dev_environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/environments.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/exports.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/factories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/factory_evidence.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/files.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/github.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/image_releases.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/images.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/logs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/outputs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/progress.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/project.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/projects.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/prs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/readiness.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/repositories.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/runs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/secrets.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/setup.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/tag.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/trained_models.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/transport.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/usage.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/work_products.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/workspace_inputs.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/surface_parity.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/swarms.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/traces.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/__init__.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/http.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/pagination.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/version.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/visuals.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/wiki.py +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/dependency_links.txt +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/entry_points.txt +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/requires.txt +0 -0
- {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: synth-ai
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.21.0.dev647
|
|
4
4
|
Summary: Python SDK and CLI for Synth Index, Managed Research, and Research Factory
|
|
5
5
|
Author-email: Synth AI <josh@usesynth.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -29,7 +29,7 @@ Dynamic: license-file
|
|
|
29
29
|
|
|
30
30
|
# Synth AI SDK
|
|
31
31
|
|
|
32
|
-
<!-- CI release pins: PyPI-0.
|
|
32
|
+
<!-- CI release pins: PyPI-0.21.0-orange synth-ai==0.21.0 -->
|
|
33
33
|
|
|
34
34
|
[](https://pypi.org/project/synth-ai/)
|
|
35
35
|
[](https://pypi.org/project/synth-ai/)
|
|
@@ -202,6 +202,29 @@ synth-ai --help
|
|
|
202
202
|
synth-ai research --help
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
## Synth Index (alpha v0.1)
|
|
206
|
+
|
|
207
|
+
Synth Index alpha v0.1 offers authenticated, paid FAST and DEEP Search over
|
|
208
|
+
reviewed, published research. DEEP is in beta. Install `synth-ai>=0.20.2`:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
uv add "synth-ai>=0.20.2"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
- **Python:** `SynthClient().index.search(query=..., mode="fast" | "deep", billing=...)`.
|
|
215
|
+
An example is under [Public Surface](#public-surface). The
|
|
216
|
+
[Index SDK guide](synth_ai/sdk/index/README.md) covers DEEP's durable Search
|
|
217
|
+
ID, reconnect and cancel.
|
|
218
|
+
- **MCP:** `synth-ai-index-mcp` is an Index-only stdio server and is read-only
|
|
219
|
+
by default. Search tools are advertised only when `SYNTH_API_KEY` is set.
|
|
220
|
+
Setup is in the [Index SDK guide](synth_ai/sdk/index/README.md#external-agents-over-stdio-mcp).
|
|
221
|
+
- Every Search needs an API key, an authorized organization and funding.
|
|
222
|
+
|
|
223
|
+
Not in alpha v0.1: `/index/answer`, downloading the files behind
|
|
224
|
+
a citation, citations that point to an exact passage, a latency guarantee, and
|
|
225
|
+
free, anonymous or zero-data-retention Search. Contributing research to the
|
|
226
|
+
Index is planned for Index v0.2.
|
|
227
|
+
|
|
205
228
|
## Public Surface
|
|
206
229
|
|
|
207
230
|
Use `SynthClient` as the front door:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Synth AI SDK
|
|
2
2
|
|
|
3
|
-
<!-- CI release pins: PyPI-0.
|
|
3
|
+
<!-- CI release pins: PyPI-0.21.0-orange synth-ai==0.21.0 -->
|
|
4
4
|
|
|
5
5
|
[](https://pypi.org/project/synth-ai/)
|
|
6
6
|
[](https://pypi.org/project/synth-ai/)
|
|
@@ -173,6 +173,29 @@ synth-ai --help
|
|
|
173
173
|
synth-ai research --help
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
+
## Synth Index (alpha v0.1)
|
|
177
|
+
|
|
178
|
+
Synth Index alpha v0.1 offers authenticated, paid FAST and DEEP Search over
|
|
179
|
+
reviewed, published research. DEEP is in beta. Install `synth-ai>=0.20.2`:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
uv add "synth-ai>=0.20.2"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
- **Python:** `SynthClient().index.search(query=..., mode="fast" | "deep", billing=...)`.
|
|
186
|
+
An example is under [Public Surface](#public-surface). The
|
|
187
|
+
[Index SDK guide](synth_ai/sdk/index/README.md) covers DEEP's durable Search
|
|
188
|
+
ID, reconnect and cancel.
|
|
189
|
+
- **MCP:** `synth-ai-index-mcp` is an Index-only stdio server and is read-only
|
|
190
|
+
by default. Search tools are advertised only when `SYNTH_API_KEY` is set.
|
|
191
|
+
Setup is in the [Index SDK guide](synth_ai/sdk/index/README.md#external-agents-over-stdio-mcp).
|
|
192
|
+
- Every Search needs an API key, an authorized organization and funding.
|
|
193
|
+
|
|
194
|
+
Not in alpha v0.1: `/index/answer`, downloading the files behind
|
|
195
|
+
a citation, citations that point to an exact passage, a latency guarantee, and
|
|
196
|
+
free, anonymous or zero-data-retention Search. Contributing research to the
|
|
197
|
+
Index is planned for Index v0.2.
|
|
198
|
+
|
|
176
199
|
## Public Surface
|
|
177
200
|
|
|
178
201
|
Use `SynthClient` as the front door:
|
|
@@ -368,6 +368,7 @@ def workspace_upload(
|
|
|
368
368
|
ProjectId,
|
|
369
369
|
WorkspaceFileEncoding,
|
|
370
370
|
WorkspaceFileKind,
|
|
371
|
+
WorkspaceFileMode,
|
|
371
372
|
WorkspaceFilesBatchUploadRequest,
|
|
372
373
|
WorkspaceFileUpload,
|
|
373
374
|
)
|
|
@@ -390,6 +391,7 @@ def workspace_upload(
|
|
|
390
391
|
content_type=content_type,
|
|
391
392
|
encoding=WorkspaceFileEncoding.BASE64,
|
|
392
393
|
kind=WorkspaceFileKind.FILE,
|
|
394
|
+
mode=WorkspaceFileMode.from_posix_mode(resolved_source.stat().st_mode),
|
|
393
395
|
)
|
|
394
396
|
)
|
|
395
397
|
|
|
@@ -49,8 +49,10 @@ becoming callable without a scope.
|
|
|
49
49
|
|
|
50
50
|
`synth-ai-index-mcp` is the Index-only stdio entrypoint. It requires an explicit
|
|
51
51
|
`SYNTH_BACKEND_URL`, advertises no unrelated Research tools, and defaults to
|
|
52
|
-
read-only. Without `SYNTH_API_KEY` it advertises public browse tools
|
|
53
|
-
|
|
52
|
+
read-only. Without `SYNTH_API_KEY` it advertises public browse tools and the
|
|
53
|
+
free public `index_search` (Index Search v0.2; price, limits and privacy
|
|
54
|
+
terms are read from backend capabilities at call time, never hardcoded);
|
|
55
|
+
`index_private_search` and the durable-search lifecycle tools require the key.
|
|
54
56
|
`SYNTH_INDEX_MCP_WRITE_ENABLED=true` separately enables Contribution draft,
|
|
55
57
|
upload, and submission tools. Tool discovery performs no backend request.
|
|
56
58
|
|
|
@@ -504,7 +504,8 @@ class ResearchMcpServer:
|
|
|
504
504
|
tool
|
|
505
505
|
for tool in build_index_tools(
|
|
506
506
|
self._index_client_factory,
|
|
507
|
-
|
|
507
|
+
# The public search route (v0.2) is free and needs no key.
|
|
508
|
+
include_search=True,
|
|
508
509
|
# /index/answer is not in the public launch.
|
|
509
510
|
include_answer=False,
|
|
510
511
|
include_lifecycle=self._default_api_key is not None,
|
|
@@ -2996,7 +2997,7 @@ def _stdio_server(*, index_only: bool = False) -> ResearchMcpServer:
|
|
|
2996
2997
|
_INDEX_ENVIRONMENT_HELP = """\
|
|
2997
2998
|
environment:
|
|
2998
2999
|
SYNTH_BACKEND_URL backend base URL (required when Index tools are enabled)
|
|
2999
|
-
SYNTH_API_KEY API key; enables
|
|
3000
|
+
SYNTH_API_KEY API key; enables private/durable Search tools (public search needs none)
|
|
3000
3001
|
SYNTH_INDEX_MCP_WRITE_ENABLED true|false; Contribution write tools (needs SYNTH_API_KEY)
|
|
3001
3002
|
"""
|
|
3002
3003
|
|
|
@@ -21,16 +21,36 @@ from synth_ai.mcp.research.registry import (
|
|
|
21
21
|
)
|
|
22
22
|
from synth_ai.mcp.research.tools.local_files import SelectedFileReader
|
|
23
23
|
from synth_ai.sdk.index.answer import AnswerSpec
|
|
24
|
-
from synth_ai.sdk.index.
|
|
24
|
+
from synth_ai.sdk.index.catalog import PublicSearchCapability
|
|
25
|
+
from synth_ai.sdk.index.client import STATUS_POLL_TIMEOUT_SECONDS, IndexAPI, PublicIndexAPI
|
|
25
26
|
from synth_ai.sdk.index.contracts import ContributionReference, Identifier, IndexContract
|
|
26
27
|
from synth_ai.sdk.index.contributions import ContributionDraft, ContributionUploadSpec
|
|
27
|
-
from synth_ai.sdk.index.
|
|
28
|
+
from synth_ai.sdk.index.public_search import (
|
|
29
|
+
DEFAULT_PUBLIC_SEARCH_WAIT_SECONDS,
|
|
30
|
+
PublicSearchDisabledError,
|
|
31
|
+
PublicSearchHandle,
|
|
32
|
+
PublicSearchResult,
|
|
33
|
+
public_search_copy,
|
|
34
|
+
)
|
|
35
|
+
from synth_ai.sdk.index.search import (
|
|
36
|
+
ContentsSpec,
|
|
37
|
+
SearchBillingConstraints,
|
|
38
|
+
SearchMode,
|
|
39
|
+
SearchResult,
|
|
40
|
+
SearchSpec,
|
|
41
|
+
)
|
|
28
42
|
from synth_ai.sdk.index.submission import ContributionSubmitSpec
|
|
43
|
+
from synth_ai.sdk.index.wallet_search import (
|
|
44
|
+
AccessFundingCache,
|
|
45
|
+
WalletSearchGrant,
|
|
46
|
+
wallet_search_grant,
|
|
47
|
+
)
|
|
29
48
|
|
|
30
|
-
IndexClientFactory = Callable[[], AbstractContextManager[IndexAPI]]
|
|
49
|
+
IndexClientFactory = Callable[[], AbstractContextManager[IndexAPI | PublicIndexAPI]]
|
|
31
50
|
|
|
32
51
|
INDEX_READ_TOOL_NAMES: tuple[str, ...] = (
|
|
33
52
|
"index_search",
|
|
53
|
+
"index_private_search",
|
|
34
54
|
"index_search_create",
|
|
35
55
|
"index_search_get",
|
|
36
56
|
"index_search_result",
|
|
@@ -60,12 +80,31 @@ _KEY = Field(min_length=1, max_length=128, pattern=r"^[a-zA-Z0-9_.-]+$")
|
|
|
60
80
|
|
|
61
81
|
|
|
62
82
|
class IndexSearchRequest(IndexContract):
|
|
83
|
+
"""Public (credential-optional) Index Search v0.2; price and limits come from capabilities."""
|
|
84
|
+
|
|
85
|
+
query: Annotated[str, Field(min_length=1, max_length=8192)]
|
|
86
|
+
mode: SearchMode = Field(
|
|
87
|
+
default=SearchMode.FAST,
|
|
88
|
+
description="fast answers synchronously; deep is admitted and polled to completion.",
|
|
89
|
+
)
|
|
90
|
+
max_results: Annotated[StrictInt, Field(ge=1, le=10)] | None = None
|
|
91
|
+
idempotency_key: str | None = Field(
|
|
92
|
+
default=None,
|
|
93
|
+
min_length=1,
|
|
94
|
+
max_length=128,
|
|
95
|
+
pattern=r"^[a-zA-Z0-9_.-]+$",
|
|
96
|
+
description="Optional stable key to replay the same intent after an uncertain response.",
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class IndexPrivateSearchRequest(IndexContract):
|
|
63
101
|
search: SearchSpec = Field(
|
|
64
102
|
description=(
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"at
|
|
103
|
+
"Authenticated, funded search intent (private scope, wallet). The price per "
|
|
104
|
+
"search comes from capabilities.private_search.price_cents_per_search; wallet "
|
|
105
|
+
"funding needs billing.allow_wallet=true and a billing.max_charge_cents ceiling "
|
|
106
|
+
"at or above it. DEEP needs a mode grant. Never infer funding consent from the "
|
|
107
|
+
"query."
|
|
69
108
|
)
|
|
70
109
|
)
|
|
71
110
|
idempotency_key: str = _KEY
|
|
@@ -123,29 +162,156 @@ def read_selected_files(root: str, files: Mapping[str, str]) -> dict[str, bytes]
|
|
|
123
162
|
return content
|
|
124
163
|
|
|
125
164
|
|
|
165
|
+
_PUBLIC_SEARCH_DESCRIPTION = (
|
|
166
|
+
"Search reviewed Synth Index Contributions (Index Search v0.2). Without an API key "
|
|
167
|
+
"this is the free public search; mode is fast (synchronous) or deep (admitted, then "
|
|
168
|
+
"polled to completion). Price, rate limits, retention and privacy terms are published "
|
|
169
|
+
"by the backend's capabilities and returned under `terms` with every result; this tool "
|
|
170
|
+
"never assumes a price. With an API key a call is a PAID search charged to your "
|
|
171
|
+
"organization's wallet, and it runs only if your organization has turned on wallet "
|
|
172
|
+
"payments for that mode; the result reports the `charge`. Otherwise it is refused "
|
|
173
|
+
"with index_wallet_consent_required, the steps to enable it, and no charge. A rate-limit error carries retry_after_seconds and the limit scope; "
|
|
174
|
+
"a 503 means the search failed closed and nothing was charged. `response` cites "
|
|
175
|
+
"contribution ids inline as [<contribution_id>]; `citations` lists the exact revisions "
|
|
176
|
+
"(contribution_id, revision_id) in first-appearance order; preserve them verbatim."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def public_search_tool_description(capability: PublicSearchCapability | None) -> str:
|
|
181
|
+
"""Tool text built from the backend's capabilities; nothing priced by hand."""
|
|
182
|
+
if capability is None:
|
|
183
|
+
return _PUBLIC_SEARCH_DESCRIPTION
|
|
184
|
+
copy = public_search_copy(capability)
|
|
185
|
+
return " ".join((*copy.lines, _PUBLIC_SEARCH_DESCRIPTION))
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _public_search_payload(result: PublicSearchResult) -> JSONDict:
|
|
189
|
+
return {
|
|
190
|
+
"search_id": result.search_id,
|
|
191
|
+
"mode": result.mode.value,
|
|
192
|
+
"status": result.status,
|
|
193
|
+
"response": result.response,
|
|
194
|
+
"partial_reason": result.partial_reason,
|
|
195
|
+
"citations": [
|
|
196
|
+
{"contribution_id": item.contribution_id, "revision_id": item.revision_id}
|
|
197
|
+
for item in result.citations
|
|
198
|
+
],
|
|
199
|
+
"customer_charge_cents": result.customer_charge_cents,
|
|
200
|
+
"monitor_release_id": result.monitor_release_id,
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _paid_search_payload(result: SearchResult, grant: WalletSearchGrant) -> JSONDict:
|
|
205
|
+
usage = result.usage
|
|
206
|
+
return {
|
|
207
|
+
"search_id": result.search_id,
|
|
208
|
+
"mode": result.effective_mode.value,
|
|
209
|
+
"status": result.status,
|
|
210
|
+
"response": result.response,
|
|
211
|
+
"partial_reason": (None if result.partial_reason is None else result.partial_reason.value),
|
|
212
|
+
"citations": [
|
|
213
|
+
{"contribution_id": item.contribution_id, "revision_id": item.revision_id}
|
|
214
|
+
for item in result.citations
|
|
215
|
+
],
|
|
216
|
+
"paid": True,
|
|
217
|
+
"customer_charge_cents": usage.amount_cents,
|
|
218
|
+
"charge": {
|
|
219
|
+
"amount_cents": usage.amount_cents,
|
|
220
|
+
"wallet_debit_cents": usage.wallet_debit_cents,
|
|
221
|
+
"funding_source": usage.funding_source,
|
|
222
|
+
"receipt_id": usage.receipt_id,
|
|
223
|
+
"max_charge_cents": grant.max_charge_cents,
|
|
224
|
+
},
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
126
228
|
def build_index_tools(
|
|
127
229
|
client_factory: IndexClientFactory,
|
|
128
230
|
*,
|
|
129
231
|
include_search: bool = True,
|
|
130
232
|
include_answer: bool = False,
|
|
131
233
|
include_lifecycle: bool = True,
|
|
234
|
+
public_search_capability: PublicSearchCapability | None = None,
|
|
132
235
|
) -> list[ToolDefinition]:
|
|
133
236
|
"""Build Index tools without discovering credentials or widening scope.
|
|
134
237
|
|
|
135
|
-
|
|
136
|
-
|
|
238
|
+
``index_search`` without a key is the free public route. With a key it is
|
|
239
|
+
the paid search, run only when the org has consented to wallet funding
|
|
240
|
+
for the mode (a cached access-funding read), with an explicit per-call
|
|
241
|
+
ceiling; otherwise it raises ``WalletConsentRequiredError`` before any paid
|
|
242
|
+
request is sent (owner decision 2026-09-28). Private and
|
|
243
|
+
lifecycle search require an explicit stable key because they may consume
|
|
244
|
+
bounded, funded service resources. Backend authorization, execution and usage
|
|
137
245
|
remain authoritative; no local search or model fallback is installed.
|
|
246
|
+
``public_search_capability`` (when the caller already holds it) puts the
|
|
247
|
+
backend's price/limits/privacy copy into the tool description; discovery
|
|
248
|
+
itself never makes a request.
|
|
138
249
|
"""
|
|
139
250
|
|
|
251
|
+
funding_cache = AccessFundingCache()
|
|
252
|
+
|
|
253
|
+
def keyed_search(client: IndexAPI, request: IndexSearchRequest) -> JSONDict:
|
|
254
|
+
account = funding_cache.get(client.account.access_funding)
|
|
255
|
+
grant = wallet_search_grant(account, request.mode)
|
|
256
|
+
try:
|
|
257
|
+
result = client.search(
|
|
258
|
+
query=request.query,
|
|
259
|
+
mode=request.mode,
|
|
260
|
+
max_results=request.max_results,
|
|
261
|
+
billing=SearchBillingConstraints(
|
|
262
|
+
allow_wallet=True, max_charge_cents=grant.max_charge_cents
|
|
263
|
+
),
|
|
264
|
+
idempotency_key=request.idempotency_key,
|
|
265
|
+
)
|
|
266
|
+
except Exception:
|
|
267
|
+
# Consent or caps may have changed server-side: read them again next call.
|
|
268
|
+
funding_cache.invalidate()
|
|
269
|
+
raise
|
|
270
|
+
return _paid_search_payload(result, grant)
|
|
271
|
+
|
|
140
272
|
def search(arguments: JSONDict) -> JSONDict:
|
|
141
273
|
request = IndexSearchRequest.model_validate(arguments)
|
|
142
274
|
with client_factory() as client:
|
|
275
|
+
if isinstance(client, IndexAPI):
|
|
276
|
+
# The public route is anonymous-only (backend 409). A keyed call is
|
|
277
|
+
# paid, and only runs when the org has opted in to wallet funding.
|
|
278
|
+
return keyed_search(client, request)
|
|
279
|
+
capability = client.public_search_capability()
|
|
280
|
+
if capability is None or not capability.enabled:
|
|
281
|
+
raise PublicSearchDisabledError(
|
|
282
|
+
"Public Index search is not enabled on this backend", status=404
|
|
283
|
+
)
|
|
284
|
+
if request.mode not in capability.modes:
|
|
285
|
+
raise PublicSearchDisabledError(
|
|
286
|
+
f"Public Index search does not offer mode {request.mode.value!r}",
|
|
287
|
+
status=404,
|
|
288
|
+
)
|
|
289
|
+
outcome = client.public_search(
|
|
290
|
+
request.query,
|
|
291
|
+
mode=request.mode,
|
|
292
|
+
max_results=request.max_results,
|
|
293
|
+
idempotency_key=request.idempotency_key,
|
|
294
|
+
wait=True,
|
|
295
|
+
timeout_s=DEFAULT_PUBLIC_SEARCH_WAIT_SECONDS,
|
|
296
|
+
)
|
|
297
|
+
if isinstance(outcome, PublicSearchHandle): # pragma: no cover - wait=True
|
|
298
|
+
raise RuntimeError("public search returned a handle while waiting")
|
|
299
|
+
return {
|
|
300
|
+
**_public_search_payload(outcome),
|
|
301
|
+
"terms": public_search_copy(capability).as_dict(),
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
def private_search(arguments: JSONDict) -> JSONDict:
|
|
305
|
+
request = IndexPrivateSearchRequest.model_validate(arguments)
|
|
306
|
+
with client_factory() as client:
|
|
307
|
+
if not isinstance(client, IndexAPI):
|
|
308
|
+
raise ValueError("index_private_search requires an API key")
|
|
143
309
|
return client.search(
|
|
144
310
|
request.search, idempotency_key=request.idempotency_key
|
|
145
311
|
).model_dump(mode="json")
|
|
146
312
|
|
|
147
313
|
def search_create(arguments: JSONDict) -> JSONDict:
|
|
148
|
-
request =
|
|
314
|
+
request = IndexPrivateSearchRequest.model_validate(arguments)
|
|
149
315
|
with client_factory() as client:
|
|
150
316
|
return client.searches.create(
|
|
151
317
|
request.search, idempotency_key=request.idempotency_key
|
|
@@ -235,15 +401,22 @@ def build_index_tools(
|
|
|
235
401
|
tools = [
|
|
236
402
|
ToolDefinition(
|
|
237
403
|
name="index_search",
|
|
238
|
-
description=
|
|
404
|
+
description=public_search_tool_description(public_search_capability),
|
|
239
405
|
input_schema=IndexSearchRequest.model_json_schema(),
|
|
240
406
|
handler=search,
|
|
241
407
|
required_scopes=read,
|
|
242
408
|
),
|
|
409
|
+
ToolDefinition(
|
|
410
|
+
name="index_private_search",
|
|
411
|
+
description="Search with an authenticated funding identity (private scope or wallet-funded). The per-search price is capabilities.private_search.price_cents_per_search; wallet funding requires search.billing.allow_wallet=true and a max_charge_cents ceiling at or above it. Do not infer consent. Reuse the same idempotency key for uncertain retries (never a new key for the same intent); if an error carries search_id, reconnect with index_search_get. Preserve exact revision citations.",
|
|
412
|
+
input_schema=IndexPrivateSearchRequest.model_json_schema(),
|
|
413
|
+
handler=private_search,
|
|
414
|
+
required_scopes=read,
|
|
415
|
+
),
|
|
243
416
|
ToolDefinition(
|
|
244
417
|
name="index_search_create",
|
|
245
|
-
description="Create one durable FAST or DEEP Search.
|
|
246
|
-
input_schema=
|
|
418
|
+
description="Create one durable FAST or DEEP authenticated Search. Wallet-funded searches need explicit consent and a max_charge_cents ceiling at or above the price published in capabilities; DEEP needs a mode grant. Return its Search ID and state immediately. Always send a stable idempotency key: after an uncertain response or a transient 503, retry with the SAME key (the SDK retries automatically); if an error carries search_id, the Search was admitted, so read it with index_search_get instead of creating another.",
|
|
419
|
+
input_schema=IndexPrivateSearchRequest.model_json_schema(),
|
|
247
420
|
handler=search_create,
|
|
248
421
|
required_scopes=read,
|
|
249
422
|
),
|
|
@@ -326,6 +499,7 @@ def build_index_tools(
|
|
|
326
499
|
),
|
|
327
500
|
]
|
|
328
501
|
lifecycle_names = {
|
|
502
|
+
"index_private_search",
|
|
329
503
|
"index_search_create",
|
|
330
504
|
"index_search_get",
|
|
331
505
|
"index_search_result",
|
{synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/workspace_inputs.py
RENAMED
|
@@ -18,6 +18,7 @@ from synth_ai.sdk.research.contracts.workspaces import (
|
|
|
18
18
|
WORKSPACE_BATCH_UPLOAD_FILE_LIMIT,
|
|
19
19
|
WorkspaceFileEncoding,
|
|
20
20
|
WorkspaceFileKind,
|
|
21
|
+
WorkspaceFileMode,
|
|
21
22
|
WorkspaceFilesBatchUploadRequest,
|
|
22
23
|
WorkspaceFileUpload,
|
|
23
24
|
WorkspaceMetadata,
|
|
@@ -26,7 +27,9 @@ from synth_ai.sdk.research.contracts.workspaces import (
|
|
|
26
27
|
|
|
27
28
|
CoreClientFactory = Callable[[JSONDict], ResearchClient]
|
|
28
29
|
|
|
29
|
-
_FILE_FIELDS = frozenset(
|
|
30
|
+
_FILE_FIELDS = frozenset(
|
|
31
|
+
{"path", "content", "content_type", "encoding", "kind", "mode", "metadata"}
|
|
32
|
+
)
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
def _file_upload(value: object, *, index: int) -> WorkspaceFileUpload:
|
|
@@ -52,6 +55,9 @@ def _file_upload(value: object, *, index: int) -> WorkspaceFileUpload:
|
|
|
52
55
|
kind = value.get("kind")
|
|
53
56
|
if kind is not None and not isinstance(kind, str):
|
|
54
57
|
raise ValueError(f"files[{index}].kind must be a string")
|
|
58
|
+
mode = value.get("mode")
|
|
59
|
+
if mode is not None and not isinstance(mode, str):
|
|
60
|
+
raise ValueError(f"files[{index}].mode must be a string")
|
|
55
61
|
metadata = value.get("metadata", {})
|
|
56
62
|
if not isinstance(metadata, dict):
|
|
57
63
|
raise ValueError(f"files[{index}].metadata must be an object")
|
|
@@ -61,6 +67,7 @@ def _file_upload(value: object, *, index: int) -> WorkspaceFileUpload:
|
|
|
61
67
|
content_type=content_type,
|
|
62
68
|
encoding=WorkspaceFileEncoding(encoding) if encoding is not None else None,
|
|
63
69
|
kind=WorkspaceFileKind(kind) if kind is not None else None,
|
|
70
|
+
mode=WorkspaceFileMode(mode) if mode is not None else None,
|
|
64
71
|
metadata=WorkspaceMetadata(metadata),
|
|
65
72
|
)
|
|
66
73
|
|
|
@@ -194,6 +201,11 @@ def build_workspace_input_tools(
|
|
|
194
201
|
"type": "string",
|
|
195
202
|
"enum": [item.value for item in WorkspaceFileKind],
|
|
196
203
|
},
|
|
204
|
+
"mode": {
|
|
205
|
+
"type": "string",
|
|
206
|
+
"enum": [item.value for item in WorkspaceFileMode],
|
|
207
|
+
"description": "Git blob mode; 100755 commits the file executable.",
|
|
208
|
+
},
|
|
197
209
|
"metadata": {"type": "object"},
|
|
198
210
|
},
|
|
199
211
|
"required": ["path", "content"],
|
|
@@ -20,19 +20,23 @@ product UI or to run a paid search during setup.
|
|
|
20
20
|
> without my explicit authorization for that operation. If the backend URL or
|
|
21
21
|
> authorized key source is missing, report exactly what is missing and stop.
|
|
22
22
|
>
|
|
23
|
-
> Verify that the server starts and advertises `index_search`
|
|
24
|
-
>
|
|
25
|
-
>
|
|
26
|
-
> tools. Tool discovery must not execute a search or
|
|
23
|
+
> Verify that the server starts and advertises `index_search` (the public
|
|
24
|
+
> route, available with or without a key) and, with the key, `index_private_search`
|
|
25
|
+
> and `index_search_create`. Without a key it must not advertise private or
|
|
26
|
+
> durable-search lifecycle tools. Tool discovery must not execute a search or
|
|
27
|
+
> incur a charge.
|
|
27
28
|
>
|
|
28
|
-
>
|
|
29
|
-
>
|
|
30
|
-
>
|
|
31
|
-
>
|
|
32
|
-
>
|
|
33
|
-
>
|
|
34
|
-
>
|
|
35
|
-
>
|
|
29
|
+
> Public `index_search` (fast or deep) is priced, rate-limited and governed by the
|
|
30
|
+
> privacy terms the backend publishes in capabilities; the tool returns them under
|
|
31
|
+
> `terms` with every result. Never quote a price you did not read from there.
|
|
32
|
+
> For a private or wallet-funded search I explicitly request, first state the
|
|
33
|
+
> aggregate maximum charge and use a fresh idempotency key. Wallet funding
|
|
34
|
+
> requires `search.billing.allow_wallet=true` and a `max_charge_cents` ceiling
|
|
35
|
+
> at or above `capabilities.private_search.price_cents_per_search`; do not infer
|
|
36
|
+
> my wallet consent from a query. DEEP also needs a mode grant. If a response is
|
|
37
|
+
> uncertain, retry the same logical request with the **same** idempotency key,
|
|
38
|
+
> not a new charge attempt. Preserve returned Contribution and revision IDs when
|
|
39
|
+
> reporting evidence.
|
|
36
40
|
> Do not enable Contribution writes unless I separately ask for them.
|
|
37
41
|
>
|
|
38
42
|
> Report the package version, backend environment name (not a secret), MCP
|