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.
Files changed (306) hide show
  1. {synth_ai-0.20.2.dev643/synth_ai.egg-info → synth_ai-0.21.0.dev647}/PKG-INFO +25 -2
  2. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/README.md +24 -1
  3. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/pyproject.toml +1 -1
  4. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_projects.py +2 -0
  5. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/README.md +4 -2
  6. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/server.py +3 -2
  7. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/index.py +187 -13
  8. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/workspace_inputs.py +13 -1
  9. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/AGENT_SETUP_PROMPT.md +16 -12
  10. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/README.md +91 -23
  11. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/__init__.py +64 -0
  12. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/catalog.py +52 -1
  13. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/client.py +16 -6
  14. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/errors.py +14 -0
  15. synth_ai-0.21.0.dev647/synth_ai/sdk/index/public_search.py +873 -0
  16. synth_ai-0.21.0.dev647/synth_ai/sdk/index/wallet_search.py +174 -0
  17. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/workspaces.py +6 -0
  18. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647/synth_ai.egg-info}/PKG-INFO +25 -2
  19. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/SOURCES.txt +2 -0
  20. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/LICENSE +0 -0
  21. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/MANIFEST.in +0 -0
  22. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/index-v1.json +0 -0
  23. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/messaging-v1.json +0 -0
  24. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/openapi/research-v1.json +0 -0
  25. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/setup.cfg +0 -0
  26. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/setup.py +0 -0
  27. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/README.md +0 -0
  28. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/__init__.py +0 -0
  29. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/__main__.py +0 -0
  30. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/AGENTS.md +0 -0
  31. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/README.md +0 -0
  32. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/__init__.py +0 -0
  33. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/__main__.py +0 -0
  34. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/index.py +0 -0
  35. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/main.py +0 -0
  36. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research.py +0 -0
  37. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_environments.py +0 -0
  38. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/cli/research_image_releases.py +0 -0
  39. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/client.py +0 -0
  40. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/README.md +0 -0
  41. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/__init__.py +0 -0
  42. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/auth/__init__.py +0 -0
  43. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/auth/credentials.py +0 -0
  44. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/__init__.py +0 -0
  45. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/json_value.py +0 -0
  46. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/contracts/pagination.py +0 -0
  47. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/errors.py +0 -0
  48. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/__init__.py +0 -0
  49. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/async_transport.py +0 -0
  50. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/request.py +0 -0
  51. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/retry.py +0 -0
  52. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/streaming.py +0 -0
  53. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/http/transport.py +0 -0
  54. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/research/__init__.py +0 -0
  55. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/__init__.py +0 -0
  56. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/env.py +0 -0
  57. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/log_filter.py +0 -0
  58. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/paths.py +0 -0
  59. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/core/utils/urls.py +0 -0
  60. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/__init__.py +0 -0
  61. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/__main__.py +0 -0
  62. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/objective_tools.py +0 -0
  63. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/registry.py +0 -0
  64. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/request_models.py +0 -0
  65. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/__init__.py +0 -0
  66. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/approvals.py +0 -0
  67. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/artifacts.py +0 -0
  68. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/datasets.py +0 -0
  69. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/environments.py +0 -0
  70. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/exports.py +0 -0
  71. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/factories.py +0 -0
  72. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/factory_results.py +0 -0
  73. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/files.py +0 -0
  74. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/image_releases.py +0 -0
  75. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/integrations.py +0 -0
  76. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/intern_program.py +0 -0
  77. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/local_files.py +0 -0
  78. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/logs.py +0 -0
  79. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/models.py +0 -0
  80. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/outputs.py +0 -0
  81. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/policy_schemas.py +0 -0
  82. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/progress.py +0 -0
  83. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/project_data.py +0 -0
  84. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/projects.py +0 -0
  85. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/prs.py +0 -0
  86. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/readiness.py +0 -0
  87. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/repos.py +0 -0
  88. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/research_intern.py +0 -0
  89. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/resources.py +0 -0
  90. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/runs.py +0 -0
  91. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/trained_models.py +0 -0
  92. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/usage.py +0 -0
  93. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/mcp/research/tools/visuals.py +0 -0
  94. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/pools.py +0 -0
  95. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/py.typed +0 -0
  96. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/README.md +0 -0
  97. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/__init__.py +0 -0
  98. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/agent_policy.py +0 -0
  99. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/answer.py +0 -0
  100. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/artifacts.py +0 -0
  101. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/contracts.py +0 -0
  102. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/contributions.py +0 -0
  103. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/lifecycle.py +0 -0
  104. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/package.py +0 -0
  105. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/public.py +0 -0
  106. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/research_intake.py +0 -0
  107. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/retry.py +0 -0
  108. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/search.py +0 -0
  109. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/submission.py +0 -0
  110. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/timeouts.py +0 -0
  111. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/transfer.py +0 -0
  112. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/index/usage_accounting.py +0 -0
  113. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/README.md +0 -0
  114. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/__init__.py +0 -0
  115. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/client.py +0 -0
  116. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/messaging/contracts.py +0 -0
  117. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/__init__.py +0 -0
  118. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/client.py +0 -0
  119. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/optimizers/contracts.py +0 -0
  120. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/pagination.py +0 -0
  121. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/__init__.py +0 -0
  122. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/__init__.py +0 -0
  123. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/crypto.py +0 -0
  124. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/env.py +0 -0
  125. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/_internal/urls.py +0 -0
  126. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/account.py +0 -0
  127. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced.py +0 -0
  128. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced_factories.py +0 -0
  129. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/advanced_swarms.py +0 -0
  130. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/artifacts.py +0 -0
  131. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/auth.py +0 -0
  132. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/client.py +0 -0
  133. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/__init__.py +0 -0
  134. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/api.py +0 -0
  135. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/contracts.py +0 -0
  136. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/operations.py +0 -0
  137. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/container_pools/packaging.py +0 -0
  138. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/__init__.py +0 -0
  139. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_activity_wire.py +0 -0
  140. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_environment_wire.py +0 -0
  141. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_transcript_wire.py +0 -0
  142. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/_wire.py +0 -0
  143. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/activity.py +0 -0
  144. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/activity_items.py +0 -0
  145. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/actor_images.py +0 -0
  146. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/billing.py +0 -0
  147. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/canonical_usage.py +0 -0
  148. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/checkpoints.py +0 -0
  149. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/cloud_deployment_claims.py +0 -0
  150. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/cloud_deployments.py +0 -0
  151. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/common.py +0 -0
  152. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/dataset_revisions.py +0 -0
  153. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/deliveries.py +0 -0
  154. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/dev_environment_evidence.py +0 -0
  155. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/economics.py +0 -0
  156. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/environment_manifest.py +0 -0
  157. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/environments.py +0 -0
  158. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/evidence.py +0 -0
  159. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factories.py +0 -0
  160. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_evidence.py +0 -0
  161. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_lenses.py +0 -0
  162. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_operations.py +0 -0
  163. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/factory_role_receipts.py +0 -0
  164. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/failure.py +0 -0
  165. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/image_releases.py +0 -0
  166. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_blockers.py +0 -0
  167. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_grants.py +0 -0
  168. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_program.py +0 -0
  169. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_resources.py +0 -0
  170. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/intern_usage.py +0 -0
  171. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/limit_evidence.py +0 -0
  172. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/local_execution_profile.py +0 -0
  173. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/operator_evidence.py +0 -0
  174. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project.py +0 -0
  175. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_data.py +0 -0
  176. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_runtime.py +0 -0
  177. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_workspace.py +0 -0
  178. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/project_workspace_evidence.py +0 -0
  179. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/projects.py +0 -0
  180. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/promotions.py +0 -0
  181. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/research_intern.py +0 -0
  182. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/resource_settlement.py +0 -0
  183. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_authority.py +0 -0
  184. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_control.py +0 -0
  185. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_diagnostics.py +0 -0
  186. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_events.py +0 -0
  187. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_execution.py +0 -0
  188. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_launch.py +0 -0
  189. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_observability.py +0 -0
  190. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_state.py +0 -0
  191. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/run_timeline.py +0 -0
  192. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_image.py +0 -0
  193. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_intent.py +0 -0
  194. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_stream.py +0 -0
  195. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/runtime_stream_snapshot.py +0 -0
  196. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/scientific_integrity.py +0 -0
  197. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_actor_models.py +0 -0
  198. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_actor_policy_data.py +0 -0
  199. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_harnesses.py +0 -0
  200. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_kinds.py +0 -0
  201. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_agent_models.py +0 -0
  202. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_branching.py +0 -0
  203. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_credential_providers.py +0 -0
  204. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_environment_kinds.py +0 -0
  205. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_evidence_obligations.py +0 -0
  206. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_funding_sources.py +0 -0
  207. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_horizons.py +0 -0
  208. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_host_kinds.py +0 -0
  209. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_inference_providers.py +0 -0
  210. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_network_topology.py +0 -0
  211. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_providers.py +0 -0
  212. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_resource_kinds.py +0 -0
  213. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_roles.py +0 -0
  214. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_run_policy.py +0 -0
  215. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runbooks.py +0 -0
  216. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runnable_project.py +0 -0
  217. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_runtime_kinds.py +0 -0
  218. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_tool_providers.py +0 -0
  219. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/smr_work_modes.py +0 -0
  220. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/status.py +0 -0
  221. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/swarm_rollouts.py +0 -0
  222. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/swarms.py +0 -0
  223. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/tag.py +0 -0
  224. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/traces.py +0 -0
  225. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/transcript.py +0 -0
  226. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/types.py +0 -0
  227. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/usage.py +0 -0
  228. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/visuals.py +0 -0
  229. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/wire_models.py +0 -0
  230. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/wire_models_README.md +0 -0
  231. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/contracts/work_products.py +0 -0
  232. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/economics.py +0 -0
  233. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/efforts.py +0 -0
  234. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/environments.py +0 -0
  235. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/errors.py +0 -0
  236. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/events.py +0 -0
  237. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/experiments.py +0 -0
  238. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/facade.py +0 -0
  239. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/factories.py +0 -0
  240. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/factory_storage.py +0 -0
  241. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/image_releases.py +0 -0
  242. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/intern_blockers.py +0 -0
  243. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/intern_program.py +0 -0
  244. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/knowledge.py +0 -0
  245. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/models.py +0 -0
  246. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/operations.py +0 -0
  247. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_data.py +0 -0
  248. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_deliveries.py +0 -0
  249. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/project_workspaces.py +0 -0
  250. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/projects.py +0 -0
  251. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/public.py +0 -0
  252. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/readouts.py +0 -0
  253. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/research_intern.py +0 -0
  254. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/secrets.py +0 -0
  255. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/README.md +0 -0
  256. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/__init__.py +0 -0
  257. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_base.py +0 -0
  258. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_client_helpers.py +0 -0
  259. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/_run_authority_mixin.py +0 -0
  260. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/approvals.py +0 -0
  261. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/billing.py +0 -0
  262. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/client.py +0 -0
  263. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/cloud_deployments.py +0 -0
  264. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/config.py +0 -0
  265. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/cost.py +0 -0
  266. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/datasets.py +0 -0
  267. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/dev_environments.py +0 -0
  268. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/environments.py +0 -0
  269. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/exports.py +0 -0
  270. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/factories.py +0 -0
  271. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/factory_evidence.py +0 -0
  272. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/files.py +0 -0
  273. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/github.py +0 -0
  274. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/image_releases.py +0 -0
  275. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/images.py +0 -0
  276. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/logs.py +0 -0
  277. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/models.py +0 -0
  278. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/outputs.py +0 -0
  279. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/progress.py +0 -0
  280. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/project.py +0 -0
  281. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/projects.py +0 -0
  282. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/prs.py +0 -0
  283. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/readiness.py +0 -0
  284. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/repositories.py +0 -0
  285. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/runs.py +0 -0
  286. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/secrets.py +0 -0
  287. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/setup.py +0 -0
  288. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/tag.py +0 -0
  289. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/trained_models.py +0 -0
  290. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/transport.py +0 -0
  291. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/usage.py +0 -0
  292. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/work_products.py +0 -0
  293. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/session/workspace_inputs.py +0 -0
  294. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/surface_parity.py +0 -0
  295. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/swarms.py +0 -0
  296. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/traces.py +0 -0
  297. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/__init__.py +0 -0
  298. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/http.py +0 -0
  299. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/transport/pagination.py +0 -0
  300. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/version.py +0 -0
  301. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/visuals.py +0 -0
  302. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai/sdk/research/wiki.py +0 -0
  303. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/dependency_links.txt +0 -0
  304. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/entry_points.txt +0 -0
  305. {synth_ai-0.20.2.dev643 → synth_ai-0.21.0.dev647}/synth_ai.egg-info/requires.txt +0 -0
  306. {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.20.2.dev643
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.20.0-orange synth-ai==0.20.0 -->
32
+ <!-- CI release pins: PyPI-0.21.0-orange synth-ai==0.21.0 -->
33
33
 
34
34
  [![PyPI version](https://img.shields.io/pypi/v/synth-ai.svg)](https://pypi.org/project/synth-ai/)
35
35
  [![License](https://img.shields.io/pypi/l/synth-ai.svg)](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.20.0-orange synth-ai==0.20.0 -->
3
+ <!-- CI release pins: PyPI-0.21.0-orange synth-ai==0.21.0 -->
4
4
 
5
5
  [![PyPI version](https://img.shields.io/pypi/v/synth-ai.svg)](https://pypi.org/project/synth-ai/)
6
6
  [![License](https://img.shields.io/pypi/l/synth-ai.svg)](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:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "synth-ai"
3
- version = "0.20.2.dev643"
3
+ version = "0.21.0.dev647"
4
4
  description = "Python SDK and CLI for Synth Index, Managed Research, and Research Factory"
5
5
  authors = [{name = "Synth AI", email = "josh@usesynth.ai"}]
6
6
  license = "MIT"
@@ -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 only;
53
- authenticated search and durable-search lifecycle tools require the key.
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
- include_search=self._default_api_key is not None,
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 authenticated Search and answer tools
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.client import STATUS_POLL_TIMEOUT_SECONDS, IndexAPI
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.search import ContentsSpec, SearchSpec
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
- "Search intent and caller-owned billing bound. Current FAST public and private "
66
- "searches cost 5 cents; wallet funding needs billing.allow_wallet=true and "
67
- "billing.max_charge_cents>=5. DEEP needs a mode grant and a ceiling of "
68
- "at least 10 cents. Never infer funding consent from the query."
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
- Search requires an explicit stable key because private or deep searches may
136
- consume bounded service resources. Backend authorization, execution and usage
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 = IndexSearchRequest.model_validate(arguments)
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="Search reviewed Synth Index Contributions with an authenticated funding identity. Current FAST public and private searches cost 5 cents; wallet funding requires search.billing.allow_wallet=true and max_charge_cents>=5. 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.",
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. Current FAST public/private wallet searches need explicit consent and a ceiling of at least 5 cents; DEEP needs a mode grant and at least 10 cents. 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.",
246
- input_schema=IndexSearchRequest.model_json_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",
@@ -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({"path", "content", "content_type", "encoding", "kind", "metadata"})
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` and
24
- > `index_search_create` with the key. Without a key it may advertise public
25
- > browse tools, but it must not advertise search or durable-search lifecycle
26
- > tools. Tool discovery must not execute a search or incur a charge.
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
- > For a later search I explicitly request, first state the aggregate maximum
29
- > charge and use a fresh idempotency key. Current public- and private-scope FAST
30
- > searches are both priced at 5 cents. Wallet funding requires
31
- > `search.billing.allow_wallet=true` and `max_charge_cents` of at least 5; do
32
- > not infer my wallet consent from a query. DEEP also needs a mode grant and a
33
- > ceiling of at least 10 cents. If a response is uncertain, retry the same
34
- > logical request with the **same** idempotency key, not a new charge attempt.
35
- > Preserve returned Contribution and revision IDs when reporting evidence.
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