synth-ai 0.22.2.dev687__tar.gz → 0.22.2.dev688__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 (359) hide show
  1. {synth_ai-0.22.2.dev687/synth_ai.egg-info → synth_ai-0.22.2.dev688}/PKG-INFO +1 -1
  2. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/pyproject.toml +1 -1
  3. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/index.py +1 -1
  4. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/registry.py +1 -0
  5. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/server.py +9 -0
  6. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/index.py +2 -22
  7. synth_ai-0.22.2.dev688/synth_ai/mcp/research/tools/local_files.py +5 -0
  8. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/runs.py +13 -0
  9. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/scientific_records.py +12 -1
  10. synth_ai-0.22.2.dev688/synth_ai/sdk/index/local_files.py +32 -0
  11. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/upload_session.py +1 -1
  12. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/__init__.py +8 -0
  13. synth_ai-0.22.2.dev688/synth_ai/sdk/research/contracts/forge_citations.py +29 -0
  14. synth_ai-0.22.2.dev688/synth_ai/sdk/research/contracts/forge_uploads.py +84 -0
  15. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/runtime_intent.py +40 -0
  16. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/status.py +81 -9
  17. synth_ai-0.22.2.dev688/synth_ai/sdk/research/contracts/swarm_history.py +167 -0
  18. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/operations.py +6 -0
  19. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/scientific_records.py +137 -0
  20. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/_client_helpers.py +24 -0
  21. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/client.py +23 -29
  22. synth_ai-0.22.2.dev688/synth_ai/sdk/research/session/directory_inputs.py +243 -0
  23. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/swarms.py +39 -0
  24. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688/synth_ai.egg-info}/PKG-INFO +1 -1
  25. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai.egg-info/SOURCES.txt +6 -0
  26. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/LICENSE +0 -0
  27. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/MANIFEST.in +0 -0
  28. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/README.md +0 -0
  29. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/openapi/index-v1.json +0 -0
  30. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/openapi/messaging-v1.json +0 -0
  31. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/openapi/research-v1.json +0 -0
  32. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/setup.cfg +0 -0
  33. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/setup.py +0 -0
  34. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/README.md +0 -0
  35. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/__init__.py +0 -0
  36. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/__main__.py +0 -0
  37. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/AGENTS.md +0 -0
  38. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/README.md +0 -0
  39. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/__init__.py +0 -0
  40. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/__main__.py +0 -0
  41. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/main.py +0 -0
  42. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/research.py +0 -0
  43. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/research_environments.py +0 -0
  44. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/research_image_releases.py +0 -0
  45. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/research_projects.py +0 -0
  46. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/utils/__init__.py +0 -0
  47. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/cli/utils/research_launch.py +0 -0
  48. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/client.py +0 -0
  49. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/README.md +0 -0
  50. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/__init__.py +0 -0
  51. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/auth/__init__.py +0 -0
  52. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/auth/credentials.py +0 -0
  53. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/contracts/__init__.py +0 -0
  54. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/contracts/json_value.py +0 -0
  55. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/contracts/pagination.py +0 -0
  56. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/errors.py +0 -0
  57. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/__init__.py +0 -0
  58. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/async_transport.py +0 -0
  59. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/request.py +0 -0
  60. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/retry.py +0 -0
  61. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/streaming.py +0 -0
  62. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/http/transport.py +0 -0
  63. {synth_ai-0.22.2.dev687/synth_ai/mcp/research/tools → synth_ai-0.22.2.dev688/synth_ai/core}/local_files.py +0 -0
  64. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/research/__init__.py +0 -0
  65. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/utils/__init__.py +0 -0
  66. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/utils/env.py +0 -0
  67. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/utils/log_filter.py +0 -0
  68. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/utils/paths.py +0 -0
  69. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/core/utils/urls.py +0 -0
  70. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/README.md +0 -0
  71. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/__init__.py +0 -0
  72. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/__main__.py +0 -0
  73. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/objective_tools.py +0 -0
  74. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/request_models.py +0 -0
  75. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/__init__.py +0 -0
  76. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/approvals.py +0 -0
  77. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/artifacts.py +0 -0
  78. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/datasets.py +0 -0
  79. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/environments.py +0 -0
  80. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/exports.py +0 -0
  81. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/factories.py +0 -0
  82. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/factory_results.py +0 -0
  83. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/files.py +0 -0
  84. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/image_releases.py +0 -0
  85. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/index_qa.py +0 -0
  86. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/integrations.py +0 -0
  87. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/intern_program.py +0 -0
  88. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/launch_schemas.py +0 -0
  89. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/logs.py +0 -0
  90. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/models.py +0 -0
  91. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/outputs.py +0 -0
  92. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/policy_schemas.py +0 -0
  93. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/progress.py +0 -0
  94. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/project_data.py +0 -0
  95. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/projects.py +0 -0
  96. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/prs.py +0 -0
  97. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/readiness.py +0 -0
  98. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/repos.py +0 -0
  99. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/research_intern.py +0 -0
  100. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/resource_reads.py +0 -0
  101. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/resources.py +0 -0
  102. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/trained_models.py +0 -0
  103. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/usage.py +0 -0
  104. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/visuals.py +0 -0
  105. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/mcp/research/tools/workspace_inputs.py +0 -0
  106. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/pools.py +0 -0
  107. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/py.typed +0 -0
  108. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/README.md +0 -0
  109. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/__init__.py +0 -0
  110. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/AGENT_SETUP_PROMPT.md +0 -0
  111. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/README.md +0 -0
  112. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/__init__.py +0 -0
  113. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/agent_policy.py +0 -0
  114. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/artifacts.py +0 -0
  115. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/catalog.py +0 -0
  116. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/catalogue.py +0 -0
  117. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/classification.py +0 -0
  118. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/client.py +0 -0
  119. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/contracts.py +0 -0
  120. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/contributions.py +0 -0
  121. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/errors.py +0 -0
  122. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/forge_notices.py +0 -0
  123. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/intake.py +0 -0
  124. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/lifecycle.py +0 -0
  125. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/manifest.py +0 -0
  126. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/oauth.py +0 -0
  127. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/package.py +0 -0
  128. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/public.py +0 -0
  129. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/public_corpus.py +0 -0
  130. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/public_search.py +0 -0
  131. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/qa.py +0 -0
  132. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/qa_checks.py +0 -0
  133. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/qa_preflight.py +0 -0
  134. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/qa_reviews.py +0 -0
  135. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/__init__.py +0 -0
  136. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/build.py +0 -0
  137. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/capture.py +0 -0
  138. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/contracts.py +0 -0
  139. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/files.py +0 -0
  140. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research/release.py +0 -0
  141. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/research_intake.py +0 -0
  142. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/retry.py +0 -0
  143. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/rights.py +0 -0
  144. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/scientific_provenance.py +0 -0
  145. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/scope_errors.py +0 -0
  146. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/scopes.py +0 -0
  147. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/search.py +0 -0
  148. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/submission.py +0 -0
  149. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/timeouts.py +0 -0
  150. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/transfer.py +0 -0
  151. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/usage_accounting.py +0 -0
  152. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/value.py +0 -0
  153. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/index/wallet_search.py +0 -0
  154. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/messaging/README.md +0 -0
  155. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/messaging/__init__.py +0 -0
  156. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/messaging/client.py +0 -0
  157. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/messaging/contracts.py +0 -0
  158. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/optimizers/__init__.py +0 -0
  159. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/optimizers/client.py +0 -0
  160. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/optimizers/contracts.py +0 -0
  161. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/pagination.py +0 -0
  162. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/__init__.py +0 -0
  163. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/_internal/__init__.py +0 -0
  164. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/_internal/crypto.py +0 -0
  165. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/_internal/env.py +0 -0
  166. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/_internal/urls.py +0 -0
  167. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/account.py +0 -0
  168. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/advanced.py +0 -0
  169. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/advanced_factories.py +0 -0
  170. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/advanced_swarms.py +0 -0
  171. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/artifacts.py +0 -0
  172. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/auth.py +0 -0
  173. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/client.py +0 -0
  174. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/container_pools/__init__.py +0 -0
  175. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/container_pools/api.py +0 -0
  176. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/container_pools/contracts.py +0 -0
  177. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/container_pools/operations.py +0 -0
  178. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/container_pools/packaging.py +0 -0
  179. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/_activity_wire.py +0 -0
  180. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/_environment_wire.py +0 -0
  181. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/_transcript_wire.py +0 -0
  182. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/_wire.py +0 -0
  183. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/activity.py +0 -0
  184. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/activity_items.py +0 -0
  185. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/actor_images.py +0 -0
  186. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/billing.py +0 -0
  187. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/canonical_usage.py +0 -0
  188. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/checkpoints.py +0 -0
  189. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/cloud_deployment_claims.py +0 -0
  190. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/cloud_deployments.py +0 -0
  191. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/common.py +0 -0
  192. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/dataset_revisions.py +0 -0
  193. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/deliveries.py +0 -0
  194. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/dev_environment_evidence.py +0 -0
  195. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/economics.py +0 -0
  196. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/environment_manifest.py +0 -0
  197. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/environments.py +0 -0
  198. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/evidence.py +0 -0
  199. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/experiment_evidence.py +0 -0
  200. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/factories.py +0 -0
  201. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/factory_evidence.py +0 -0
  202. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/factory_lenses.py +0 -0
  203. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/factory_operations.py +0 -0
  204. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/factory_role_receipts.py +0 -0
  205. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/failure.py +0 -0
  206. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/__init__.py +0 -0
  207. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/contracts.py +0 -0
  208. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/evaluation.py +0 -0
  209. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/exports.py +0 -0
  210. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/operations.py +0 -0
  211. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/records.py +0 -0
  212. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/resources.py +0 -0
  213. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/forge/schema.py +0 -0
  214. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/image_releases.py +0 -0
  215. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_authority.py +0 -0
  216. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_blockers.py +0 -0
  217. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_grants.py +0 -0
  218. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_program.py +0 -0
  219. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_resources.py +0 -0
  220. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/intern_usage.py +0 -0
  221. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/limit_evidence.py +0 -0
  222. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/local_execution_profile.py +0 -0
  223. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/native_attachment.py +0 -0
  224. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/native_result_outcome.py +0 -0
  225. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/operator_evidence.py +0 -0
  226. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/project.py +0 -0
  227. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/project_data.py +0 -0
  228. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/project_runtime.py +0 -0
  229. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/project_workspace.py +0 -0
  230. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/project_workspace_evidence.py +0 -0
  231. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/projects.py +0 -0
  232. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/promotions.py +0 -0
  233. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/research_intern.py +0 -0
  234. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/resource_reads.py +0 -0
  235. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/resource_settlement.py +0 -0
  236. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_authority.py +0 -0
  237. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_control.py +0 -0
  238. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_diagnostics.py +0 -0
  239. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_events.py +0 -0
  240. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_execution.py +0 -0
  241. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_launch.py +0 -0
  242. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_observability.py +0 -0
  243. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_state.py +0 -0
  244. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/run_timeline.py +0 -0
  245. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/runtime_image.py +0 -0
  246. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/runtime_stream.py +0 -0
  247. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/runtime_stream_snapshot.py +0 -0
  248. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/scientific_citations.py +0 -0
  249. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/scientific_integrity.py +0 -0
  250. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_actor_models.py +0 -0
  251. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_actor_policy_data.py +0 -0
  252. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_agent_harnesses.py +0 -0
  253. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_agent_kinds.py +0 -0
  254. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_agent_models.py +0 -0
  255. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_branching.py +0 -0
  256. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_credential_providers.py +0 -0
  257. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_environment_kinds.py +0 -0
  258. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_evidence_obligations.py +0 -0
  259. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_funding_sources.py +0 -0
  260. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_horizons.py +0 -0
  261. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_host_kinds.py +0 -0
  262. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_inference_providers.py +0 -0
  263. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_network_topology.py +0 -0
  264. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_providers.py +0 -0
  265. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_resource_kinds.py +0 -0
  266. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_roles.py +0 -0
  267. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_run_policy.py +0 -0
  268. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_runbooks.py +0 -0
  269. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_runnable_project.py +0 -0
  270. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_runtime_kinds.py +0 -0
  271. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_tool_providers.py +0 -0
  272. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/smr_work_modes.py +0 -0
  273. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/swarm_controls.py +0 -0
  274. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/swarm_rollouts.py +0 -0
  275. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/swarm_tasks.py +0 -0
  276. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/swarms.py +0 -0
  277. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/tag.py +0 -0
  278. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/traces.py +0 -0
  279. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/transcript.py +0 -0
  280. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/types.py +0 -0
  281. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/usage.py +0 -0
  282. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/visuals.py +0 -0
  283. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/wire_models.py +0 -0
  284. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/wire_models_README.md +0 -0
  285. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/work_products.py +0 -0
  286. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/contracts/workspaces.py +0 -0
  287. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/economics.py +0 -0
  288. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/efforts.py +0 -0
  289. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/environments.py +0 -0
  290. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/errors.py +0 -0
  291. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/events.py +0 -0
  292. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/experiments.py +0 -0
  293. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/facade.py +0 -0
  294. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/factories.py +0 -0
  295. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/factory_storage.py +0 -0
  296. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/image_releases.py +0 -0
  297. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/intern_authority.py +0 -0
  298. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/intern_blockers.py +0 -0
  299. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/intern_program.py +0 -0
  300. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/knowledge.py +0 -0
  301. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/models.py +0 -0
  302. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/project_data.py +0 -0
  303. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/project_deliveries.py +0 -0
  304. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/project_workspaces.py +0 -0
  305. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/projects.py +0 -0
  306. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/public.py +0 -0
  307. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/readouts.py +0 -0
  308. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/research_intern.py +0 -0
  309. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/resource_reads.py +0 -0
  310. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/secrets.py +0 -0
  311. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/README.md +0 -0
  312. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/__init__.py +0 -0
  313. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/_base.py +0 -0
  314. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/_run_authority_mixin.py +0 -0
  315. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/approvals.py +0 -0
  316. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/billing.py +0 -0
  317. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/cloud_deployments.py +0 -0
  318. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/config.py +0 -0
  319. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/cost.py +0 -0
  320. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/datasets.py +0 -0
  321. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/dev_environments.py +0 -0
  322. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/environments.py +0 -0
  323. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/exports.py +0 -0
  324. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/factories.py +0 -0
  325. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/factory_evidence.py +0 -0
  326. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/files.py +0 -0
  327. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/github.py +0 -0
  328. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/image_releases.py +0 -0
  329. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/images.py +0 -0
  330. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/logs.py +0 -0
  331. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/models.py +0 -0
  332. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/outputs.py +0 -0
  333. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/progress.py +0 -0
  334. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/project.py +0 -0
  335. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/projects.py +0 -0
  336. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/prs.py +0 -0
  337. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/readiness.py +0 -0
  338. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/repositories.py +0 -0
  339. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/runs.py +0 -0
  340. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/secrets.py +0 -0
  341. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/setup.py +0 -0
  342. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/tag.py +0 -0
  343. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/trained_models.py +0 -0
  344. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/transport.py +0 -0
  345. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/usage.py +0 -0
  346. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/work_products.py +0 -0
  347. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/session/workspace_inputs.py +0 -0
  348. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/surface_parity.py +0 -0
  349. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/traces.py +0 -0
  350. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/transport/__init__.py +0 -0
  351. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/transport/http.py +0 -0
  352. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/transport/pagination.py +0 -0
  353. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/version.py +0 -0
  354. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/visuals.py +0 -0
  355. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai/sdk/research/wiki.py +0 -0
  356. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai.egg-info/dependency_links.txt +0 -0
  357. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai.egg-info/entry_points.txt +0 -0
  358. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/synth_ai.egg-info/requires.txt +0 -0
  359. {synth_ai-0.22.2.dev687 → synth_ai-0.22.2.dev688}/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.22.2.dev687
