mainsequence 6.0.26__tar.gz → 6.0.27__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 (126) hide show
  1. {mainsequence-6.0.26/mainsequence.egg-info → mainsequence-6.0.27}/PKG-INFO +1 -1
  2. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/cli.py +0 -1
  3. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/agent_runtime_models.py +37 -14
  4. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/models_helpers.py +31 -15
  5. {mainsequence-6.0.26 → mainsequence-6.0.27/mainsequence.egg-info}/PKG-INFO +1 -1
  6. {mainsequence-6.0.26 → mainsequence-6.0.27}/pyproject.toml +1 -1
  7. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_cli.py +8 -7
  8. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_filter_normalization.py +124 -25
  9. {mainsequence-6.0.26 → mainsequence-6.0.27}/LICENSE +0 -0
  10. {mainsequence-6.0.26 → mainsequence-6.0.27}/README.md +0 -0
  11. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/AGENTS.md +0 -0
  12. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  13. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  14. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  15. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  16. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  17. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  18. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  19. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
  20. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  21. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  22. {mainsequence-6.0.26 → mainsequence-6.0.27}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
  23. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/__init__.py +0 -0
  24. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/__main__.py +0 -0
  25. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/bootstrap.py +0 -0
  26. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/__init__.py +0 -0
  27. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/api.py +0 -0
  28. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/browser_auth.py +0 -0
  29. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/config.py +0 -0
  30. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/docker_utils.py +0 -0
  31. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/doctor.py +0 -0
  32. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/local_ops.py +0 -0
  33. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/migrations.py +0 -0
  34. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/model_filters.py +0 -0
  35. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/project_status.py +0 -0
  36. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/pydantic_cli.py +0 -0
  37. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/sdk_utils.py +0 -0
  38. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/ssh_utils.py +0 -0
  39. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/cli/ui.py +0 -0
  40. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/__init__.py +0 -0
  41. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/base.py +0 -0
  42. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/client.py +0 -0
  43. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/compute_validation.py +0 -0
  44. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  45. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  46. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  47. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  48. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/dtype_codec.py +0 -0
  49. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/exceptions.py +0 -0
  50. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/fastapi/__init__.py +0 -0
  51. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/fastapi/auth.py +0 -0
  52. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/metatables/__init__.py +0 -0
  53. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/metatables/core.py +0 -0
  54. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/models_foundry.py +0 -0
  55. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/models_user.py +0 -0
  56. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/client/utils.py +0 -0
  57. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/defaults.py +0 -0
  58. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/instrumentation/__init__.py +0 -0
  59. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/instrumentation/utils.py +0 -0
  60. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/logconf.py +0 -0
  61. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/__init__.py +0 -0
  62. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/__main__.py +0 -0
  63. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  64. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  65. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  66. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  67. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
  68. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  69. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  70. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
  71. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  72. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  73. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/future_registry.py +0 -0
  74. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/hashing.py +0 -0
  75. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  76. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  77. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/env.py +0 -0
  78. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/provider.py +0 -0
  79. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/registry.py +0 -0
  80. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  81. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  82. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  83. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  84. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  85. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/schema_names.py +0 -0
  86. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  87. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/project_skills.py +0 -0
  88. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/runtime_context.py +0 -0
  89. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/runtime_flags.py +0 -0
  90. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence/scaffold_skills.py +0 -0
  91. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence.egg-info/SOURCES.txt +0 -0
  92. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence.egg-info/dependency_links.txt +0 -0
  93. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence.egg-info/entry_points.txt +0 -0
  94. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence.egg-info/requires.txt +0 -0
  95. {mainsequence-6.0.26 → mainsequence-6.0.27}/mainsequence.egg-info/top_level.txt +0 -0
  96. {mainsequence-6.0.26 → mainsequence-6.0.27}/setup.cfg +0 -0
  97. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_auth_precedence.py +0 -0
  98. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_build_operations_hashing.py +0 -0
  99. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_canonical_api_route_contract.py +0 -0
  100. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_cli_browser_auth.py +0 -0
  101. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_cli_migrations.py +0 -0
  102. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_client.py +0 -0
  103. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  104. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_data_node_storage_dimension_queries.py +0 -0
  105. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_data_node_update_flow.py +0 -0
  106. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_dependency_extras.py +0 -0
  107. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_duckdb_interface_dimensions.py +0 -0
  108. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_instrumentation.py +0 -0
  109. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_logconf.py +0 -0
  110. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_meta_table_migrations.py +0 -0
  111. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_meta_tables_client_models.py +0 -0
  112. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  113. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_models_user_request_bound_auth.py +0 -0
  114. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_pod_project_resolution.py +0 -0
  115. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_project_batch_jobs_from_file.py +0 -0
  116. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_project_branch_contract.py +0 -0
  117. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_project_skills.py +0 -0
  118. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_run_configuration.py +0 -0
  119. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_scaffold_skills.py +0 -0
  120. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_schema_names.py +0 -0
  121. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_secret_client_model.py +0 -0
  122. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_source_table_configuration.py +0 -0
  123. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_sqlite_interface_dimensions.py +0 -0
  124. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_update_runner_uid_runtime.py +0 -0
  125. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_update_statistics.py +0 -0
  126. {mainsequence-6.0.26 → mainsequence-6.0.27}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 6.0.26
