mainsequence 8.1.18__tar.gz → 8.1.20.dev1__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 (141) hide show
  1. {mainsequence-8.1.18/mainsequence.egg-info → mainsequence-8.1.20.dev1}/PKG-INFO +1 -1
  2. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +7 -5
  3. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/api.py +2 -6
  4. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/cli.py +0 -16
  5. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/agent_runtime_models.py +16 -16
  6. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1/mainsequence.egg-info}/PKG-INFO +1 -1
  7. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/SOURCES.txt +1 -0
  8. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/pyproject.toml +18 -1
  9. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli.py +6 -26
  10. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_client.py +5 -0
  11. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_batch_jobs_from_file.py +26 -0
  12. mainsequence-8.1.20.dev1/tests/test_dev_release_version.py +118 -0
  13. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_filter_normalization.py +82 -7
  14. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_tables_client_models.py +45 -1
  15. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_configuration_client.py +43 -0
  16. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/LICENSE +0 -0
  17. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/MANIFEST.in +0 -0
  18. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/README.md +0 -0
  19. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/AGENTS.md +0 -0
  20. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  21. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  22. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  23. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  24. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
  25. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  26. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
  27. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  28. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  29. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
  30. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/__init__.py +0 -0
  31. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/__main__.py +0 -0
  32. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/bootstrap.py +0 -0
  33. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/__init__.py +0 -0
  34. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/browser_auth.py +0 -0
  35. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/code_repository_status.py +0 -0
  36. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/config.py +0 -0
  37. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/docker_utils.py +0 -0
  38. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/doctor.py +0 -0
  39. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/local_ops.py +0 -0
  40. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/migrations.py +0 -0
  41. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/model_filters.py +0 -0
  42. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/pydantic_cli.py +0 -0
  43. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/sdk_utils.py +0 -0
  44. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/ssh_utils.py +0 -0
  45. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/ui.py +0 -0
  46. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/__init__.py +0 -0
  47. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/base.py +0 -0
  48. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/client.py +0 -0
  49. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/compute_validation.py +0 -0
  50. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  51. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  52. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  53. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  54. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/dtype_codec.py +0 -0
  55. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/exceptions.py +0 -0
  56. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/github_issues.py +0 -0
  57. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/metatables/__init__.py +0 -0
  58. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/metatables/core.py +0 -0
  59. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_foundry.py +0 -0
  60. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_helpers.py +0 -0
  61. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_user.py +0 -0
  62. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/observability.py +0 -0
  63. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/utils.py +0 -0
  64. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/code_repository_context.py +0 -0
  65. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/code_repository_skills.py +0 -0
  66. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/defaults.py +0 -0
  67. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/instrumentation/__init__.py +0 -0
  68. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/instrumentation/utils.py +0 -0
  69. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/logconf.py +0 -0
  70. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/__init__.py +0 -0
  71. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/__main__.py +0 -0
  72. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  73. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  74. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/future_registry.py +0 -0
  75. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/hashing.py +0 -0
  76. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  77. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  78. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/env.py +0 -0
  79. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/provider.py +0 -0
  80. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/registry.py +0 -0
  81. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  82. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  83. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  84. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  85. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  86. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/schema_names.py +0 -0
  87. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  88. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
  89. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
  90. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
  91. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
  92. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
  93. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
  94. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
  95. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
  96. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
  97. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/repository_identity_security.py +0 -0
  98. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/runtime_flags.py +0 -0
  99. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/scaffold_skills.py +0 -0
  100. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/dependency_links.txt +0 -0
  101. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/entry_points.txt +0 -0
  102. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/requires.txt +0 -0
  103. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/top_level.txt +0 -0
  104. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/setup.cfg +0 -0
  105. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
  106. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_auth_precedence.py +0 -0
  107. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_canonical_api_route_contract.py +0 -0
  108. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli_browser_auth.py +0 -0
  109. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli_migrations.py +0 -0
  110. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_branch_contract.py +0 -0
  111. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_documentation_contract.py +0 -0
  112. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_runtime_context.py +0 -0
  113. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_skills.py +0 -0
  114. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_dependency_extras.py +0 -0
  115. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_duckdb_interface_dimensions.py +0 -0
  116. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_environment_resource_context.py +0 -0
  117. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_environment_response_contracts.py +0 -0
  118. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_github_issues_client.py +0 -0
  119. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_instrumentation.py +0 -0
  120. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_local_ops.py +0 -0
  121. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_logconf.py +0 -0
  122. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_table_migrations.py +0 -0
  123. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  124. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_models_user_request_bound_auth.py +0 -0
  125. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_notification_uid_contract.py +0 -0
  126. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_observability_client.py +0 -0
  127. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_pod_project_resolution.py +0 -0
  128. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_scaffold_skills.py +0 -0
  129. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_schema_names.py +0 -0
  130. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_secret_client_model.py +0 -0
  131. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_source_table_configuration.py +0 -0
  132. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_sqlite_interface_dimensions.py +0 -0
  133. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_ssh_utils.py +0 -0
  134. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_access_dimension_audit.py +0 -0
  135. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_dimension_queries.py +0 -0
  136. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_configuration.py +0 -0
  137. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_flow.py +0 -0
  138. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_hard_cut.py +0 -0
  139. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_runner_uid_runtime.py +0 -0
  140. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_statistics.py +0 -0
  141. {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 8.1.18
3
+ Version: 8.1.20.dev1
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -43,14 +43,16 @@ internally and sends a standard A2A message.
43
43
 
44
44
  ```bash
45
45
  mainsequence agent search "<discoveryPrompt>" \
46
- --environment-uid "<organizationEnvironmentUid>" \
47
46
  --limit 10 \
48
47
  --json
49
48
  ```
50
49
 
51
- Use the canonical Organization Environment UID associated with the target
52
- CodeRepositoryBranch. It scopes discovery only; it does not create, assign, or override an
53
- Agent's environment.
50
+ The SDK resolves the active Git branch once for the process and scopes discovery
51
+ to its Organization Environment. Do not supply a branch or Environment UID.
52
+ An unregistered branch fails only when discovery is attempted.
53
+ For an exact Python lookup, use `Agent.filter(name="SentinelExecutor")` and
54
+ inspect the returned Agent UID and `code_repository_branch_uid`; names are not
55
+ unique routing authority.
54
56
 
55
57
  4. Treat the CLI output as authoritative.
56
58
  5. Prefer the highest `combined_score` when present.
@@ -321,7 +323,7 @@ handle for a different task or conversation.
321
323
  ## Deterministic Execution Path
322
324
 
323
325
  1. Build the discovery prompt.
324
- 2. Run `mainsequence agent search "<discoveryPrompt>" --environment-uid "<organizationEnvironmentUid>" --limit <n> --json`.
326
+ 2. Run `mainsequence agent search "<discoveryPrompt>" --limit <n> --json`.
325
327
  3. Select the target agent.
326
328
  4. Create or resolve the target session with `mainsequence agent session get_or_create`.
327
329
  5. Use the returned session `uid`.
@@ -1161,16 +1161,14 @@ def delete_organization_team(
1161
1161
 
1162
1162
  def list_agents(
1163
1163
  *,
1164
- organization_environment_uid: str,
1165
1164
  timeout: int | None = None,
1166
1165
  filters: dict[str, Any] | None = None,
1167
1166
  ) -> list[dict[str, Any]]:
1168
1167
  """
1169
- List agents in one Organization Environment via the SDK client model.
1168
+ List agents in the Git-resolved Organization Environment via the SDK client model.
1170
1169
  """
1171
1170
  try:
1172
1171
  read_params = dict(filters or {})
1173
- read_params["organization_environment_uid"] = organization_environment_uid
1174
1172
  payload = _run_sdk_model_operation(
1175
1173
  module_name="mainsequence.client.agent_runtime_models",
1176
1174
  class_name="Agent",
@@ -1293,12 +1291,11 @@ def get_agent_resource_usage(
1293
1291
  def semantic_search_agents(
1294
1292
  q: str,
1295
1293
  *,
1296
- organization_environment_uid: str,
1297
1294
  limit: int = 20,
1298
1295
  timeout: int | None = None,
1299
1296
  ) -> list[dict[str, Any]]:
1300
1297
  """
1301
- Search agents in one Organization Environment via `Agent.semantic_search()`.
1298
+ Search agents in the Git-resolved Organization Environment.
1302
1299
  """
1303
1300
  try:
1304
1301
  payload = _run_sdk_model_operation(
@@ -1306,7 +1303,6 @@ def semantic_search_agents(
1306
1303
  class_name="Agent",
1307
1304
  operation=lambda ClientAgent: ClientAgent.semantic_search(
1308
1305
  q,
1309
- organization_environment_uid=organization_environment_uid,
1310
1306
  limit=limit,
1311
1307
  timeout=timeout,
1312
1308
  ),
@@ -3541,7 +3541,6 @@ def _render_owner_resource_usage(payload: dict[str, object], *, title: str) -> N
3541
3541
 
3542
3542
 
3543
3543
  def _agent_list_impl(
3544
- organization_environment_uid: str,
3545
3544
  timeout: int | None,
3546
3545
  filter_entries: list[str] | None,
3547
3546
  show_filters: bool,
@@ -3556,7 +3555,6 @@ def _agent_list_impl(
3556
3555
 
3557
3556
  try:
3558
3557
  agents = list_agents(
3559
- organization_environment_uid=organization_environment_uid,
3560
3558
  timeout=timeout,
3561
3559
  filters=filters,
3562
3560
  )
@@ -3630,7 +3628,6 @@ def _agent_detail_impl(
3630
3628
  def _agent_search_impl(
3631
3629
  *,
3632
3630
  q: str,
3633
- organization_environment_uid: str,
3634
3631
  limit: int,
3635
3632
  timeout: int | None,
3636
3633
  ) -> None:
@@ -3639,7 +3636,6 @@ def _agent_search_impl(
3639
3636
  try:
3640
3637
  results = semantic_search_agents(
3641
3638
  q,
3642
- organization_environment_uid=organization_environment_uid,
3643
3639
  limit=limit,
3644
3640
  timeout=timeout,
3645
3641
  )
@@ -4697,11 +4693,6 @@ def _print_time_index_table_search_section(
4697
4693
 
4698
4694
  @agent.command("list")
4699
4695
  def agent_list_cmd(
4700
- organization_environment_uid: uuid.UUID = typer.Option(
4701
- ...,
4702
- "--environment-uid",
4703
- help="Organization Environment UID that scopes Agent discovery.",
4704
- ),
4705
4696
  filter_entries: list[str] | None = typer.Option(None, "--filter", help=LIST_FILTER_OPTION_HELP),
4706
4697
  show_filters: bool = typer.Option(
4707
4698
  False, "--show-filters", help="Show the filters supported by this list command and exit."
@@ -4712,7 +4703,6 @@ def agent_list_cmd(
4712
4703
  List agents visible to the authenticated user.
4713
4704
  """
4714
4705
  _agent_list_impl(
4715
- organization_environment_uid=str(organization_environment_uid),
4716
4706
  timeout=timeout,
4717
4707
  filter_entries=filter_entries,
4718
4708
  show_filters=show_filters,
@@ -4799,11 +4789,6 @@ def agent_resource_usage_cmd(
4799
4789
  @agent.command("search")
4800
4790
  def agent_search_cmd(
4801
4791
  q: str = typer.Argument(..., help="Natural-language query to match against agents."),
4802
- organization_environment_uid: uuid.UUID = typer.Option(
4803
- ...,
4804
- "--environment-uid",
4805
- help="Organization Environment UID that scopes Agent discovery.",
4806
- ),
4807
4792
  limit: int = typer.Option(
4808
4793
  20, "--limit", min=1, max=100, help="Maximum number of ranked agent matches to return."
4809
4794
  ),
@@ -4823,7 +4808,6 @@ def agent_search_cmd(
4823
4808
  """
4824
4809
  _agent_search_impl(
4825
4810
  q=q,
4826
- organization_environment_uid=str(organization_environment_uid),
4827
4811
  limit=limit,
4828
4812
  timeout=timeout,
4829
4813
  )
@@ -12,7 +12,12 @@ from typing import Any, ClassVar, Literal
12
12
  import requests
13
13
  from pydantic import ConfigDict, Field, model_validator
14
14
 
15
- from .base import BaseObjectOrm, BasePydanticModel, ShareableObjectMixin
15
+ from .base import (
16
+ BaseObjectOrm,
17
+ BasePydanticModel,
18
+ CurrentCodeRepositoryEnvironmentResourceMixin,
19
+ ShareableObjectMixin,
20
+ )
16
21
  from .exceptions import ApiError, raise_for_response
17
22
  from .observability import (
18
23
  EnvironmentLogSearchMixin,
@@ -465,6 +470,7 @@ def _runtime_access_retry_seconds(access: AgentSessionRuntimeAccess) -> float:
465
470
 
466
471
 
467
472
  class Agent(
473
+ CurrentCodeRepositoryEnvironmentResourceMixin,
468
474
  EnvironmentLogSearchMixin,
469
475
  OwnerLogMixin,
470
476
  OwnerResourceUsageMixin,
@@ -482,14 +488,22 @@ class Agent(
482
488
 
483
489
  FILTERSET_FIELDS: ClassVar[dict[str, list[str]] | None] = {
484
490
  "uid": ["exact", "in"],
491
+ "name": ["exact"],
485
492
  "search": ["exact"],
486
493
  }
487
494
  FILTER_VALUE_NORMALIZERS: ClassVar[dict[str, str]] = {
488
495
  "uid": "uid",
489
496
  "uid__in": "uid",
497
+ "name": "str",
490
498
  "search": "str",
491
499
  }
492
500
 
501
+ @classmethod
502
+ def _sdk_owned_query_context(cls, operation: str) -> dict[str, str]:
503
+ if operation in {f"{cls.__name__}.filter", f"{cls.__name__}.semantic_search"}:
504
+ return super()._sdk_owned_query_context(operation)
505
+ return {}
506
+
493
507
  @classmethod
494
508
  def search_logs(
495
509
  cls,
@@ -522,16 +536,6 @@ class Agent(
522
536
  timeout=timeout,
523
537
  )
524
538
 
525
- READ_QUERY_PARAMS: ClassVar[dict[str, str]] = {
526
- "organization_environment_uid": "uid",
527
- }
528
- READ_QUERY_PARAM_DESCRIPTIONS: ClassVar[dict[str, str]] = {
529
- "organization_environment_uid": (
530
- "Required Organization Environment boundary for Agent discovery. "
531
- "This scopes reads and does not assign an environment to an Agent."
532
- ),
533
- }
534
-
535
539
  uid: str | None = Field(None, description="Public UID of the agent resource.")
536
540
  name: str = Field(
537
541
  ..., description="Human-readable display name for the agent inside the organization."
@@ -667,7 +671,6 @@ class Agent(
667
671
  cls,
668
672
  q: str,
669
673
  *,
670
- organization_environment_uid: str,
671
674
  limit: int = 20,
672
675
  timeout=None,
673
676
  ) -> list[AgentSemanticSearchResult]:
@@ -688,12 +691,9 @@ class Agent(
688
691
  raise ValueError("limit must be between 1 and 100")
689
692
 
690
693
  body: dict[str, Any] = {
691
- "organization_environment_uid": cls._coerce_filter_uid(
692
- organization_environment_uid,
693
- field_name="organization_environment_uid",
694
- ),
695
694
  "q": q,
696
695
  "limit": limit,
696
+ **cls._sdk_owned_query_context(f"{cls.__name__}.semantic_search"),
697
697
  }
698
698
 
699
699
  payload = {"json": serialize_to_json(body)}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 8.1.18
3
+ Version: 8.1.20.dev1
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -105,6 +105,7 @@ tests/test_code_repository_documentation_contract.py
105
105
  tests/test_code_repository_runtime_context.py
106
106
  tests/test_code_repository_skills.py
107
107
  tests/test_dependency_extras.py
108
+ tests/test_dev_release_version.py
108
109
  tests/test_duckdb_interface_dimensions.py
109
110
  tests/test_environment_resource_context.py
110
111
  tests/test_environment_response_contracts.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "8.1.18"
7
+ version = "8.1.20.dev1"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -95,6 +95,23 @@ publish-url = "https://test.pypi.org/legacy/"
95
95
  explicit = true
96
96
 
97
97
 
98
+ # --------------------
99
+ # Testing (pytest)
100
+ # --------------------
101
+ [tool.pytest.ini_options]
102
+ testpaths = ["tests"]
103
+ # Put the repository root on sys.path so tests can import `scripts`. `pytest`
104
+ # invoked as `python -m pytest` gets this from the CWD, but the `pytest`
105
+ # entrypoint (what `uv run pytest` and CI use) does not.
106
+ pythonpath = ["."]
107
+ # `live` tests talk to a real backend and need credentials, so they are
108
+ # deselected by default. CI and a plain `pytest` therefore run offline.
109
+ # Run them explicitly with `pytest -m live`.
110
+ addopts = "-m 'not live'"
111
+ markers = [
112
+ "live: talks to a live Main Sequence backend and needs credentials; deselected unless `-m live` is passed",
113
+ ]
114
+
98
115
  # --------------------
99
116
  # Formatting (Black)
100
117
  # --------------------
@@ -579,7 +579,6 @@ def test_list_organization_teams_uses_client_model(cli_mod, monkeypatch):
579
579
  def test_list_agents_uses_client_model(cli_mod, monkeypatch):
580
580
  api_mod = importlib.import_module("mainsequence.cli.api")
581
581
  captured = {}
582
- environment_uid = "22222222-2222-4222-8222-222222222222"
583
582
 
584
583
  class FakeAgent:
585
584
  def __init__(self, uid, name):
@@ -607,7 +606,6 @@ def test_list_agents_uses_client_model(cli_mod, monkeypatch):
607
606
  monkeypatch.setattr(api_mod, "_run_sdk_model_operation", _run_sdk_model_operation)
608
607
 
609
608
  out = api_mod.list_agents(
610
- organization_environment_uid=environment_uid,
611
609
  timeout=9,
612
610
  filters={"search": "Research"},
613
611
  )
@@ -615,10 +613,7 @@ def test_list_agents_uses_client_model(cli_mod, monkeypatch):
615
613
  "module_name": "mainsequence.client.agent_runtime_models",
616
614
  "class_name": "Agent",
617
615
  "timeout": 9,
618
- "filters": {
619
- "search": "Research",
620
- "organization_environment_uid": environment_uid,
621
- },
616
+ "filters": {"search": "Research"},
622
617
  }
623
618
  assert out == [
624
619
  {
@@ -677,7 +672,6 @@ def test_get_code_repository_repository_uses_public_client_model(cli_mod, monkey
677
672
  def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
678
673
  api_mod = importlib.import_module("mainsequence.cli.api")
679
674
  captured = {}
680
- environment_uid = "22222222-2222-4222-8222-222222222222"
681
675
 
682
676
  class FakeSearchResult:
683
677
  def __init__(self):
@@ -710,12 +704,10 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
710
704
  cls,
711
705
  q,
712
706
  *,
713
- organization_environment_uid,
714
707
  limit=20,
715
708
  timeout=None,
716
709
  ):
717
710
  captured["q"] = q
718
- captured["organization_environment_uid"] = organization_environment_uid
719
711
  captured["limit"] = limit
720
712
  captured["timeout"] = timeout
721
713
  return [FakeSearchResult()]
@@ -726,7 +718,6 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
726
718
 
727
719
  out = api_mod.semantic_search_agents(
728
720
  "data research",
729
- organization_environment_uid=environment_uid,
730
721
  limit=10,
731
722
  timeout=17,
732
723
  )
@@ -734,7 +725,6 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
734
725
  "module_name": "mainsequence.client.agent_runtime_models",
735
726
  "class_name": "Agent",
736
727
  "q": "data research",
737
- "organization_environment_uid": environment_uid,
738
728
  "limit": 10,
739
729
  "timeout": 17,
740
730
  }
@@ -6322,12 +6312,11 @@ def test_code_repository_code_repository_resource_delete_fastapi_requires_confir
6322
6312
 
6323
6313
 
6324
6314
  def test_agent_list(cli_mod, runner, monkeypatch):
6325
- environment_uid = "22222222-2222-4222-8222-222222222222"
6326
6315
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6327
6316
  monkeypatch.setattr(
6328
6317
  cli_mod,
6329
6318
  "list_agents",
6330
- lambda organization_environment_uid, timeout=None, filters=None: [
6319
+ lambda timeout=None, filters=None: [
6331
6320
  {
6332
6321
  "uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
6333
6322
  "name": "Research Copilot",
@@ -6343,7 +6332,7 @@ def test_agent_list(cli_mod, runner, monkeypatch):
6343
6332
 
6344
6333
  result = runner.invoke(
6345
6334
  cli_mod.app,
6346
- ["agent", "list", "--environment-uid", environment_uid],
6335
+ ["agent", "list", "--filter", "name=SentinelExecutor"],
6347
6336
  )
6348
6337
  assert result.exit_code == 0
6349
6338
  assert "Agents" in result.output
@@ -6355,12 +6344,11 @@ def test_agent_list(cli_mod, runner, monkeypatch):
6355
6344
 
6356
6345
 
6357
6346
  def test_agent_list_json(cli_mod, runner, monkeypatch):
6358
- environment_uid = "22222222-2222-4222-8222-222222222222"
6359
6347
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6360
6348
  monkeypatch.setattr(
6361
6349
  cli_mod,
6362
6350
  "list_agents",
6363
- lambda organization_environment_uid, timeout=None, filters=None: [
6351
+ lambda timeout=None, filters=None: [
6364
6352
  {
6365
6353
  "uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
6366
6354
  "name": "Research Copilot",
@@ -6376,7 +6364,7 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
6376
6364
 
6377
6365
  result = runner.invoke(
6378
6366
  cli_mod.app,
6379
- ["agent", "list", "--environment-uid", environment_uid, "--json"],
6367
+ ["agent", "list", "--json"],
6380
6368
  )
6381
6369
  assert result.exit_code == 0
6382
6370
  payload = json.loads(result.output)
@@ -6386,14 +6374,12 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
6386
6374
 
6387
6375
  def test_agent_search(cli_mod, runner, monkeypatch):
6388
6376
  captured = {}
6389
- environment_uid = "22222222-2222-4222-8222-222222222222"
6390
6377
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6391
6378
 
6392
- def _search(q, *, organization_environment_uid, limit=20, timeout=None):
6379
+ def _search(q, *, limit=20, timeout=None):
6393
6380
  captured.update(
6394
6381
  {
6395
6382
  "q": q,
6396
- "organization_environment_uid": organization_environment_uid,
6397
6383
  "limit": limit,
6398
6384
  "timeout": timeout,
6399
6385
  }
@@ -6417,8 +6403,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6417
6403
  "agent",
6418
6404
  "search",
6419
6405
  "data research",
6420
- "--environment-uid",
6421
- environment_uid,
6422
6406
  "--limit",
6423
6407
  "10",
6424
6408
  "--timeout",
@@ -6428,7 +6412,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6428
6412
  assert result.exit_code == 0
6429
6413
  assert captured == {
6430
6414
  "q": "data research",
6431
- "organization_environment_uid": environment_uid,
6432
6415
  "limit": 10,
6433
6416
  "timeout": 17,
6434
6417
  }
@@ -6442,7 +6425,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6442
6425
 
6443
6426
 
6444
6427
  def test_agent_search_json(cli_mod, runner, monkeypatch):
6445
- environment_uid = "22222222-2222-4222-8222-222222222222"
6446
6428
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6447
6429
  monkeypatch.setattr(
6448
6430
  cli_mod,
@@ -6465,8 +6447,6 @@ def test_agent_search_json(cli_mod, runner, monkeypatch):
6465
6447
  "agent",
6466
6448
  "search",
6467
6449
  "data research",
6468
- "--environment-uid",
6469
- environment_uid,
6470
6450
  "--json",
6471
6451
  ],
6472
6452
  )
@@ -4,6 +4,11 @@ import pytest
4
4
 
5
5
  import mainsequence.client as msc
6
6
 
7
+ # Every test in this module drives a real backend over the network and needs
8
+ # SDK credentials, so none of them can run in CI. See `[tool.pytest.ini_options]`
9
+ # in pyproject.toml: `pytest` deselects them, `pytest -m live` runs them.
10
+ pytestmark = pytest.mark.live
11
+
7
12
 
8
13
  def test_create_code_repository():
9
14
  ds = msc.DataSource.filter(status=msc.DataSource.STATUS_AVAILABLE)[0]
@@ -6,6 +6,32 @@ import types
6
6
  import pytest
7
7
 
8
8
 
9
+ def _snapshot_mainsequence_modules() -> dict[str, types.ModuleType]:
10
+ return {
11
+ name: module
12
+ for name, module in sys.modules.items()
13
+ if name == "mainsequence" or name.startswith("mainsequence.")
14
+ }
15
+
16
+
17
+ @pytest.fixture(autouse=True)
18
+ def _restore_mainsequence_modules():
19
+ """Undo the stub packages this module installs into ``sys.modules``.
20
+
21
+ ``_load_models_helpers_module`` replaces the real ``mainsequence`` packages
22
+ with stubs so ``models_helpers`` can be imported without the heavy client
23
+ stack. Without this fixture the stubs leak into every test module that runs
24
+ afterwards, and ``monkeypatch.setattr("mainsequence.client....")`` there
25
+ fails with ``module 'mainsequence' has no attribute 'client'``.
26
+ """
27
+ snapshot = _snapshot_mainsequence_modules()
28
+ yield
29
+ for name in tuple(sys.modules):
30
+ if name == "mainsequence" or name.startswith("mainsequence."):
31
+ sys.modules.pop(name, None)
32
+ sys.modules.update(snapshot)
33
+
34
+
9
35
  def _load_models_helpers_module():
10
36
  repo_root = pathlib.Path(__file__).resolve().parents[1]
11
37
  pkg_root = repo_root / "mainsequence"
@@ -0,0 +1,118 @@
1
+ """Contract for the development-release version computed by the publish workflow.
2
+
3
+ The standard these tests pin down is documented in
4
+ `docs/knowledge/release_process.md`.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import pytest
10
+ from packaging.version import Version
11
+
12
+ from scripts import dev_release_version
13
+
14
+
15
+ def _files(*, yanked: bool = False) -> list[dict[str, object]]:
16
+ return [{"filename": "mainsequence-x-py3-none-any.whl", "yanked": yanked}]
17
+
18
+
19
+ def test_latest_final_ignores_development_and_pre_releases():
20
+ releases = {
21
+ "8.1.19": _files(),
22
+ "8.1.20.dev41": _files(),
23
+ "8.2.0rc1": _files(),
24
+ "8.1.19.post1": _files(),
25
+ }
26
+
27
+ assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
28
+
29
+
30
+ def test_latest_final_ignores_releases_with_no_installable_file():
31
+ releases = {
32
+ "8.1.19": _files(),
33
+ "9.0.0": [],
34
+ "9.1.0": _files(yanked=True),
35
+ }
36
+
37
+ assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
38
+
39
+
40
+ def test_latest_final_keeps_a_release_with_one_file_left():
41
+ releases = {
42
+ "8.1.19": _files(),
43
+ "8.2.0": [
44
+ {"filename": "mainsequence-8.2.0.tar.gz", "yanked": True},
45
+ {"filename": "mainsequence-8.2.0-py3-none-any.whl", "yanked": False},
46
+ ],
47
+ }
48
+
49
+ assert dev_release_version.latest_final_version(releases) == Version("8.2.0")
50
+
51
+
52
+ def test_latest_final_orders_numerically_not_lexically():
53
+ releases = {"8.1.9": _files(), "8.1.10": _files(), "8.1.2": _files()}
54
+
55
+ assert dev_release_version.latest_final_version(releases) == Version("8.1.10")
56
+
57
+
58
+ def test_latest_final_skips_unparseable_versions():
59
+ releases = {"8.1.19": _files(), "not-a-version": _files()}
60
+
61
+ assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
62
+
63
+
64
+ def test_latest_final_requires_at_least_one_installable_release():
65
+ with pytest.raises(dev_release_version.DevVersionError):
66
+ dev_release_version.latest_final_version({"9.0.0": []})
67
+
68
+
69
+ def test_dev_version_carries_the_next_patch_number():
70
+ assert dev_release_version.dev_version(Version("8.1.19"), 41) == "8.1.20.dev41"
71
+
72
+
73
+ def test_dev_version_sorts_between_the_current_and_the_next_release():
74
+ computed = Version(dev_release_version.dev_version(Version("8.1.19"), 41))
75
+
76
+ assert Version("8.1.19") < computed < Version("8.1.20")
77
+
78
+
79
+ def test_dev_version_is_a_development_release_so_pip_skips_it_by_default():
80
+ computed = Version(dev_release_version.dev_version(Version("8.1.19"), 41))
81
+
82
+ assert computed.is_devrelease
83
+
84
+
85
+ def test_dev_version_rejects_a_negative_run_number():
86
+ with pytest.raises(dev_release_version.DevVersionError):
87
+ dev_release_version.dev_version(Version("8.1.19"), -1)
88
+
89
+
90
+ def test_apply_version_rewrites_only_the_project_version():
91
+ pyproject = '[project]\nname = "mainsequence"\nversion = "8.1.19"\n\n[tool.other]\nversion = "1.0.0"\n'
92
+
93
+ rewritten = dev_release_version.apply_version(pyproject, "8.1.20.dev41")
94
+
95
+ assert 'version = "8.1.20.dev41"' in rewritten
96
+ assert rewritten.count('version = "1.0.0"') == 1
97
+
98
+
99
+ def test_apply_version_refuses_a_pyproject_without_a_project_version():
100
+ with pytest.raises(dev_release_version.DevVersionError):
101
+ dev_release_version.apply_version('[project]\nname = "mainsequence"\n', "8.1.20.dev41")
102
+
103
+
104
+ def test_read_declared_version_reports_the_repository_version():
105
+ text = dev_release_version.PYPROJECT.read_text(encoding="utf-8")
106
+
107
+ declared = dev_release_version.read_declared_version(text)
108
+
109
+ assert declared is not None
110
+ Version(declared)
111
+
112
+
113
+ def test_the_repository_pyproject_accepts_a_rewritten_version():
114
+ text = dev_release_version.PYPROJECT.read_text(encoding="utf-8")
115
+
116
+ rewritten = dev_release_version.apply_version(text, "8.1.20.dev41")
117
+
118
+ assert dev_release_version.read_declared_version(rewritten) == "8.1.20.dev41"