synth-ai 0.18.1.dev594__tar.gz → 0.18.1.dev596__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 (250) hide show
  1. {synth_ai-0.18.1.dev594/synth_ai.egg-info → synth_ai-0.18.1.dev596}/PKG-INFO +1 -1
  2. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/pyproject.toml +1 -1
  3. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/__init__.py +16 -0
  4. synth_ai-0.18.1.dev596/synth_ai/sdk/research/contracts/failure.py +173 -0
  5. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/image_releases.py +65 -4
  6. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_observability.py +9 -5
  7. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/image_releases.py +48 -0
  8. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/operations.py +7 -0
  9. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/public.py +14 -0
  10. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/runs.py +8 -13
  11. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596/synth_ai.egg-info}/PKG-INFO +1 -1
  12. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai.egg-info/SOURCES.txt +1 -0
  13. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/LICENSE +0 -0
  14. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/MANIFEST.in +0 -0
  15. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/README.md +0 -0
  16. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/setup.cfg +0 -0
  17. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/README.md +0 -0
  18. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/__init__.py +0 -0
  19. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/__main__.py +0 -0
  20. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/AGENTS.md +0 -0
  21. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/README.md +0 -0
  22. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/__init__.py +0 -0
  23. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/__main__.py +0 -0
  24. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/main.py +0 -0
  25. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/research.py +0 -0
  26. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/research_environments.py +0 -0
  27. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/research_image_releases.py +0 -0
  28. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/cli/research_projects.py +0 -0
  29. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/client.py +0 -0
  30. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/README.md +0 -0
  31. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/__init__.py +0 -0
  32. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/auth/__init__.py +0 -0
  33. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/auth/credentials.py +0 -0
  34. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/contracts/__init__.py +0 -0
  35. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/contracts/json_value.py +0 -0
  36. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/contracts/pagination.py +0 -0
  37. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/errors.py +0 -0
  38. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/__init__.py +0 -0
  39. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/async_transport.py +0 -0
  40. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/request.py +0 -0
  41. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/retry.py +0 -0
  42. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/streaming.py +0 -0
  43. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/http/transport.py +0 -0
  44. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/research/__init__.py +0 -0
  45. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/utils/__init__.py +0 -0
  46. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/utils/env.py +0 -0
  47. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/utils/log_filter.py +0 -0
  48. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/utils/paths.py +0 -0
  49. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/core/utils/urls.py +0 -0
  50. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/README.md +0 -0
  51. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/__init__.py +0 -0
  52. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/__main__.py +0 -0
  53. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/objective_tools.py +0 -0
  54. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/registry.py +0 -0
  55. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/request_models.py +0 -0
  56. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/server.py +0 -0
  57. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/__init__.py +0 -0
  58. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/approvals.py +0 -0
  59. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/artifacts.py +0 -0
  60. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/datasets.py +0 -0
  61. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/environments.py +0 -0
  62. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/exports.py +0 -0
  63. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/factories.py +0 -0
  64. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/factory_results.py +0 -0
  65. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/files.py +0 -0
  66. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/image_releases.py +0 -0
  67. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/integrations.py +0 -0
  68. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/logs.py +0 -0
  69. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/models.py +0 -0
  70. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/outputs.py +0 -0
  71. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/policy_schemas.py +0 -0
  72. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/progress.py +0 -0
  73. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/project_data.py +0 -0
  74. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/projects.py +0 -0
  75. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/prs.py +0 -0
  76. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/readiness.py +0 -0
  77. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/repos.py +0 -0
  78. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/resources.py +0 -0
  79. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/runs.py +0 -0
  80. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/trained_models.py +0 -0
  81. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/usage.py +0 -0
  82. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/visuals.py +0 -0
  83. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/mcp/research/tools/workspace_inputs.py +0 -0
  84. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/py.typed +0 -0
  85. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/README.md +0 -0
  86. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/__init__.py +0 -0
  87. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/pagination.py +0 -0
  88. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/__init__.py +0 -0
  89. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/_internal/__init__.py +0 -0
  90. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/_internal/crypto.py +0 -0
  91. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/_internal/env.py +0 -0
  92. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/_internal/urls.py +0 -0
  93. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/account.py +0 -0
  94. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/advanced.py +0 -0
  95. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/advanced_factories.py +0 -0
  96. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/advanced_swarms.py +0 -0
  97. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/artifacts.py +0 -0
  98. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/auth.py +0 -0
  99. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/client.py +0 -0
  100. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/_activity_wire.py +0 -0
  101. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/_environment_wire.py +0 -0
  102. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/_transcript_wire.py +0 -0
  103. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/_wire.py +0 -0
  104. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/activity.py +0 -0
  105. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/activity_items.py +0 -0
  106. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/actor_images.py +0 -0
  107. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/billing.py +0 -0
  108. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/canonical_usage.py +0 -0
  109. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/checkpoints.py +0 -0
  110. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/cloud_deployment_claims.py +0 -0
  111. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/cloud_deployments.py +0 -0
  112. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/common.py +0 -0
  113. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/dataset_revisions.py +0 -0
  114. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/deliveries.py +0 -0
  115. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/dev_environment_evidence.py +0 -0
  116. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/economics.py +0 -0
  117. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/environment_manifest.py +0 -0
  118. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/environments.py +0 -0
  119. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/evidence.py +0 -0
  120. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/factories.py +0 -0
  121. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/factory_evidence.py +0 -0
  122. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/factory_lenses.py +0 -0
  123. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/factory_operations.py +0 -0
  124. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/factory_role_receipts.py +0 -0
  125. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/local_execution_profile.py +0 -0
  126. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/operator_evidence.py +0 -0
  127. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/project.py +0 -0
  128. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/project_data.py +0 -0
  129. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/project_runtime.py +0 -0
  130. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/project_workspace.py +0 -0
  131. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/project_workspace_evidence.py +0 -0
  132. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/projects.py +0 -0
  133. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/promotions.py +0 -0
  134. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/research_intern.py +0 -0
  135. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_authority.py +0 -0
  136. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_control.py +0 -0
  137. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_diagnostics.py +0 -0
  138. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_events.py +0 -0
  139. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_execution.py +0 -0
  140. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_launch.py +0 -0
  141. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_state.py +0 -0
  142. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/run_timeline.py +0 -0
  143. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/runtime_image.py +0 -0
  144. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/runtime_intent.py +0 -0
  145. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/runtime_stream.py +0 -0
  146. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/runtime_stream_snapshot.py +0 -0
  147. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/scientific_integrity.py +0 -0
  148. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_actor_models.py +0 -0
  149. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_actor_policy_data.py +0 -0
  150. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_agent_harnesses.py +0 -0
  151. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_agent_kinds.py +0 -0
  152. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_agent_models.py +0 -0
  153. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_branching.py +0 -0
  154. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_credential_providers.py +0 -0
  155. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_environment_kinds.py +0 -0
  156. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_evidence_obligations.py +0 -0
  157. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_funding_sources.py +0 -0
  158. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_horizons.py +0 -0
  159. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_host_kinds.py +0 -0
  160. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_inference_providers.py +0 -0
  161. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_network_topology.py +0 -0
  162. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_providers.py +0 -0
  163. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_resource_kinds.py +0 -0
  164. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_roles.py +0 -0
  165. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_run_policy.py +0 -0
  166. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_runbooks.py +0 -0
  167. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_runnable_project.py +0 -0
  168. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_runtime_kinds.py +0 -0
  169. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_tool_providers.py +0 -0
  170. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/smr_work_modes.py +0 -0
  171. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/status.py +0 -0
  172. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/swarms.py +0 -0
  173. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/tag.py +0 -0
  174. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/traces.py +0 -0
  175. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/transcript.py +0 -0
  176. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/types.py +0 -0
  177. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/usage.py +0 -0
  178. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/visuals.py +0 -0
  179. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/wire_models.py +0 -0
  180. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/wire_models_README.md +0 -0
  181. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/work_products.py +0 -0
  182. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/contracts/workspaces.py +0 -0
  183. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/economics.py +0 -0
  184. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/efforts.py +0 -0
  185. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/environments.py +0 -0
  186. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/errors.py +0 -0
  187. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/events.py +0 -0
  188. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/experiments.py +0 -0
  189. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/facade.py +0 -0
  190. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/factories.py +0 -0
  191. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/factory_storage.py +0 -0
  192. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/knowledge.py +0 -0
  193. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/models.py +0 -0
  194. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/project_data.py +0 -0
  195. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/project_deliveries.py +0 -0
  196. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/project_workspaces.py +0 -0
  197. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/projects.py +0 -0
  198. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/readouts.py +0 -0
  199. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/research_intern.py +0 -0
  200. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/secrets.py +0 -0
  201. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/README.md +0 -0
  202. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/__init__.py +0 -0
  203. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/_base.py +0 -0
  204. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/_client_helpers.py +0 -0
  205. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/_run_authority_mixin.py +0 -0
  206. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/approvals.py +0 -0
  207. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/billing.py +0 -0
  208. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/client.py +0 -0
  209. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/cloud_deployments.py +0 -0
  210. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/config.py +0 -0
  211. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/cost.py +0 -0
  212. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/datasets.py +0 -0
  213. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/dev_environments.py +0 -0
  214. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/environments.py +0 -0
  215. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/exports.py +0 -0
  216. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/factories.py +0 -0
  217. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/factory_evidence.py +0 -0
  218. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/files.py +0 -0
  219. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/github.py +0 -0
  220. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/image_releases.py +0 -0
  221. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/images.py +0 -0
  222. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/logs.py +0 -0
  223. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/models.py +0 -0
  224. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/outputs.py +0 -0
  225. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/progress.py +0 -0
  226. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/project.py +0 -0
  227. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/projects.py +0 -0
  228. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/prs.py +0 -0
  229. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/readiness.py +0 -0
  230. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/repositories.py +0 -0
  231. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/secrets.py +0 -0
  232. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/setup.py +0 -0
  233. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/tag.py +0 -0
  234. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/trained_models.py +0 -0
  235. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/transport.py +0 -0
  236. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/usage.py +0 -0
  237. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/work_products.py +0 -0
  238. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/session/workspace_inputs.py +0 -0
  239. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/swarms.py +0 -0
  240. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/traces.py +0 -0
  241. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/transport/__init__.py +0 -0
  242. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/transport/http.py +0 -0
  243. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/transport/pagination.py +0 -0
  244. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/version.py +0 -0
  245. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/visuals.py +0 -0
  246. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai/sdk/research/wiki.py +0 -0
  247. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai.egg-info/dependency_links.txt +0 -0
  248. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai.egg-info/entry_points.txt +0 -0
  249. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/synth_ai.egg-info/requires.txt +0 -0
  250. {synth_ai-0.18.1.dev594 → synth_ai-0.18.1.dev596}/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.18.1.dev594