3
+ Version: 0.22.2.dev688
4
4
  Summary: Python SDK, CLI and MCP servers for Synth Index search and Swarms
5
5
  Author-email: Synth AI <josh@usesynth.ai>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "synth-ai"
3
- version = "0.22.2.dev687"
3
+ version = "0.22.2.dev688"
4
4
  description = "Python SDK, CLI and MCP servers for Synth Index search and Swarms"
5
5
  keywords = ["synth", "index", "search", "citations", "research", "swarms", "mcp", "sdk"]
6
6
  authors = [{name = "Synth AI", email = "josh@usesynth.ai"}]
@@ -633,8 +633,8 @@ def contribution_status(contribution_id, revision_id, search_id, api_key, backen
633
633
  @_lifecycle_target_options
634
634
  def contribution_upload(draft_file, upload_spec_file, root, files, api_key, backend_url):
635
635
  """Prepare, transfer exactly the selected files, then finalize. Does not submit."""
636
- from synth_ai.mcp.research.tools.index import read_selected_files
637
636
  from synth_ai.sdk.index.contributions import ContributionDraft, ContributionUploadSpec
637
+ from synth_ai.sdk.index.local_files import read_selected_files
638
638
 
639
639
  selected: dict[str, str] = {}
640
640
  for item in files:
@@ -109,6 +109,7 @@ _DEFAULT_REQUIRED_SCOPES_BY_TOOL_NAME: dict[str, tuple[str, ...]] = {
109
109
  "research_get_run": READ_SCOPES,
110
110
  "research_get_swarm_activity": READ_SCOPES,
111
111
  "research_get_swarm_configuration": READ_SCOPES,
112
+ "research_get_run_history": READ_SCOPES,
112
113
  "research_get_swarm_evidence": READ_SCOPES,
113
114
  "research_get_swarm_usage": READ_SCOPES,
114
115
  "research_get_run_execution": READ_SCOPES,
@@ -173,6 +173,7 @@ _STABLE_TOOL_NAMES = RESOURCE_READ_TOOL_NAMES | frozenset(
173
173
  "research_get_record",
174
174
  "research_get_record_citations",
175
175
  "research_get_native_attachments",
176
+ "research_verify_citations",
176
177
  "research_list_records",
177
178
  "research_get_operation_receipt",
178
179
  "research_record_events",
@@ -192,6 +193,7 @@ _STABLE_TOOL_NAMES = RESOURCE_READ_TOOL_NAMES | frozenset(
192
193
  "research_get_run_transcript",
193
194
  "research_get_swarm_activity",
194
195
  "research_get_swarm_configuration",
196
+ "research_get_run_history",
195
197
  "research_get_swarm_evidence",
196
198
  "research_get_swarm_status",
197
199
  "research_get_swarm_usage",
@@ -2015,6 +2017,13 @@ class ResearchMcpServer:
2015
2017
  result = client.runs.get(run_id, project_id=project_id)
2016
2018
  return asdict(result) if is_dataclass(result) else result
2017
2019
 
2020
+ def _tool_get_run_history(self, args: JSONDict) -> JSONDict:
2021
+ run_id = SwarmId(require_string(args, "run_id"))
2022
+ after = _optional_int_default(args, "after", 0)
2023
+ limit = _optional_int_default(args, "limit", 100)
2024
+ with self._core_client_from_args(args) as client:
2025
+ return client.swarms.history(run_id, after=after, limit=limit).to_wire()
2026
+
2018
2027
  def _tool_get_swarm_configuration(self, args: JSONDict) -> JSONDict:
2019
2028
  swarm_id = SwarmId(require_string(args, "run_id"))
2020
2029
  with self._core_client_from_args(args) as client:
@@ -7,8 +7,7 @@ Upload reads only explicitly listed files under an explicit root: this stdio ser
7
7
  runs on the caller's machine; the hosted server cannot read a client's disk.
8
8
  """
9
9
 
10
- import re
11
- from collections.abc import Callable, Mapping
10
+ from collections.abc import Callable
12
11
  from contextlib import AbstractContextManager
13
12
  from typing import Annotated
14
13
 
@@ -24,11 +23,11 @@ from synth_ai.mcp.research.tools.index_qa import (
24
23
  QA_READ_TOOL_NAMES,
25
24
  build_qa_tools,
26
25
  )
27
- from synth_ai.mcp.research.tools.local_files import SelectedFileReader
28
26
  from synth_ai.sdk.index.catalog import PublicSearchCapability
29
27
  from synth_ai.sdk.index.client import STATUS_POLL_TIMEOUT_SECONDS, IndexAPI, PublicIndexAPI
30
28
  from synth_ai.sdk.index.contracts import ContributionReference, Identifier, IndexContract
31
29
  from synth_ai.sdk.index.contributions import ContributionDraft, ContributionUploadSpec
30
+ from synth_ai.sdk.index.local_files import read_selected_files
32
31
  from synth_ai.sdk.index.public_search import (
33
32
  DEFAULT_PUBLIC_SEARCH_WAIT_SECONDS,
34
33
  PublicSearchDisabledError,
@@ -75,11 +74,6 @@ INDEX_WRITE_TOOL_NAMES: tuple[str, ...] = (
75
74
  )
76
75
  INDEX_TOOL_NAMES = frozenset(INDEX_READ_TOOL_NAMES + INDEX_WRITE_TOOL_NAMES)
77
76
 
78
- _UPLOAD_MAX_BYTES = 64 * 1024 * 1024
79
- _CREDENTIAL = re.compile(
80
- rb"(sk-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY"
81
- rb"|ghp_[A-Za-z0-9]{30,}|xox[bpa]-[A-Za-z0-9-]{10,})"
82
- )
83
77
  _KEY = Field(min_length=1, max_length=128, pattern=r"^[a-zA-Z0-9_.-]+$")
84
78
 
85
79
 
@@ -158,20 +152,6 @@ class SubmitRequest(IndexContract):
158
152
  spec: ContributionSubmitSpec
159
153
 
160
154
 
161
- def read_selected_files(root: str, files: Mapping[str, str]) -> dict[str, bytes]:
162
- """Read exactly the listed regular files; reject escapes, symlinks and secrets."""
163
- content: dict[str, bytes] = {}
164
- total = 0
165
- with SelectedFileReader(root) as reader:
166
- for logical_path, relative in files.items():
167
- data = reader.read(relative, _UPLOAD_MAX_BYTES - total)
168
- total += len(data)
169
- if _CREDENTIAL.search(data):
170
- raise ValueError(f"{logical_path}: possible credential; remove it before upload")
171
- content[logical_path] = data
172
- return content
173
-
174
-
175
155
  _PUBLIC_SEARCH_DESCRIPTION = (
176
156
  "Search reviewed Synth Index Contributions (Index Search v0.2). Without an API key "
177
157
  "this is the free public search; mode is fast (synchronous) or deep (admitted, then "
@@ -0,0 +1,5 @@
1
+ """Compatibility import for the shared descriptor-confined file reader."""
2
+
3
+ from synth_ai.core.local_files import SelectedFileReader
4
+
5
+ __all__ = ["SelectedFileReader"]
@@ -821,6 +821,19 @@ def build_run_tools(server: Any) -> list[ToolDefinition]:
821
821
  ),
822
822
  handler=server._tool_get_run,
823
823
  ),
824
+ ToolDefinition(
825
+ name="research_get_run_history",
826
+ description="Read a bounded backend-authorized journal page with decision reasons and redacted inputs.",
827
+ input_schema=tool_schema(
828
+ {
829
+ "run_id": {"type": "string", "description": "Research run id."},
830
+ "after": {"type": "integer", "minimum": 0, "maximum": 2**64 - 1},
831
+ "limit": {"type": "integer", "minimum": 1, "maximum": 256},
832
+ },
833
+ required=["run_id"],
834
+ ),
835
+ handler=server._tool_get_run_history,
836
+ ),
824
837
  ToolDefinition(
825
838
  name="research_get_swarm_configuration",
826
839
  description=(
@@ -58,6 +58,14 @@ class EventArguments(Contract):
58
58
  limit: int = Field(default=100, ge=1, le=1000)
59
59
 
60
60
 
61
+ READ_DESCRIPTIONS = {
62
+ "research_verify_citations": (
63
+ "Check a retained record revision's external citations: retained, dangling, "
64
+ "denied, conflict, unavailable or refused. Read-only."
65
+ ),
66
+ }
67
+
68
+
61
69
  def build_scientific_record_tools(client_factory):
62
70
  def execution_writer(arguments):
63
71
  selected = ExecutionWriteArguments.model_validate(arguments)
@@ -159,6 +167,7 @@ def build_scientific_record_tools(client_factory):
159
167
  )
160
168
  for name, model, method in (
161
169
  ("research_get_record", ReadArguments, "get"),
170
+ ("research_verify_citations", ReadArguments, "verify_citations"),
162
171
  ("research_list_records", ListArguments, "list"),
163
172
  ("research_get_operation_receipt", ReceiptArguments, "receipt"),
164
173
  ("research_record_events", EventArguments, "events"),
@@ -180,7 +189,9 @@ def build_scientific_record_tools(client_factory):
180
189
  tools.append(
181
190
  ToolDefinition(
182
191
  name=name,
183
- description="Read scoped retained scientific evidence.",
192
+ description=READ_DESCRIPTIONS.get(
193
+ name, "Read scoped retained scientific evidence."
194
+ ),
184
195
  input_schema=model.model_json_schema(),
185
196
  handler=reader(model, method),
186
197
  required_scopes=READ_SCOPES,
@@ -0,0 +1,32 @@
1
+ """Explicit, bounded local bytes shared by Index SDK, CLI and MCP uploads.
2
+
3
+ # See: synth_ai/core/local_files.py (descriptor confinement)
4
+ """
5
+
6
+ import re
7
+ from collections.abc import Mapping
8
+
9
+ from synth_ai.core.local_files import SelectedFileReader
10
+
11
+ _UPLOAD_MAX_BYTES = 64 * 1024 * 1024
12
+ _CREDENTIAL = re.compile(
13
+ rb"(sk-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN [A-Z ]*PRIVATE KEY"
14
+ rb"|ghp_[A-Za-z0-9]{30,}|xox[bpa]-[A-Za-z0-9-]{10,})"
15
+ )
16
+
17
+
18
+ def read_selected_files(root: str, files: Mapping[str, str]) -> dict[str, bytes]:
19
+ """Read exactly the listed regular files; reject escapes, symlinks and secrets."""
20
+ content: dict[str, bytes] = {}
21
+ total = 0
22
+ with SelectedFileReader(root) as reader:
23
+ for logical_path, relative in files.items():
24
+ data = reader.read(relative, _UPLOAD_MAX_BYTES - total)
25
+ total += len(data)
26
+ if _CREDENTIAL.search(data):
27
+ raise ValueError(f"{logical_path}: possible credential; remove it before upload")
28
+ content[logical_path] = data
29
+ return content
30
+
31
+
32
+ __all__ = ["read_selected_files"]
@@ -30,8 +30,8 @@ from urllib.parse import urlsplit
30
30
  import httpx
31
31
  from pydantic import ValidationError
32
32
 
33
- from synth_ai.mcp.research.tools.index import read_selected_files
34
33
  from synth_ai.sdk.index.contributions import ContributionUploadPrepared
34
+ from synth_ai.sdk.index.local_files import read_selected_files
35
35
  from synth_ai.sdk.index.transfer import _transfer_content
36
36
 
37
37
  _ACCEPTED = (200, 201, 204)
@@ -430,6 +430,11 @@ from synth_ai.sdk.research.contracts.runtime_stream_snapshot import (
430
430
  )
431
431
  from synth_ai.sdk.research.contracts.status import SwarmPendingAction
432
432
  from synth_ai.sdk.research.contracts.swarm_controls import SwarmControlReceipt
433
+ from synth_ai.sdk.research.contracts.swarm_history import (
434
+ SwarmHistoryDecision,
435
+ SwarmHistoryEntry,
436
+ SwarmHistoryPage,
437
+ )
433
438
  from synth_ai.sdk.research.contracts.swarm_tasks import (
434
439
  RetryKind,
435
440
  ReviewVerdict,
@@ -626,6 +631,9 @@ def __getattr__(name: str) -> object:
626
631
 
627
632
 
628
633
  __all__ = [
634
+ "SwarmHistoryDecision",
635
+ "SwarmHistoryEntry",
636
+ "SwarmHistoryPage",
629
637
  "SwarmControlReceipt",
630
638
  "ReviewVerdict",
631
639
  "RetryKind",
@@ -0,0 +1,29 @@
1
+ # Mirrors backend services/forge/client.py (CitationVerification) and Forge
2
+ # forge_service.persistence.CitationVerification (forge.citation-verification.v1).
3
+ """Read-time custodian state of a retained revision's external citations (R06).
4
+
5
+ The retained record and its exact references are never changed or dropped;
6
+ each external citation reports ``retained``, ``dangling`` (deleted/retired or
7
+ withdrawn), ``denied`` (revoked grant, foreign scope), ``conflict``,
8
+ ``unavailable`` or ``refused`` with the custodian's closed code.
9
+ """
10
+
11
+ from typing import Literal
12
+
13
+ from synth_ai.sdk.research.contracts.forge.contracts import Contract, ExactReference
14
+
15
+ CitationStatus = Literal["retained", "dangling", "denied", "conflict", "unavailable", "refused"]
16
+
17
+
18
+ class CitationCheck(Contract):
19
+ reference: ExactReference
20
+ status: CitationStatus
21
+ code: str = ""
22
+ authority_code: str = ""
23
+
24
+
25
+ class CitationVerification(Contract):
26
+ schema_version: Literal["forge.citation-verification.v1"]
27
+ record: ExactReference
28
+ citations: tuple[CitationCheck, ...]
29
+ retained: bool
@@ -0,0 +1,84 @@
1
+ # Generated from backend packages/forge_authority/uploads.py.
2
+ """Bounded private Forge publication contract; forge-authority.v1.md."""
3
+
4
+ import base64
5
+ import hashlib
6
+ from typing import Literal
7
+
8
+ from pydantic import Field, model_validator
9
+
10
+ from synth_ai.sdk.research.contracts.forge.contracts import (
11
+ Contract,
12
+ Digest,
13
+ ExactReference,
14
+ Identifier,
15
+ Scope,
16
+ )
17
+
18
+ MAX_UPLOAD_BYTES = 4 * 1024 * 1024
19
+
20
+
21
+ class UploadObject(Contract):
22
+ logical_path: str = Field(min_length=1, max_length=1024)
23
+ media_type: str = Field(min_length=1, max_length=128)
24
+ content_base64: str = Field(max_length=5592408, repr=False)
25
+ digest_sha256: Digest
26
+ size_bytes: int = Field(strict=True, ge=0, le=MAX_UPLOAD_BYTES)
27
+
28
+ @model_validator(mode="after")
29
+ def exact_bytes(self):
30
+ if (
31
+ "\\" in self.logical_path
32
+ or "\x00" in self.logical_path
33
+ or any(part in {"", ".", ".."} for part in self.logical_path.split("/"))
34
+ ):
35
+ raise ValueError("normalized relative path required")
36
+ if len(self.bytes()) != self.size_bytes:
37
+ raise ValueError("declared bytes differ")
38
+ return self
39
+
40
+ def bytes(self):
41
+ content = base64.b64decode(self.content_base64, validate=True)
42
+ if (
43
+ len(content) > MAX_UPLOAD_BYTES
44
+ or hashlib.sha256(content).hexdigest() != self.digest_sha256
45
+ ):
46
+ raise ValueError("exact bounded byte digest required")
47
+ return content
48
+
49
+
50
+ class UploadRequest(Contract):
51
+ schema_version: Literal["synth.forge.upload.v1"] = "synth.forge.upload.v1"
52
+ scope: Scope
53
+ operation_id: Identifier
54
+ objects: tuple[UploadObject, ...] = Field(min_length=1, max_length=16)
55
+
56
+ @model_validator(mode="after")
57
+ def bounded_unique_objects(self):
58
+ if len({item.logical_path for item in self.objects}) != len(self.objects):
59
+ raise ValueError("unique object paths required")
60
+ if sum(item.size_bytes for item in self.objects) > MAX_UPLOAD_BYTES:
61
+ raise ValueError("publication exceeds 4 MiB")
62
+ if len({item.digest_sha256 for item in self.objects}) != len(self.objects):
63
+ raise ValueError("unique object digests required for exact reference lookup")
64
+ return self
65
+
66
+
67
+ class UploadedObject(Contract):
68
+ logical_path: str
69
+ media_type: str
70
+ size_bytes: int
71
+ reference: ExactReference
72
+
73
+
74
+ class Uploaded(Contract):
75
+ schema_version: Literal["synth.forge.upload.v1"] = "synth.forge.upload.v1"
76
+ result: Literal["committed"] = "committed"
77
+ scope: Scope
78
+ operation_id: Identifier
79
+ request_digest_sha256: Digest
80
+ publication_id: str
81
+ collection_id: str
82
+ revision: int = Field(strict=True, ge=1)
83
+ manifest: ExactReference
84
+ objects: tuple[UploadedObject, ...] = Field(min_length=1, max_length=16)
@@ -21,6 +21,7 @@ class RuntimeIntentKind(StrEnum):
21
21
  RECORD_SPEND = "record_spend"
22
22
  PLAN_TASKS = "plan_tasks"
23
23
  WRITE_PROJECT_MILESTONES = "write_project_milestones"
24
+ TOOL_WRITE = "tool_write"
24
25
 
25
26
 
26
27
  class RuntimeIntentStatus(StrEnum):
@@ -283,6 +284,38 @@ class RuntimeIntentReceipt:
283
284
  )
284
285
 
285
286
 
287
+ @dataclass(frozen=True)
288
+ class RuntimeScientificRecordReference:
289
+ """Consumer of backend docs/contracts/runtime-scientific-record.v1.md."""
290
+
291
+ schema_version: str
292
+ kind: str
293
+ record_id: str
294
+ parent_entry_id: str | None = None
295
+
296
+ @classmethod
297
+ def from_wire(cls, payload: object) -> RuntimeScientificRecordReference:
298
+ from uuid import UUID
299
+
300
+ mapping = _require_mapping(payload, label="scientific record reference")
301
+ if mapping.get("schema_version") != "runtime_scientific_record.v1":
302
+ raise ValueError("unsupported scientific record reference version")
303
+ kind = str(mapping.get("kind") or "")
304
+ if kind not in {
305
+ "experiment_log_append",
306
+ "experiment_log_attach_link",
307
+ "work_product_publish_report",
308
+ }:
309
+ raise ValueError("unsupported scientific record reference kind")
310
+ identity = str(UUID(str(mapping.get("record_id") or "")))
311
+ parent = mapping.get("parent_entry_id")
312
+ if parent is not None:
313
+ parent = str(UUID(str(parent)))
314
+ if kind == "experiment_log_attach_link" and parent is None:
315
+ raise ValueError("scientific link reference requires parent entry")
316
+ return cls("runtime_scientific_record.v1", kind, identity, parent)
317
+
318
+
286
319
  @dataclass(frozen=True)
287
320
  class RuntimeIntentView(RuntimeIntentReceipt):
288
321
  message_id: str = ""
@@ -301,6 +334,7 @@ class RuntimeIntentView(RuntimeIntentReceipt):
301
334
  error_detail: str | None = None
302
335
  retryable: bool = False
303
336
  applied_mode: str | None = None
337
+ scientific_record: RuntimeScientificRecordReference | None = None
304
338
 
305
339
  @classmethod
306
340
  def from_wire(cls, payload: object) -> RuntimeIntentView:
@@ -331,6 +365,11 @@ class RuntimeIntentView(RuntimeIntentReceipt):
331
365
  error_detail=_optional_string(mapping, "error_detail"),
332
366
  retryable=bool(mapping.get("retryable", False)),
333
367
  applied_mode=_optional_string(mapping, "applied_mode"),
368
+ scientific_record=(
369
+ RuntimeScientificRecordReference.from_wire(mapping["scientific_record"])
370
+ if mapping.get("scientific_record") is not None
371
+ else None
372
+ ),
334
373
  )
335
374
 
336
375
 
@@ -341,4 +380,5 @@ __all__ = [
341
380
  "RuntimeIntentStatus",
342
381
  "RuntimeIntentView",
343
382
  "RuntimeMessageMode",
383
+ "RuntimeScientificRecordReference",
344
384
  ]
@@ -397,6 +397,50 @@ class SwarmPendingAction:
397
397
  }
398
398
 
399
399
 
400
+ @dataclass(frozen=True, slots=True)
401
+ class SwarmStatusAuthorityRef:
402
+ """Evidence reference to the constructor terminal that owns terminal truth.
403
+
404
+ # See: backend services/smr/runtime/terminal_public_adapter.py (hotspot 2a)
405
+ """
406
+
407
+ owner: str
408
+ schema: str
409
+ reference: str
410
+ sha256: str
411
+
412
+ @classmethod
413
+ def from_wire(cls, value: JsonValue) -> SwarmStatusAuthorityRef:
414
+ payload = _exact(
415
+ value,
416
+ label="swarm status authority_ref",
417
+ fields=frozenset({"owner", "schema", "reference", "sha256"}),
418
+ )
419
+ return cls(
420
+ required_text(payload, "owner"),
421
+ required_text(payload, "schema"),
422
+ required_text(payload, "reference"),
423
+ required_text(payload, "sha256"),
424
+ )
425
+
426
+ def to_wire(self) -> JsonObject:
427
+ return {
428
+ "owner": self.owner,
429
+ "schema": self.schema,
430
+ "reference": self.reference,
431
+ "sha256": self.sha256,
432
+ }
433
+
434
+
435
+ def _optional_bool(payload: JsonObject, name: str) -> bool | None:
436
+ value = payload.get(name)
437
+ if value is None:
438
+ return None
439
+ if not isinstance(value, bool):
440
+ raise ValueError(f"{name} must be a boolean or null")
441
+ return value
442
+
443
+
400
444
  _STATUS_FIELDS = frozenset(
401
445
  {
402
446
  "schema_version",
@@ -413,8 +457,15 @@ _STATUS_FIELDS = frozenset(
413
457
  "freshness",
414
458
  }
415
459
  )
416
- # Orchestra-authority runs carry unanswered actions; older backends omit the key.
417
- _STATUS_OPTIONAL_FIELDS = frozenset({"pending_questions"})
460
+ # Known keys an older backend may omit. Each is parsed strictly when present:
461
+ # Orchestra-authority runs carry unanswered actions (``pending_questions``);
462
+ # the hotspot 2a terminal adapter (Pressure beceec07) carries ``active``,
463
+ # ``authority_ref`` and ``finished_at``.
464
+ _STATUS_OPTIONAL_FIELDS = frozenset({"pending_questions", "active", "authority_ref", "finished_at"})
465
+
466
+
467
+ # Preserve both public names for the same strict pending-question contract.
468
+ SwarmStatusPendingQuestion = SwarmPendingAction
418
469
 
419
470
 
420
471
  @dataclass(frozen=True, slots=True)
@@ -434,18 +485,31 @@ class SwarmStatus:
434
485
  freshness: SwarmStatusFreshness
435
486
  schema_version: int = 1
436
487
  pending_actions: tuple[SwarmPendingAction, ...] = ()
488
+ # ``None`` means the backend did not send the key (older backend) or
489
+ # explicitly published no value (no terminal authority / refused authority).
490
+ active: bool | None = None
491
+ authority_ref: SwarmStatusAuthorityRef | None = None
492
+ finished_at: datetime | None = None
493
+ # Top-level keys this SDK does not know yet. Additive server fields must
494
+ # not break installed clients (Pressure 6204833e); their names are kept so
495
+ # callers can detect a newer server, their values are not interpreted.
496
+ unrecognized_fields: frozenset[str] = frozenset()
497
+
498
+ @property
499
+ def pending_questions(self) -> tuple[SwarmPendingAction, ...]:
500
+ return self.pending_actions
437
501
 
438
502
  @classmethod
439
503
  def from_wire(cls, value: JsonValue) -> SwarmStatus:
440
504
  payload = object_value(value, operation_id="retrieve_swarm_status")
441
- present = payload.keys() - _STATUS_OPTIONAL_FIELDS
442
- missing, extra = _STATUS_FIELDS - present, present - _STATUS_FIELDS
443
- if missing or extra:
444
- raise ValueError(
445
- "retrieve_swarm_status fields drifted: "
446
- f"missing={sorted(missing)!r} extra={sorted(extra)!r}"
447
- )
505
+ missing = _STATUS_FIELDS - payload.keys()
506
+ if missing:
507
+ raise ValueError(f"retrieve_swarm_status fields drifted: missing={sorted(missing)!r}")
508
+ unrecognized = frozenset(
509
+ str(key) for key in payload.keys() - _STATUS_FIELDS - _STATUS_OPTIONAL_FIELDS
510
+ )
448
511
  pending = payload.get("pending_questions")
512
+ authority_ref = payload.get("authority_ref")
449
513
  schema_version = payload["schema_version"]
450
514
  if schema_version != 1:
451
515
  raise ValueError(f"unsupported swarm status schema_version {schema_version!r}")
@@ -470,6 +534,10 @@ class SwarmStatus:
470
534
  else array_value(pending, operation_id="swarm status pending_questions")
471
535
  )
472
536
  ),
537
+ _optional_bool(payload, "active"),
538
+ None if authority_ref is None else SwarmStatusAuthorityRef.from_wire(authority_ref),
539
+ _optional_datetime(payload, "finished_at"),
540
+ unrecognized,
473
541
  )
474
542
 
475
543
  def to_wire(self) -> JsonObject:
@@ -560,12 +628,16 @@ class SwarmStatus:
560
628
  "generated_at": self.freshness.generated_at.isoformat(),
561
629
  },
562
630
  "pending_questions": [item.to_wire() for item in self.pending_actions],
631
+ "active": self.active,
632
+ "authority_ref": None if self.authority_ref is None else self.authority_ref.to_wire(),
633
+ "finished_at": None if self.finished_at is None else self.finished_at.isoformat(),
563
634
  }
564
635
 
565
636
 
566
637
  __all__ = [
567
638
  "SwarmPendingAction",
568
639
  "SwarmStatus",
640
+ "SwarmStatusAuthorityRef",
569
641
  "SwarmStatusFailure",
570
642
  "SwarmStatusFinalization",
571
643
  "SwarmStatusFreshness",