3
+ Version: 6.0.27
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -1496,7 +1496,6 @@ def _format_resource_release_delete_preview(release: dict[str, object]) -> list[
1496
1496
  return [
1497
1497
  ("UID", str(release.get("uid") or "-")),
1498
1498
  ("Release Kind", str(release.get("release_kind") or "-")),
1499
- ("Subdomain", str(release.get("subdomain") or "-")),
1500
1499
  ("Resource", str(release.get("resource") or "-")),
1501
1500
  ("Related Image", _format_related_image_label(release.get("related_image"))),
1502
1501
  ]
@@ -143,24 +143,23 @@ class AgentRuntimePaths(BasePydanticModel):
143
143
  class AgentSessionRuntimeAccess(BasePydanticModel):
144
144
  model_config = ConfigDict(extra="allow")
145
145
 
146
- coding_agent_service_id: str | None = Field(
146
+ coding_agent_service_uid: str | None = Field(
147
147
  None,
148
- description="Identifier of the backing coding-agent service that owns the runtime.",
148
+ description="Canonical public UID of the coding-agent service that owns the runtime.",
149
149
  )
150
- coding_agent_id: str | None = Field(
151
- None,
152
- description="Stable coding-agent routing identifier presented to the gateway.",
153
- )
154
- mode: str = Field(
150
+ mode: Literal["token", "unavailable"] = Field(
155
151
  "token",
156
- description="Runtime access mode. Currently only token-based gateway access is supported.",
152
+ description="Runtime access mode returned by the backend.",
157
153
  )
158
- rpc_url: str = Field(
159
- ...,
160
- description="Gateway RPC URL that the caller should use to reach the coding-agent runtime.",
154
+ rpc_url: str | None = Field(
155
+ None,
156
+ description=(
157
+ "Opaque, server-issued gateway RPC URL for the coding-agent runtime. "
158
+ "Callers must not derive it from tenancy, names, numeric IDs, or subdomains."
159
+ ),
161
160
  )
162
- token: str = Field(
163
- ...,
161
+ token: str | None = Field(
162
+ None,
164
163
  description="Bearer token that authorizes calls to the coding-agent gateway.",
165
164
  )
166
165
  expires_at: str | None = Field(
@@ -175,6 +174,14 @@ class AgentSessionRuntimeAccess(BasePydanticModel):
175
174
  None,
176
175
  description="Backend readiness metadata returned by runtime access resolution.",
177
176
  )
177
+ reconciliation: dict[str, Any] | None = Field(
178
+ None,
179
+ description="Backend reconciliation metadata when runtime access is unavailable or stale.",
180
+ )
181
+ detail: str | None = Field(
182
+ None,
183
+ description="Human-readable runtime access detail returned by the backend.",
184
+ )
178
185
  runtime_paths: AgentRuntimePaths = Field(
179
186
  default_factory=AgentRuntimePaths,
180
187
  description="Runtime-relative paths returned by the control plane.",
@@ -292,6 +299,14 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
292
299
  None,
293
300
  description="Service-level automatic deployment flag for the resolved typed coding-agent service.",
294
301
  )
302
+ project_branch_uid: str | None = Field(
303
+ None,
304
+ description=(
305
+ "Public UID of the canonical ProjectBranch attached through the "
306
+ "typed Project Executor service, or null when the agent is not "
307
+ "ProjectBranch-scoped."
308
+ ),
309
+ )
295
310
 
296
311
  @classmethod
297
312
  def semantic_search(
@@ -973,10 +988,18 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
973
988
  body: dict[str, Any],
974
989
  timeout=None,
975
990
  ) -> requests.Response:
991
+ if access.mode != "token":
992
+ detail = str(access.detail or "").strip()
993
+ message = "Coding-agent runtime access is unavailable."
994
+ if detail:
995
+ message = f"{message} {detail}"
996
+ raise ApiError(message)
997
+ if not isinstance(access.token, str) or not access.token.strip():
998
+ raise ApiError("Runtime access response is missing token.")
976
999
  url = _join_runtime_url(access.rpc_url, STANDARD_A2A_MESSAGE_SEND_PATH)
977
1000
  request_timeout = DEFAULT_AGENT_SESSION_LONG_REQUEST_TIMEOUT if timeout is None else timeout
978
1001
  headers = {
979
- "Authorization": f"Bearer {access.token}",
1002
+ "Authorization": f"Bearer {access.token.strip()}",
980
1003
  "Content-Type": STANDARD_A2A_CONTENT_TYPE,
981
1004
  "Accept": STANDARD_A2A_CONTENT_TYPE,
982
1005
  }
@@ -1003,11 +1003,6 @@ class ResourceRelease(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
1003
1003
  description="Public UID of the resource release.",
1004
1004
  examples=["0ce33c15-e3b1-4677-a66e-70460b89198f"],
1005
1005
  )
1006
- subdomain: str = Field(
1007
- title="Subdomain",
1008
- description="DNS-safe label used as the subdomain for this release.",
1009
- examples=["analytics-123"],
1010
- )
1011
1006
  project_branch_uid: str | None = Field(
1012
1007
  None,
1013
1008
  title="ProjectBranch UID",
@@ -1204,20 +1199,42 @@ class DeploymentRunError(BaseModel):
1204
1199
 
1205
1200
  class DeploymentRunStep(BaseModel):
1206
1201
  uid: str
1207
- sequence: int
1202
+ sequence: PositiveInt
1208
1203
  key: str
1209
1204
  name: str = ""
1210
- kind: str
1211
- state: str
1212
- phase: str = ""
1205
+ kind: Literal[
1206
+ "source",
1207
+ "image_build",
1208
+ "validation",
1209
+ "runtime_deploy",
1210
+ "runtime_readiness",
1211
+ "publish",
1212
+ "cleanup",
1213
+ "orchestration",
1214
+ ]
1215
+ required: bool = True
1216
+ state: Literal[
1217
+ "pending",
1218
+ "running",
1219
+ "succeeded",
1220
+ "failed",
1221
+ "cancelled",
1222
+ "skipped",
1223
+ "blocked",
1224
+ "superseded",
1225
+ ]
1213
1226
  outcome: str = ""
1214
- provider: str = ""
1215
- external_operation_id: str = ""
1216
1227
  artifact_context: dict[str, Any] = Field(default_factory=dict)
1217
1228
  started_at: datetime.datetime | None = None
1218
1229
  finished_at: datetime.datetime | None = None
1219
- error_code: str = ""
1220
- error_detail: str = ""
1230
+ error: DeploymentRunError | None = None
1231
+
1232
+
1233
+ class DeploymentRunPipeline(BaseModel):
1234
+ key: str
1235
+ version: PositiveInt
1236
+ current_step_key: str | None = None
1237
+ steps: list[DeploymentRunStep] = Field(default_factory=list)
1221
1238
 
1222
1239
 
1223
1240
  class DeploymentRunLogEntry(BaseModel):
@@ -1282,8 +1299,8 @@ class DeploymentRun(BaseObjectOrm, BasePydanticModel):
1282
1299
  commit_sha: str = ""
1283
1300
  configuration_revision: int | None = None
1284
1301
  state: str
1285
- phase: str = ""
1286
1302
  outcome: str = ""
1303
+ pipeline: DeploymentRunPipeline
1287
1304
  created_at: datetime.datetime
1288
1305
  started_at: datetime.datetime | None = None
1289
1306
  finished_at: datetime.datetime | None = None
@@ -1294,7 +1311,6 @@ class DeploymentRun(BaseObjectOrm, BasePydanticModel):
1294
1311
  result: dict[str, Any] = Field(default_factory=dict)
1295
1312
  builder_image: str = ""
1296
1313
  builder_runtime: str = ""
1297
- steps: list[DeploymentRunStep] = Field(default_factory=list)
1298
1314
  logs: DeploymentRunLogReference
1299
1315
  error: DeploymentRunError | None = None
1300
1316
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 6.0.26
3
+ Version: 6.0.27
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "6.0.26"
7
+ version = "6.0.27"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -933,7 +933,9 @@ def test_send_agent_session_a2a_message_uses_client_model(cli_mod, monkeypatch):
933
933
  api_mod,
934
934
  "get_runtime_access_cache",
935
935
  lambda agent_session_uid: {
936
- "rpc_url": "https://runtime.main-sequence.app/rpc",
936
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
937
+ "mode": "token",
938
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
937
939
  "token": "tok-secret",
938
940
  },
939
941
  )
@@ -1000,7 +1002,9 @@ def test_send_agent_session_a2a_message_uses_client_model(cli_mod, monkeypatch):
1000
1002
  assert captured["cached_runtime_access"] == {
1001
1003
  "agent_session": session_uid,
1002
1004
  "runtime_access": {
1003
- "rpc_url": "https://runtime.main-sequence.app/rpc",
1005
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
1006
+ "mode": "token",
1007
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
1004
1008
  "token": "tok-secret",
1005
1009
  },
1006
1010
  }
@@ -4398,7 +4402,6 @@ def test_delete_resource_release_uses_client_model(cli_mod, monkeypatch):
4398
4402
  return {
4399
4403
  "uid": pk,
4400
4404
  "release_kind": "streamlit_dashboard",
4401
- "subdomain": "analytics-123",
4402
4405
  "resource": 381,
4403
4406
  "related_image": 94,
4404
4407
  }
@@ -6203,7 +6206,6 @@ def test_project_project_resource_delete_dashboard_requires_confirmation(
6203
6206
  lambda release_uid, expected_release_kind=None, timeout=None: {
6204
6207
  "uid": release_uid,
6205
6208
  "release_kind": expected_release_kind,
6206
- "subdomain": "analytics-123",
6207
6209
  "resource": 381,
6208
6210
  "related_image": 94,
6209
6211
  },
@@ -6215,7 +6217,6 @@ def test_project_project_resource_delete_dashboard_requires_confirmation(
6215
6217
  return {
6216
6218
  "uid": release_uid,
6217
6219
  "release_kind": expected_release_kind,
6218
- "subdomain": "analytics-123",
6219
6220
  "resource": 381,
6220
6221
  "related_image": 94,
6221
6222
  }
@@ -6231,6 +6232,7 @@ def test_project_project_resource_delete_dashboard_requires_confirmation(
6231
6232
  assert captured["release_uid"] == release_uid
6232
6233
  assert captured["expected_release_kind"] == "streamlit_dashboard"
6233
6234
  assert "Project Resource Release Delete Preview" in result.output
6235
+ assert "Subdomain" not in result.output
6234
6236
  assert f"Delete dashboard release {release_uid}?" in result.output
6235
6237
  assert f"Project resource release deleted: uid={release_uid}" in result.output
6236
6238
 
@@ -6248,7 +6250,6 @@ def test_project_project_resource_delete_fastapi_requires_confirmation(
6248
6250
  lambda release_uid, expected_release_kind=None, timeout=None: {
6249
6251
  "uid": release_uid,
6250
6252
  "release_kind": expected_release_kind,
6251
- "subdomain": "api-123",
6252
6253
  "resource": 382,
6253
6254
  "related_image": 94,
6254
6255
  },
@@ -6260,7 +6261,6 @@ def test_project_project_resource_delete_fastapi_requires_confirmation(
6260
6261
  return {
6261
6262
  "uid": release_uid,
6262
6263
  "release_kind": expected_release_kind,
6263
- "subdomain": "api-123",
6264
6264
  "resource": 382,
6265
6265
  "related_image": 94,
6266
6266
  }
@@ -6275,6 +6275,7 @@ def test_project_project_resource_delete_fastapi_requires_confirmation(
6275
6275
  assert result.exit_code == 0
6276
6276
  assert captured["release_uid"] == release_uid
6277
6277
  assert captured["expected_release_kind"] == "fastapi"
6278
+ assert "Subdomain" not in result.output
6278
6279
  assert f"Delete FastAPI release {release_uid}?" in result.output
6279
6280
  assert f"Project resource release deleted: uid={release_uid}" in result.output
6280
6281
 
@@ -1647,6 +1647,7 @@ def test_agent_runtime_models_deserialize_backend_uid_payloads():
1647
1647
  session_uid = "3f1cc452-43ec-49cb-b2ba-87dbac164d29"
1648
1648
  user_uid = "fdf409f7-d16f-4f71-986b-9057db6c7eca"
1649
1649
  service_uid = "ac9e221d-1cd6-464c-a253-e302754872c1"
1650
+ project_branch_uid = "9d81d63f-b8c9-404d-9f1a-5f2ad29dbf16"
1650
1651
 
1651
1652
  agent = agent_models_mod.Agent.model_validate(
1652
1653
  {
@@ -1664,12 +1665,14 @@ def test_agent_runtime_models_deserialize_backend_uid_payloads():
1664
1665
  "has_agent_service": True,
1665
1666
  "agent_service_uid": service_uid,
1666
1667
  "agent_service_automatic_deployment": True,
1668
+ "project_branch_uid": project_branch_uid,
1667
1669
  }
1668
1670
  )
1669
1671
  assert agent.uid == agent_uid
1670
1672
  assert agent.has_agent_service is True
1671
1673
  assert agent.agent_service_uid == service_uid
1672
1674
  assert agent.agent_service_automatic_deployment is True
1675
+ assert agent.project_branch_uid == project_branch_uid
1673
1676
 
1674
1677
  search_result = agent_models_mod.AgentSemanticSearchResult.model_validate(
1675
1678
  {
@@ -2024,7 +2027,6 @@ def test_resource_release_model_accepts_collection_payload_without_runtime_child
2024
2027
  release = models_helpers_mod.ResourceRelease.model_validate(
2025
2028
  {
2026
2029
  "uid": release_uid,
2027
- "subdomain": "competition-analysis-dc3697f1f1",
2028
2030
  "project_branch_uid": project_branch_uid,
2029
2031
  "name": "Competition Analysis",
2030
2032
  "release_kind": "static_site",
@@ -2039,6 +2041,7 @@ def test_resource_release_model_accepts_collection_payload_without_runtime_child
2039
2041
  assert release.resource_uid is None
2040
2042
  assert release.readme_resource_uid is None
2041
2043
  assert release.related_job_uid is None
2044
+ assert "subdomain" not in models_helpers_mod.ResourceRelease.model_fields
2042
2045
 
2043
2046
 
2044
2047
  def test_resource_release_model_supports_automatic_deployment_payloads():
@@ -2049,7 +2052,6 @@ def test_resource_release_model_supports_automatic_deployment_payloads():
2049
2052
  release = models_helpers_mod.ResourceRelease.model_validate(
2050
2053
  {
2051
2054
  "uid": release_uid,
2052
- "subdomain": "analytics-123",
2053
2055
  "resource_uid": resource_uid,
2054
2056
  "readme_resource_uid": None,
2055
2057
  "related_job_uid": job_uid,
@@ -2094,7 +2096,6 @@ def test_resource_release_create_sends_automatic_deployment(monkeypatch):
2094
2096
  def json():
2095
2097
  return {
2096
2098
  "uid": release_uid,
2097
- "subdomain": "analytics-123",
2098
2099
  "resource_uid": resource_uid,
2099
2100
  "readme_resource_uid": None,
2100
2101
  "related_job_uid": "7d0ab07c-d1c0-4b7f-9c69-3c1a41c0a4da",
@@ -2156,7 +2157,6 @@ def test_project_resource_create_release_uses_related_image_uid(monkeypatch):
2156
2157
  def json():
2157
2158
  return {
2158
2159
  "uid": release_uid,
2159
- "subdomain": "analytics-123",
2160
2160
  "resource_uid": resource_uid,
2161
2161
  "readme_resource_uid": None,
2162
2162
  "related_job_uid": "7d0ab07c-d1c0-4b7f-9c69-3c1a41c0a4da",
@@ -2187,13 +2187,57 @@ def test_project_resource_create_release_uses_related_image_uid(monkeypatch):
2187
2187
  assert captured["timeout"] == 7
2188
2188
 
2189
2189
 
2190
+ def _resource_release_pipeline_payload(*, running_step: str | None = None):
2191
+ keys = (
2192
+ "resolve_revision",
2193
+ "validate_deployment",
2194
+ "resolve_resource",
2195
+ "build_project_image",
2196
+ "deploy_runtime",
2197
+ "verify_runtime_readiness",
2198
+ )
2199
+ current_index = keys.index(running_step) if running_step else None
2200
+ steps = []
2201
+ for index, key in enumerate(keys, start=1):
2202
+ if current_index is None or index - 1 < current_index:
2203
+ step_state = "succeeded"
2204
+ outcome = "completed"
2205
+ elif index - 1 == current_index:
2206
+ step_state = "running"
2207
+ outcome = ""
2208
+ else:
2209
+ step_state = "pending"
2210
+ outcome = ""
2211
+ steps.append(
2212
+ {
2213
+ "uid": f"00000000-0000-4000-8000-{index:012d}",
2214
+ "sequence": index,
2215
+ "key": key,
2216
+ "name": key.replace("_", " ").title(),
2217
+ "kind": "orchestration",
2218
+ "required": True,
2219
+ "state": step_state,
2220
+ "outcome": outcome,
2221
+ "artifact_context": {},
2222
+ "started_at": None,
2223
+ "finished_at": None,
2224
+ "error": None,
2225
+ }
2226
+ )
2227
+ return {
2228
+ "key": "resource_release.fastapi.build_and_deploy",
2229
+ "version": 1,
2230
+ "current_step_key": running_step,
2231
+ "steps": steps,
2232
+ }
2233
+
2234
+
2190
2235
  def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch):
2191
2236
  captured = {}
2192
2237
  release_uid = "2f4c4c3d-5669-4da5-9d86-b84633c1e6ed"
2193
2238
  run_uid = "11111111-1111-4111-8111-111111111111"
2194
2239
  release = models_helpers_mod.ResourceRelease(
2195
2240
  uid=release_uid,
2196
- subdomain="analytics-123",
2197
2241
  release_kind="fastapi",
2198
2242
  automatic_deployment=True,
2199
2243
  )
@@ -2214,8 +2258,8 @@ def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch
2214
2258
  "commit_sha": "a" * 40,
2215
2259
  "configuration_revision": 4,
2216
2260
  "state": "succeeded",
2217
- "phase": "completed",
2218
2261
  "outcome": "deployed",
2262
+ "pipeline": _resource_release_pipeline_payload(),
2219
2263
  "created_at": "2026-07-19T12:00:00Z",
2220
2264
  "started_at": "2026-07-19T12:00:01Z",
2221
2265
  "finished_at": "2026-07-19T12:00:05Z",
@@ -2226,7 +2270,6 @@ def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch
2226
2270
  "result": {},
2227
2271
  "builder_image": "",
2228
2272
  "builder_runtime": "",
2229
- "steps": [],
2230
2273
  "logs": {
2231
2274
  "state": "available",
2232
2275
  "url": f"/api/v1/deployment-runs/{run_uid}/logs/",
@@ -2250,8 +2293,9 @@ def test_resource_release_deploy_current_version_posts_detail_action(monkeypatch
2250
2293
  assert isinstance(run, models_helpers_mod.DeploymentRun)
2251
2294
  assert run.target.uid == release_uid
2252
2295
  assert run.state == "succeeded"
2253
- assert run.phase == "completed"
2254
2296
  assert run.outcome == "deployed"
2297
+ assert run.pipeline.current_step_key is None
2298
+ assert len(run.pipeline.steps) == 6
2255
2299
  assert run.builder_image == ""
2256
2300
  assert run.builder_runtime == ""
2257
2301
  assert run.logs.state == "available"
@@ -2281,8 +2325,8 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
2281
2325
  "commit_sha": "a" * 40,
2282
2326
  "configuration_revision": 4,
2283
2327
  "state": "succeeded",
2284
- "phase": "completed",
2285
2328
  "outcome": "deployed",
2329
+ "pipeline": _resource_release_pipeline_payload(),
2286
2330
  "created_at": "2026-07-19T12:00:00Z",
2287
2331
  "started_at": "2026-07-19T12:00:01Z",
2288
2332
  "finished_at": "2026-07-19T12:00:05Z",
@@ -2293,7 +2337,6 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
2293
2337
  "result": {},
2294
2338
  "builder_image": "",
2295
2339
  "builder_runtime": "",
2296
- "steps": [],
2297
2340
  "logs": {
2298
2341
  "state": "available",
2299
2342
  "url": f"/api/v1/deployment-runs/{run_uid}/logs/",
@@ -2314,7 +2357,6 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
2314
2357
  "result",
2315
2358
  "builder_image",
2316
2359
  "builder_runtime",
2317
- "steps",
2318
2360
  }
2319
2361
  }
2320
2362
 
@@ -2349,8 +2391,9 @@ def test_deployment_run_collection_and_detail_use_unified_resource_release_contr
2349
2391
  assert len(runs) == 1
2350
2392
  assert runs[0].target.uid == release_uid
2351
2393
  assert detail.state == "succeeded"
2352
- assert detail.phase == "completed"
2353
2394
  assert detail.outcome == "deployed"
2395
+ assert len(runs[0].pipeline.steps) == 6
2396
+ assert detail.pipeline.current_step_key is None
2354
2397
  assert detail.builder_image == ""
2355
2398
  assert detail.builder_runtime == ""
2356
2399
  assert detail.logs.state == "available"
@@ -2377,8 +2420,10 @@ def test_unified_deployment_run_models_and_filters(monkeypatch):
2377
2420
  "commit_sha": "a" * 40,
2378
2421
  "configuration_revision": None,
2379
2422
  "state": "running",
2380
- "phase": "waiting_project_image",
2381
2423
  "outcome": "",
2424
+ "pipeline": _resource_release_pipeline_payload(
2425
+ running_step="build_project_image"
2426
+ ),
2382
2427
  "created_at": "2026-07-19T12:00:00Z",
2383
2428
  "started_at": "2026-07-19T12:00:01Z",
2384
2429
  "finished_at": None,
@@ -2402,7 +2447,9 @@ def test_unified_deployment_run_models_and_filters(monkeypatch):
2402
2447
  )
2403
2448
 
2404
2449
  assert run.target.uid == target_uid
2405
- assert run.steps == []
2450
+ assert run.pipeline.current_step_key == "build_project_image"
2451
+ assert run.pipeline.steps[3].state == "running"
2452
+ assert run.pipeline.steps[4].state == "pending"
2406
2453
  assert run.builder_image == "us-docker.pkg.dev/platform/static-builder:latest"
2407
2454
  assert run.builder_runtime == "nodejs22"
2408
2455
  assert normalized == {
@@ -2471,10 +2518,9 @@ def test_agent_session_runtime_access_uses_session_uid_route(monkeypatch):
2471
2518
  @staticmethod
2472
2519
  def json():
2473
2520
  return {
2474
- "coding_agent_service_id": "svc-12",
2475
- "coding_agent_id": "agent-rt-77",
2521
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
2476
2522
  "mode": "token",
2477
- "rpc_url": "https://runtime.main-sequence.app/rpc",
2523
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
2478
2524
  "token": "tok-secret",
2479
2525
  "is_ready": True,
2480
2526
  "service_runtime_uid": "70c6efb9-8e80-4051-ad3a-f432b2c37f5a",
@@ -2532,7 +2578,9 @@ def test_agent_session_runtime_access_uses_session_uid_route(monkeypatch):
2532
2578
 
2533
2579
  access = agent_models_mod.AgentSession.resolve_runtime_access(session_uid, timeout=11)
2534
2580
 
2535
- assert access.coding_agent_service_id == "svc-12"
2581
+ assert access.coding_agent_service_uid == "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f"
2582
+ assert "coding_agent_service_id" not in agent_models_mod.AgentSessionRuntimeAccess.model_fields
2583
+ assert "coding_agent_id" not in agent_models_mod.AgentSessionRuntimeAccess.model_fields
2536
2584
  assert access.is_ready is True
2537
2585
  assert access.service_runtime_uid == "70c6efb9-8e80-4051-ad3a-f432b2c37f5a"
2538
2586
  assert access.knative_service_runtime_uid == "70c6efb9-8e80-4051-ad3a-f432b2c37f5a"
@@ -2559,10 +2607,9 @@ def test_agent_session_runtime_access_accepts_minimal_image_drift(monkeypatch):
2559
2607
  @staticmethod
2560
2608
  def json():
2561
2609
  return {
2562
- "coding_agent_service_id": "39",
2563
- "coding_agent_id": "astro-orchestrator",
2610
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
2564
2611
  "mode": "token",
2565
- "rpc_url": "https://runtime.main-sequence.app/rpc",
2612
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
2566
2613
  "token": "tok-secret",
2567
2614
  "is_ready": True,
2568
2615
  "knative_service_runtime_uid": "70c6efb9-8e80-4051-ad3a-f432b2c37f5a",
@@ -2602,7 +2649,9 @@ def test_agent_session_send_a2a_message_posts_standard_contract(monkeypatch):
2602
2649
  @staticmethod
2603
2650
  def json():
2604
2651
  return {
2605
- "rpc_url": "https://runtime.main-sequence.app/rpc",
2652
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
2653
+ "mode": "token",
2654
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
2606
2655
  "token": "tok-secret",
2607
2656
  "expires_at": "2999-01-01T00:00:00Z",
2608
2657
  }
@@ -2665,7 +2714,8 @@ def test_agent_session_send_a2a_message_posts_standard_contract(monkeypatch):
2665
2714
  }
2666
2715
  assert payload["message"]["parts"] == [{"text": "I can analyze workspaces."}]
2667
2716
  assert captured["runtime"]["url"] == (
2668
- "https://runtime.main-sequence.app/rpc/api/a2a/v1/message:send"
2717
+ "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/"
2718
+ "api/a2a/v1/message:send"
2669
2719
  )
2670
2720
  assert captured["runtime"]["headers"]["Content-Type"] == "application/a2a+json"
2671
2721
  assert captured["runtime"]["headers"]["Accept"] == "application/a2a+json"
@@ -2686,6 +2736,51 @@ def test_agent_session_send_a2a_message_posts_standard_contract(monkeypatch):
2686
2736
  assert "omit_reasoning" not in captured["runtime"]["data"]
2687
2737
 
2688
2738
 
2739
+ def test_agent_session_send_a2a_message_reports_unavailable_runtime_without_post(
2740
+ monkeypatch,
2741
+ ):
2742
+ session_uid = "3f1cc452-43ec-49cb-b2ba-87dbac164d29"
2743
+ agent_models_mod.AgentSession.clear_cached_runtime_access(session_uid)
2744
+
2745
+ class FakeResolveResponse:
2746
+ status_code = 200
2747
+ content = b'{"ok": true}'
2748
+
2749
+ @staticmethod
2750
+ def json():
2751
+ return {
2752
+ "coding_agent_service_uid": None,
2753
+ "mode": "unavailable",
2754
+ "rpc_url": None,
2755
+ "token": None,
2756
+ "is_ready": False,
2757
+ "detail": "Runtime reconciliation is queued.",
2758
+ }
2759
+
2760
+ monkeypatch.setattr(
2761
+ agent_models_mod,
2762
+ "make_request",
2763
+ lambda **kwargs: FakeResolveResponse(),
2764
+ )
2765
+
2766
+ def _unexpected_post(*args, **kwargs):
2767
+ pytest.fail("A2A HTTP request must not run for unavailable runtime access")
2768
+
2769
+ monkeypatch.setattr(agent_models_mod.requests, "post", _unexpected_post)
2770
+
2771
+ with pytest.raises(
2772
+ agent_models_mod.ApiError,
2773
+ match=(
2774
+ "Coding-agent runtime access is unavailable. "
2775
+ "Runtime reconciliation is queued."
2776
+ ),
2777
+ ):
2778
+ agent_models_mod.AgentSession.send_a2a_message(
2779
+ session_uid,
2780
+ message="Do not send this yet.",
2781
+ )
2782
+
2783
+
2689
2784
  def test_agent_session_send_a2a_message_posts_strict_dictionary_contract(monkeypatch):
2690
2785
  captured = {"resolve_count": 0}
2691
2786
  session_uid = "3f1cc452-43ec-49cb-b2ba-87dbac164d29"
@@ -2699,7 +2794,9 @@ def test_agent_session_send_a2a_message_posts_strict_dictionary_contract(monkeyp
2699
2794
  @staticmethod
2700
2795
  def json():
2701
2796
  return {
2702
- "rpc_url": "https://runtime.main-sequence.app/rpc",
2797
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
2798
+ "mode": "token",
2799
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
2703
2800
  "token": "tok-secret",
2704
2801
  }
2705
2802
 
@@ -2769,7 +2866,9 @@ def test_agent_session_send_a2a_message_refreshes_access_and_reuses_body(monkeyp
2769
2866
  def json():
2770
2867
  captured["resolve_count"] += 1
2771
2868
  return {
2772
- "rpc_url": "https://runtime.main-sequence.app/rpc",
2869
+ "coding_agent_service_uid": "7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f",
2870
+ "mode": "token",
2871
+ "rpc_url": "https://7bd86be3-d11a-4ad1-8fe2-9260ccdbca7f.coding-agent.main-sequence.app/",
2773
2872
  "token": f"tok-secret-{captured['resolve_count']}",
2774
2873
  }
2775
2874
 
File without changes
File without changes
File without changes