3
+ Version: 0.18.1.dev596
4
4
  Summary: Python SDK and CLI for Synth Managed Research and Research Factory
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.18.1.dev594"
3
+ version = "0.18.1.dev596"
4
4
  description = "Python SDK and CLI for Synth Managed Research and Research Factory"
5
5
  authors = [{name = "Synth AI", email = "josh@usesynth.ai"}]
6
6
  license = "MIT"
@@ -177,6 +177,13 @@ from synth_ai.sdk.research.contracts.factory_role_receipts import (
177
177
  FactoryRoleReceiptResponse,
178
178
  FactoryRoleReceiptRuntimeEvidence,
179
179
  )
180
+ from synth_ai.sdk.research.contracts.failure import (
181
+ ActorFailureReason,
182
+ ManagedResearchFailureClassification,
183
+ ManagedResearchFailureFamily,
184
+ ManagedResearchFailureScope,
185
+ ManagedResearchFailureSeverity,
186
+ )
180
187
  from synth_ai.sdk.research.contracts.image_releases import (
181
188
  ActorImageCapability,
182
189
  ActorRuntimeImageMaterialization,
@@ -199,6 +206,8 @@ from synth_ai.sdk.research.contracts.image_releases import (
199
206
  ImageReleaseUploadRequest,
200
207
  ImageReleaseUploadResponse,
201
208
  ImageUploadId,
209
+ RegistryActorRuntimeImageRegistration,
210
+ RegistryActorRuntimeImageRegistrationRequest,
202
211
  RuntimeImageReleaseArchiveResponse,
203
212
  RuntimeImageReleaseId,
204
213
  RuntimeImageReleaseListResponse,
@@ -476,6 +485,7 @@ def __getattr__(name: str) -> object:
476
485
 
477
486
 
478
487
  __all__ = [
488
+ "ActorFailureReason",
479
489
  "DataBindingCreateRequest",
480
490
  "DataBindingResponse",
481
491
  "DatasetRevisionContent",
@@ -513,6 +523,10 @@ __all__ = [
513
523
  "MagiDecisionReceiptResponse",
514
524
  "MagiDecisionRequest",
515
525
  "MagiMode",
526
+ "ManagedResearchFailureClassification",
527
+ "ManagedResearchFailureFamily",
528
+ "ManagedResearchFailureScope",
529
+ "ManagedResearchFailureSeverity",
516
530
  "ActivityActor",
517
531
  "ActivityActorState",
518
532
  "ActivityCursor",
@@ -545,6 +559,8 @@ __all__ = [
545
559
  "ActorRuntimeImageReleaseArchive",
546
560
  "ActorRuntimeImageReleaseDeclaration",
547
561
  "ActorRuntimeImageReleaseList",
562
+ "RegistryActorRuntimeImageRegistration",
563
+ "RegistryActorRuntimeImageRegistrationRequest",
548
564
  "BranchMode",
549
565
  "BranchResult",
550
566
  "BranchSpec",
@@ -0,0 +1,173 @@
1
+ """Public Managed Research failure vocabulary and wire contract."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from enum import StrEnum
7
+ from typing import Any
8
+
9
+
10
+ class ActorFailureReason(StrEnum):
11
+ ACTOR_STARTUP_RETRY_BUDGET_EXHAUSTED = "actor_startup_retry_budget_exhausted"
12
+ TASK_BLOCKED = "task_blocked"
13
+ TASK_FAILED = "task_failed"
14
+ RUN_FAILED = "run_failed"
15
+ ORCHESTRATOR_SESSION_START_FAILED = "orchestrator_session_start_failed"
16
+ ORCHESTRATOR_SESSION_FAILED = "orchestrator_session_failed"
17
+ TASK_CLAIM_MATERIALIZATION_FAILED = "task_claim_materialization_failed"
18
+ CLAIMED_ACTOR_MISSING_TASK_BINDING = "claimed_actor_missing_task_binding"
19
+ WORKER_HOST_CLAIMED_NON_TASK_ACTOR = "worker_host_claimed_non_task_actor"
20
+ WORKER_HOST_ACTOR_RUN_MISSING = "worker_host_actor_run_missing"
21
+ WORKER_HOST_CLAIMED_ACTOR_TASK_MISSING = "worker_host_claimed_actor_task_missing"
22
+ TASK_ALREADY_TERMINAL = "task_already_terminal"
23
+ DB_POOL_PRESSURE = "db_pool_pressure"
24
+ CONTROL_PLANE_PRESSURE = "control_plane_pressure"
25
+ PARTICIPANT_START_BACKPRESSURE = "participant_start_backpressure"
26
+ PARTICIPANT_SYNC_DEFERRED_UNCONSUMED = "participant_sync_deferred_unconsumed"
27
+ TERMINAL_TRANSITION_DEFERRED_UNCONSUMED = "terminal_transition_deferred_unconsumed"
28
+ PARTICIPANT_LIVE_CAPACITY_EXHAUSTED = "participant_live_capacity_exhausted"
29
+ PARTICIPANT_MEMORY_CAPACITY_EXHAUSTED = "participant_memory_capacity_exhausted"
30
+ EXTERNAL_IO_DEFERRED = "external_io_deferred"
31
+ OPENCODE_ENDPOINT_UNREACHABLE = "opencode_endpoint_unreachable"
32
+ OPENCODE_ENDPOINT_REFUSED = "opencode_endpoint_refused"
33
+ OPENCODE_ENDPOINT_LOST = "opencode_endpoint_lost"
34
+ OPENCODE_ENDPOINT_HEALTH_TIMEOUT = "opencode_endpoint_health_timeout"
35
+ OPENCODE_CONTAINER_OOM = "opencode_container_oom"
36
+ OPENCODE_EVENT_STREAM_ROUTE_UNREACHABLE = "opencode_event_stream_route_unreachable"
37
+ OPENCODE_EVENT_STREAM_ENDPOINT_REFUSED = "opencode_event_stream_endpoint_refused"
38
+ OPENCODE_EVENT_STREAM_READ_TIMEOUT = "opencode_event_stream_read_timeout"
39
+ OPENCODE_EVENT_STREAM_URL_ERROR = "opencode_event_stream_url_error"
40
+ OPENCODE_EVENT_STREAM_RECONNECT_GRACE_EXHAUSTED = (
41
+ "opencode_event_stream_reconnect_grace_exhausted"
42
+ )
43
+ PARTICIPANT_SESSION_MISSING = "participant_session_missing"
44
+ PARTICIPANT_SESSION_START_FAILED = "participant_session_start_failed"
45
+ PARTICIPANT_LIVE_UNBOUND = "participant_live_unbound"
46
+ PARTICIPANT_LIVE_HANDLE_MISSING = "participant_live_handle_missing"
47
+ PARTICIPANT_BINDING_FAILED = "participant_binding_failed"
48
+ CLAIMED_TASK_WITHOUT_PARTICIPANT = "claimed_task_without_participant"
49
+ STALE_CLAIM_REAPED = "stale_claim_reaped"
50
+ RUNTIME_INTENT_BACKLOG = "runtime_intent_backlog"
51
+ UNKNOWN_UNHEALTHY_EXPIRED = "unknown_unhealthy_expired"
52
+ RUNTIME_NO_PRODUCTIVE_PROGRESS = "runtime_no_productive_progress"
53
+
54
+
55
+ class ManagedResearchFailureFamily(StrEnum):
56
+ UNKNOWN = "unknown"
57
+ VALIDATION = "validation"
58
+ BOOTSTRAP = "bootstrap"
59
+ DISPATCH = "dispatch"
60
+ RUNTIME = "runtime"
61
+ RUNTIME_RECOVERY = "runtime_recovery"
62
+ TERMINALIZATION = "terminalization"
63
+ CLEANUP = "cleanup"
64
+ INFRASTRUCTURE = "infrastructure"
65
+ USAGE_CAPTURE = "usage_capture"
66
+ PARTICIPANT_START = "participant_start"
67
+ ORCHESTRATOR_CYCLE = "orchestrator_cycle"
68
+ ORCHESTRATOR_PROVIDER = "orchestrator_provider"
69
+ ORCHESTRATOR_CODEX = "orchestrator_codex"
70
+
71
+
72
+ class ManagedResearchFailureSeverity(StrEnum):
73
+ WARNING = "warning"
74
+ ERROR = "error"
75
+ FATAL = "fatal"
76
+
77
+
78
+ class ManagedResearchFailureScope(StrEnum):
79
+ ACTOR = "actor"
80
+ TASK = "task"
81
+ RUN = "run"
82
+
83
+
84
+ @dataclass(frozen=True)
85
+ class ManagedResearchFailureClassification:
86
+ family: ManagedResearchFailureFamily
87
+ code: str
88
+ severity: ManagedResearchFailureSeverity
89
+ retryable: bool
90
+ scope: ManagedResearchFailureScope | None = None
91
+ operator_action: str | None = None
92
+ detail: str | None = None
93
+ actor_id: str | None = None
94
+ actor_key: str | None = None
95
+ task_id: str | None = None
96
+ task_key: str | None = None
97
+ recorded_at: str | None = None
98
+ family_raw: str | None = None
99
+ raw: dict[str, Any] = field(default_factory=dict, repr=False, compare=False)
100
+
101
+ @classmethod
102
+ def from_wire(cls, payload: object) -> ManagedResearchFailureClassification:
103
+ if not isinstance(payload, dict):
104
+ raise ValueError("run failure classification must be an object")
105
+ family = payload.get("family")
106
+ code = payload.get("code")
107
+ severity = payload.get("severity")
108
+ retryable = payload.get("retryable")
109
+ if not isinstance(family, str) or not isinstance(code, str):
110
+ raise ValueError("run failure classification requires family and code")
111
+ if not isinstance(severity, str) or not isinstance(retryable, bool):
112
+ raise ValueError("run failure classification requires severity and retryable")
113
+ try:
114
+ parsed_family = ManagedResearchFailureFamily(family)
115
+ except ValueError:
116
+ parsed_family = ManagedResearchFailureFamily.UNKNOWN
117
+ return cls(
118
+ family=parsed_family,
119
+ code=code,
120
+ severity=ManagedResearchFailureSeverity(severity),
121
+ retryable=retryable,
122
+ scope=(
123
+ ManagedResearchFailureScope(payload["scope"])
124
+ if isinstance(payload.get("scope"), str)
125
+ else None
126
+ ),
127
+ operator_action=payload.get("operator_action")
128
+ if isinstance(payload.get("operator_action"), str)
129
+ else None,
130
+ detail=payload.get("detail") if isinstance(payload.get("detail"), str) else None,
131
+ actor_id=payload.get("actor_id") if isinstance(payload.get("actor_id"), str) else None,
132
+ actor_key=payload.get("actor_key")
133
+ if isinstance(payload.get("actor_key"), str)
134
+ else None,
135
+ task_id=payload.get("task_id") if isinstance(payload.get("task_id"), str) else None,
136
+ task_key=payload.get("task_key") if isinstance(payload.get("task_key"), str) else None,
137
+ recorded_at=payload.get("recorded_at")
138
+ if isinstance(payload.get("recorded_at"), str)
139
+ else None,
140
+ family_raw=family if parsed_family is ManagedResearchFailureFamily.UNKNOWN else None,
141
+ raw={str(key): value for key, value in payload.items()},
142
+ )
143
+
144
+ def to_wire(self) -> dict[str, Any]:
145
+ return {
146
+ key: value
147
+ for key, value in {
148
+ **self.raw,
149
+ "family": self.family.value,
150
+ "code": self.code,
151
+ "severity": self.severity.value,
152
+ "retryable": self.retryable,
153
+ "scope": self.scope.value if self.scope is not None else None,
154
+ "operator_action": self.operator_action,
155
+ "detail": self.detail,
156
+ "actor_id": self.actor_id,
157
+ "actor_key": self.actor_key,
158
+ "task_id": self.task_id,
159
+ "task_key": self.task_key,
160
+ "recorded_at": self.recorded_at,
161
+ "family_raw": self.family_raw,
162
+ }.items()
163
+ if value is not None
164
+ }
165
+
166
+
167
+ __all__ = [
168
+ "ActorFailureReason",
169
+ "ManagedResearchFailureClassification",
170
+ "ManagedResearchFailureFamily",
171
+ "ManagedResearchFailureScope",
172
+ "ManagedResearchFailureSeverity",
173
+ ]
@@ -697,11 +697,13 @@ class ActorRuntimeImageMaterialization:
697
697
  object.__setattr__(
698
698
  self, "daytona_pullable", required_bool({"value": self.daytona_pullable}, "value")
699
699
  )
700
- expected = (
701
- ("org_registry", "wasabi_artifact") if self.daytona_pullable else ("wasabi_artifact",)
700
+ allowed = (
701
+ (("org_registry",), ("org_registry", "wasabi_artifact"))
702
+ if self.daytona_pullable
703
+ else (("wasabi_artifact",),)
702
704
  )
703
- if self.image_substrates != expected:
704
- raise ValueError("image_substrates must exactly describe the admitted execution path")
705
+ if self.image_substrates not in allowed:
706
+ raise ValueError("image_substrates must exactly describe the admitted execution paths")
705
707
 
706
708
  @classmethod
707
709
  def from_wire(cls, value: JsonValue) -> ActorRuntimeImageMaterialization:
@@ -1169,6 +1171,63 @@ class ImageReleaseFinalize:
1169
1171
  }
1170
1172
 
1171
1173
 
1174
+ @dataclass(frozen=True, slots=True)
1175
+ class RegistryActorRuntimeImageRegistrationRequest:
1176
+ declaration: ActorRuntimeImageReleaseDeclaration
1177
+ image_config_digest: str
1178
+ package_release_timestamps: TimestampMap = field(default_factory=dict)
1179
+
1180
+ def __post_init__(self) -> None:
1181
+ if not isinstance(self.declaration, ActorRuntimeImageReleaseDeclaration):
1182
+ raise ValueError("declaration must be ActorRuntimeImageReleaseDeclaration")
1183
+ object.__setattr__(
1184
+ self,
1185
+ "image_config_digest",
1186
+ digest(self.image_config_digest, field="image_config_digest"),
1187
+ )
1188
+ object.__setattr__(
1189
+ self,
1190
+ "package_release_timestamps",
1191
+ _timestamp_map(self.package_release_timestamps),
1192
+ )
1193
+ _check_packages(self.declaration, self.package_release_timestamps)
1194
+
1195
+ def to_wire(self) -> JsonObject:
1196
+ return {
1197
+ "declaration": self.declaration.to_wire(),
1198
+ "image_config_digest": self.image_config_digest,
1199
+ "package_release_timestamps": _timestamp_wire(self.package_release_timestamps),
1200
+ }
1201
+
1202
+
1203
+ @dataclass(frozen=True, slots=True)
1204
+ class RegistryActorRuntimeImageRegistration:
1205
+ schema_version: str
1206
+ runtime_image_release: ActorRuntimeImageMaterialization
1207
+
1208
+ @classmethod
1209
+ def from_wire(cls, value: JsonValue) -> RegistryActorRuntimeImageRegistration:
1210
+ payload = _obj(
1211
+ value,
1212
+ "registry actor runtime image registration",
1213
+ frozenset({"schema_version", "runtime_image_release"}),
1214
+ )
1215
+ return cls(
1216
+ _const(
1217
+ payload["schema_version"],
1218
+ "schema_version",
1219
+ "smr-actor-image-registry-registration-v1",
1220
+ ),
1221
+ ActorRuntimeImageMaterialization.from_wire(payload["runtime_image_release"]),
1222
+ )
1223
+
1224
+ def to_wire(self) -> JsonObject:
1225
+ return {
1226
+ "schema_version": self.schema_version,
1227
+ "runtime_image_release": self.runtime_image_release.to_wire(),
1228
+ }
1229
+
1230
+
1172
1231
  @dataclass(frozen=True, slots=True)
1173
1232
  class ActorRuntimeImageReleaseList:
1174
1233
  schema_version: str
@@ -1229,6 +1288,8 @@ __all__ = [
1229
1288
  "ActorRuntimeImageReleaseArchive",
1230
1289
  "ActorRuntimeImageReleaseDeclaration",
1231
1290
  "ActorRuntimeImageReleaseList",
1291
+ "RegistryActorRuntimeImageRegistration",
1292
+ "RegistryActorRuntimeImageRegistrationRequest",
1232
1293
  "ActorImageCapability",
1233
1294
  "CraftaxScorerImageRelease",
1234
1295
  "CraftaxScorerImageReleaseDeclaration",
@@ -6,6 +6,7 @@ from collections.abc import Mapping
6
6
  from dataclasses import dataclass, field
7
7
  from enum import StrEnum
8
8
 
9
+ from synth_ai.sdk.research.contracts.failure import ManagedResearchFailureClassification
9
10
  from synth_ai.sdk.research.contracts.run_state import (
10
11
  ManagedResearchRun,
11
12
  ManagedResearchRunLivenessPhase,
@@ -1307,7 +1308,7 @@ class ManagedResearchRunContractIncidents:
1307
1308
  class ManagedResearchRunContractDiagnostics:
1308
1309
  lifecycle_invariants: list[dict[str, object]] = field(default_factory=list)
1309
1310
  resource_wait: dict[str, object] | None = None
1310
- failure_classification: dict[str, object] | None = None
1311
+ failure_classification: ManagedResearchFailureClassification | None = None
1311
1312
 
1312
1313
  @classmethod
1313
1314
  def from_wire(cls, payload: object) -> ManagedResearchRunContractDiagnostics:
@@ -1327,10 +1328,12 @@ class ManagedResearchRunContractDiagnostics:
1327
1328
  )
1328
1329
  if resource_wait is not None
1329
1330
  else None,
1330
- failure_classification=dict(
1331
- _require_mapping(
1332
- failure_classification,
1333
- label="run_contract.diagnostics.failure_classification",
1331
+ failure_classification=ManagedResearchFailureClassification.from_wire(
1332
+ dict(
1333
+ _require_mapping(
1334
+ failure_classification,
1335
+ label="run_contract.diagnostics.failure_classification",
1336
+ )
1334
1337
  )
1335
1338
  )
1336
1339
  if failure_classification is not None
@@ -1509,6 +1512,7 @@ __all__ = [
1509
1512
  "ManagedResearchRunContractArtifacts",
1510
1513
  "ManagedResearchRunContractContainerEvalPackages",
1511
1514
  "ManagedResearchRunContractDiagnostics",
1515
+ "ManagedResearchFailureClassification",
1512
1516
  "ManagedResearchRunContractExecutionRoute",
1513
1517
  "ManagedResearchRunContractFinalization",
1514
1518
  "ManagedResearchRunContractIncidents",
@@ -24,6 +24,8 @@ from synth_ai.sdk.research.contracts.image_releases import (
24
24
  ImageReleaseId,
25
25
  ImageReleaseUpload,
26
26
  ImageReleaseUploadRequest,
27
+ RegistryActorRuntimeImageRegistration,
28
+ RegistryActorRuntimeImageRegistrationRequest,
27
29
  RuntimeImageReleaseId,
28
30
  image_release_from_wire,
29
31
  )
@@ -165,6 +167,29 @@ class ImageReleasesAPI:
165
167
  )
166
168
  return _finalize(value, request=request)
167
169
 
170
+ def register_registry_image(
171
+ self,
172
+ request: RegistryActorRuntimeImageRegistrationRequest,
173
+ ) -> RegistryActorRuntimeImageRegistration:
174
+ """Register an org-scoped digest already published to the Synth registry."""
175
+
176
+ if not isinstance(request, RegistryActorRuntimeImageRegistrationRequest):
177
+ raise ValueError("request must be RegistryActorRuntimeImageRegistrationRequest")
178
+ value = self._transport.execute(
179
+ _request(
180
+ "register_customer_actor_registry_image",
181
+ "/smr/v1/image-releases/register-registry",
182
+ body=request.to_wire(),
183
+ )
184
+ )
185
+ result = RegistryActorRuntimeImageRegistration.from_wire(cast(JsonValue, value))
186
+ if (
187
+ result.runtime_image_release.resolved_digest
188
+ != request.declaration.image_manifest_digest
189
+ ):
190
+ raise ValueError("registry image response changed its manifest digest")
191
+ return result
192
+
168
193
  def upload_archive(
169
194
  self,
170
195
  archive_path: str | Path,
@@ -284,6 +309,29 @@ class AsyncImageReleasesAPI:
284
309
  )
285
310
  return _finalize(value, request=request)
286
311
 
312
+ async def register_registry_image(
313
+ self,
314
+ request: RegistryActorRuntimeImageRegistrationRequest,
315
+ ) -> RegistryActorRuntimeImageRegistration:
316
+ """Register an org-scoped digest already published to the Synth registry."""
317
+
318
+ if not isinstance(request, RegistryActorRuntimeImageRegistrationRequest):
319
+ raise ValueError("request must be RegistryActorRuntimeImageRegistrationRequest")
320
+ value = await self._transport.execute(
321
+ _request(
322
+ "register_customer_actor_registry_image",
323
+ "/smr/v1/image-releases/register-registry",
324
+ body=request.to_wire(),
325
+ )
326
+ )
327
+ result = RegistryActorRuntimeImageRegistration.from_wire(cast(JsonValue, value))
328
+ if (
329
+ result.runtime_image_release.resolved_digest
330
+ != request.declaration.image_manifest_digest
331
+ ):
332
+ raise ValueError("registry image response changed its manifest digest")
333
+ return result
334
+
287
335
  async def upload_archive(
288
336
  self,
289
337
  archive_path: str | Path,
@@ -50,6 +50,13 @@ RESEARCH_OPERATIONS = {
50
50
  "/smr/v1/image-releases/upload-url",
51
51
  mutation=True,
52
52
  ),
53
+ _operation(
54
+ "register_customer_actor_registry_image",
55
+ HttpMethod.POST,
56
+ "/smr/v1/image-releases/register-registry",
57
+ mutation=True,
58
+ idempotent=True,
59
+ ),
53
60
  _operation("create_factory", HttpMethod.POST, "/smr/factories", mutation=True),
54
61
  _operation(
55
62
  "provision_research_intern",
@@ -43,6 +43,7 @@ from synth_ai.sdk.research.contracts import (
43
43
  ActivityWindow,
44
44
  ActivityWindowReceipt,
45
45
  ActivityWorkProduct,
46
+ ActorFailureReason,
46
47
  ActorHarness,
47
48
  ActorId,
48
49
  ActorImageBinding,
@@ -153,6 +154,10 @@ from synth_ai.sdk.research.contracts import (
153
154
  MagiDecisionReceiptResponse,
154
155
  MagiDecisionRequest,
155
156
  MagiMode,
157
+ ManagedResearchFailureClassification,
158
+ ManagedResearchFailureFamily,
159
+ ManagedResearchFailureScope,
160
+ ManagedResearchFailureSeverity,
156
161
  MessageId,
157
162
  OpenEndedQuestionSpec,
158
163
  ParticipantSessionId,
@@ -197,6 +202,8 @@ from synth_ai.sdk.research.contracts import (
197
202
  ProjectWorkspaceInputs,
198
203
  ProviderBinding,
199
204
  ProviderPolicy,
205
+ RegistryActorRuntimeImageRegistration,
206
+ RegistryActorRuntimeImageRegistrationRequest,
200
207
  ResearchInternFactoryMembershipResponse,
201
208
  ResearchInternPatchRequest,
202
209
  ResearchInternPolicySet,
@@ -394,6 +401,7 @@ __all__ = [
394
401
  "ActivityWindow",
395
402
  "ActivityWindowReceipt",
396
403
  "ActivityWorkProduct",
404
+ "ActorFailureReason",
397
405
  "ActiveActorModel",
398
406
  "ActorId",
399
407
  "ActorRuntimeImageMaterialization",
@@ -401,12 +409,18 @@ __all__ = [
401
409
  "ActorRuntimeImageReleaseArchive",
402
410
  "ActorRuntimeImageReleaseDeclaration",
403
411
  "ActorRuntimeImageReleaseList",
412
+ "RegistryActorRuntimeImageRegistration",
413
+ "RegistryActorRuntimeImageRegistrationRequest",
404
414
  "ArtifactId",
405
415
  "ActorHarness",
406
416
  "ActorModel",
407
417
  "ActorTokenUsage",
408
418
  "ActorUsage",
409
419
  "ActorUsageMoney",
420
+ "ManagedResearchFailureClassification",
421
+ "ManagedResearchFailureFamily",
422
+ "ManagedResearchFailureScope",
423
+ "ManagedResearchFailureSeverity",
410
424
  "AsyncClient",
411
425
  "AsyncVisualsAPI",
412
426
  "Branch",
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import time
6
6
  from collections.abc import Mapping
7
7
  from dataclasses import dataclass
8
- from typing import Any, List, cast
8
+ from typing import Any, List
9
9
 
10
10
  import httpx
11
11
 
@@ -313,20 +313,15 @@ class RunHandle:
313
313
  if contract.terminal:
314
314
  if raise_if_failed and contract.public_state.value in {"failed", "blocked"}:
315
315
  failure = contract.diagnostics.failure_classification
316
- if (
317
- isinstance(failure, Mapping)
318
- and str(failure.get("code") or "").strip()
319
- == "inference_provider_unavailable"
320
- ):
321
- detail = dict(failure)
322
- message = str(detail.get("detail") or "").strip() or (
316
+ if failure is not None and failure.code == "inference_provider_unavailable":
317
+ message = str(failure.detail or "").strip() or (
323
318
  f"run {self.run_id} ended because its inference provider "
324
319
  "was temporarily unavailable"
325
320
  )
326
321
  raise ResearchInferenceProviderUnavailableError(
327
322
  message,
328
323
  status_code=None,
329
- detail=detail,
324
+ detail=failure.to_wire(),
330
325
  )
331
326
  msg = self.explain_blocker() or (
332
327
  f"run {self.run_id} ended in state {contract.public_state.value}"
@@ -1771,10 +1766,10 @@ class RunsAPI(_ClientNamespace):
1771
1766
  return detail or code or "run lifecycle invariant failed"
1772
1767
  failure = contract.diagnostics.failure_classification
1773
1768
  if failure is not None:
1774
- code = str(failure.get("code") or "").strip()
1775
- detail = str(failure.get("detail") or "").strip()
1776
- route = failure.get("route")
1777
- route_mapping = cast(Mapping[str, Any], route) if isinstance(route, Mapping) else {}
1769
+ code = failure.code.strip()
1770
+ detail = str(failure.detail or "").strip()
1771
+ route = failure.to_wire().get("route")
1772
+ route_mapping = route if isinstance(route, Mapping) else {}
1778
1773
  model = str(route_mapping.get("model") or "").strip()
1779
1774
  suffix = f" model={model}" if model else ""
1780
1775
  if detail:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synth-ai
3
- Version: 0.18.1.dev594
3
+ Version: 0.18.1.dev596
4
4
  Summary: Python SDK and CLI for Synth Managed Research and Research Factory
5
5
  Author-email: Synth AI <josh@usesynth.ai>
6
6
  License-Expression: MIT
@@ -143,6 +143,7 @@ synth_ai/sdk/research/contracts/factory_evidence.py
143
143
  synth_ai/sdk/research/contracts/factory_lenses.py
144
144
  synth_ai/sdk/research/contracts/factory_operations.py
145
145
  synth_ai/sdk/research/contracts/factory_role_receipts.py
146
+ synth_ai/sdk/research/contracts/failure.py
146
147
  synth_ai/sdk/research/contracts/image_releases.py
147
148
  synth_ai/sdk/research/contracts/local_execution_profile.py
148
149
  synth_ai/sdk/research/contracts/operator_evidence.py