mainsequence 6.0.32__tar.gz → 6.0.34__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 (125) hide show
  1. {mainsequence-6.0.32/mainsequence.egg-info → mainsequence-6.0.34}/PKG-INFO +1 -1
  2. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +9 -2
  3. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/api.py +8 -3
  4. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/cli.py +20 -1
  5. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/agent_runtime_models.py +52 -1
  6. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/models_helpers.py +20 -0
  7. {mainsequence-6.0.32 → mainsequence-6.0.34/mainsequence.egg-info}/PKG-INFO +1 -1
  8. {mainsequence-6.0.32 → mainsequence-6.0.34}/pyproject.toml +1 -1
  9. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_cli.py +81 -16
  10. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_filter_normalization.py +202 -0
  11. {mainsequence-6.0.32 → mainsequence-6.0.34}/LICENSE +0 -0
  12. {mainsequence-6.0.32 → mainsequence-6.0.34}/README.md +0 -0
  13. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/AGENTS.md +0 -0
  14. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  15. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  16. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  17. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  18. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  19. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  20. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
  21. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  22. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  23. {mainsequence-6.0.32 → mainsequence-6.0.34}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
  24. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/__init__.py +0 -0
  25. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/__main__.py +0 -0
  26. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/bootstrap.py +0 -0
  27. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/__init__.py +0 -0
  28. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/browser_auth.py +0 -0
  29. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/config.py +0 -0
  30. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/docker_utils.py +0 -0
  31. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/doctor.py +0 -0
  32. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/local_ops.py +0 -0
  33. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/migrations.py +0 -0
  34. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/model_filters.py +0 -0
  35. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/project_status.py +0 -0
  36. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/pydantic_cli.py +0 -0
  37. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/sdk_utils.py +0 -0
  38. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/ssh_utils.py +0 -0
  39. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/cli/ui.py +0 -0
  40. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/__init__.py +0 -0
  41. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/base.py +0 -0
  42. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/client.py +0 -0
  43. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/compute_validation.py +0 -0
  44. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  45. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  46. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  47. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  48. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/dtype_codec.py +0 -0
  49. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/exceptions.py +0 -0
  50. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/metatables/__init__.py +0 -0
  51. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/metatables/core.py +0 -0
  52. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/models_foundry.py +0 -0
  53. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/models_user.py +0 -0
  54. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/client/utils.py +0 -0
  55. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/defaults.py +0 -0
  56. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/instrumentation/__init__.py +0 -0
  57. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/instrumentation/utils.py +0 -0
  58. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/logconf.py +0 -0
  59. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/__init__.py +0 -0
  60. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/__main__.py +0 -0
  61. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  62. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  63. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  64. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  65. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
  66. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  67. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  68. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
  69. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  70. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  71. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/future_registry.py +0 -0
  72. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/hashing.py +0 -0
  73. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  74. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  75. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/env.py +0 -0
  76. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/provider.py +0 -0
  77. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/registry.py +0 -0
  78. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  79. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  80. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  81. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  82. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  83. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/schema_names.py +0 -0
  84. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  85. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/project_skills.py +0 -0
  86. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/runtime_context.py +0 -0
  87. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/runtime_flags.py +0 -0
  88. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence/scaffold_skills.py +0 -0
  89. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence.egg-info/SOURCES.txt +0 -0
  90. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence.egg-info/dependency_links.txt +0 -0
  91. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence.egg-info/entry_points.txt +0 -0
  92. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence.egg-info/requires.txt +0 -0
  93. {mainsequence-6.0.32 → mainsequence-6.0.34}/mainsequence.egg-info/top_level.txt +0 -0
  94. {mainsequence-6.0.32 → mainsequence-6.0.34}/setup.cfg +0 -0
  95. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_auth_precedence.py +0 -0
  96. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_build_operations_hashing.py +0 -0
  97. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_canonical_api_route_contract.py +0 -0
  98. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_cli_browser_auth.py +0 -0
  99. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_cli_migrations.py +0 -0
  100. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_client.py +0 -0
  101. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  102. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_data_node_storage_dimension_queries.py +0 -0
  103. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_data_node_update_flow.py +0 -0
  104. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_dependency_extras.py +0 -0
  105. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_duckdb_interface_dimensions.py +0 -0
  106. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_instrumentation.py +0 -0
  107. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_logconf.py +0 -0
  108. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_meta_table_migrations.py +0 -0
  109. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_meta_tables_client_models.py +0 -0
  110. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  111. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_models_user_request_bound_auth.py +0 -0
  112. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_notification_uid_contract.py +0 -0
  113. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_pod_project_resolution.py +0 -0
  114. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_project_batch_jobs_from_file.py +0 -0
  115. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_project_branch_contract.py +0 -0
  116. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_project_skills.py +0 -0
  117. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_run_configuration.py +0 -0
  118. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_scaffold_skills.py +0 -0
  119. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_schema_names.py +0 -0
  120. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_secret_client_model.py +0 -0
  121. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_source_table_configuration.py +0 -0
  122. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_sqlite_interface_dimensions.py +0 -0
  123. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_update_runner_uid_runtime.py +0 -0
  124. {mainsequence-6.0.32 → mainsequence-6.0.34}/tests/test_update_statistics.py +0 -0
  125. {mainsequence-6.0.32 → mainsequence-6.0.34}/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.32
3
+ Version: 6.0.34
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -39,9 +39,16 @@ internally and sends a standard A2A message.
39
39
  3. Run:
40
40
 
41
41
  ```bash
42
- mainsequence agent search "<discoveryPrompt>" --limit 10 --json
42
+ mainsequence agent search "<discoveryPrompt>" \
43
+ --environment-uid "<organizationEnvironmentUid>" \
44
+ --limit 10 \
45
+ --json
43
46
  ```
44
47
 
48
+ Use the canonical Organization Environment UID associated with the target
49
+ ProjectBranch. It scopes discovery only; it does not create, assign, or override an
50
+ Agent's environment.
51
+
45
52
  4. Treat the CLI output as authoritative.
46
53
  5. Prefer the highest `combined_score` when present.
47
54
  6. If the user asked only which agents are available, summarize the candidates and stop.
@@ -270,7 +277,7 @@ handle for a different task or conversation.
270
277
  ## Deterministic Execution Path
271
278
 
272
279
  1. Build the discovery prompt.
273
- 2. Run `mainsequence agent search "<discoveryPrompt>" --limit <n> --json`.
280
+ 2. Run `mainsequence agent search "<discoveryPrompt>" --environment-uid "<organizationEnvironmentUid>" --limit <n> --json`.
274
281
  3. Select the target agent.
275
282
  4. Create or resolve the target session with `mainsequence agent session get_or_create`.
276
283
  5. Use the returned session `uid`.
@@ -1166,17 +1166,20 @@ def delete_organization_team(
1166
1166
 
1167
1167
  def list_agents(
1168
1168
  *,
1169
+ organization_project_environment_uid: str,
1169
1170
  timeout: int | None = None,
1170
1171
  filters: dict[str, Any] | None = None,
1171
1172
  ) -> list[dict[str, Any]]:
1172
1173
  """
1173
- List agents via SDK client model.
1174
+ List agents in one Organization Environment via the SDK client model.
1174
1175
  """
1175
1176
  try:
1177
+ read_params = dict(filters or {})
1178
+ read_params["organization_project_environment_uid"] = organization_project_environment_uid
1176
1179
  payload = _run_sdk_model_operation(
1177
1180
  module_name="mainsequence.client.agent_runtime_models",
1178
1181
  class_name="Agent",
1179
- operation=lambda ClientAgent: ClientAgent.filter(timeout=timeout, **(filters or {})),
1182
+ operation=lambda ClientAgent: ClientAgent.filter(timeout=timeout, **read_params),
1180
1183
  )
1181
1184
  return [_sdk_object_to_dict(item) for item in list(payload or [])]
1182
1185
  except Exception as e:
@@ -1212,11 +1215,12 @@ def get_agent(
1212
1215
  def semantic_search_agents(
1213
1216
  q: str,
1214
1217
  *,
1218
+ organization_project_environment_uid: str,
1215
1219
  limit: int = 20,
1216
1220
  timeout: int | None = None,
1217
1221
  ) -> list[dict[str, Any]]:
1218
1222
  """
1219
- Search agents via SDK client `Agent.semantic_search()`.
1223
+ Search agents in one Organization Environment via `Agent.semantic_search()`.
1220
1224
  """
1221
1225
  try:
1222
1226
  payload = _run_sdk_model_operation(
@@ -1224,6 +1228,7 @@ def semantic_search_agents(
1224
1228
  class_name="Agent",
1225
1229
  operation=lambda ClientAgent: ClientAgent.semantic_search(
1226
1230
  q,
1231
+ organization_project_environment_uid=organization_project_environment_uid,
1227
1232
  limit=limit,
1228
1233
  timeout=timeout,
1229
1234
  ),
@@ -3548,6 +3548,7 @@ def _format_agent_session_details(
3548
3548
 
3549
3549
 
3550
3550
  def _agent_list_impl(
3551
+ organization_project_environment_uid: str,
3551
3552
  timeout: int | None,
3552
3553
  filter_entries: list[str] | None,
3553
3554
  show_filters: bool,
@@ -3561,7 +3562,11 @@ def _agent_list_impl(
3561
3562
  _require_login()
3562
3563
 
3563
3564
  try:
3564
- agents = list_agents(timeout=timeout, filters=filters)
3565
+ agents = list_agents(
3566
+ organization_project_environment_uid=organization_project_environment_uid,
3567
+ timeout=timeout,
3568
+ filters=filters,
3569
+ )
3565
3570
  except ApiError as e:
3566
3571
  error(f"Agents fetch failed: {e}")
3567
3572
  raise typer.Exit(1) from e
@@ -3632,6 +3637,7 @@ def _agent_detail_impl(
3632
3637
  def _agent_search_impl(
3633
3638
  *,
3634
3639
  q: str,
3640
+ organization_project_environment_uid: str,
3635
3641
  limit: int,
3636
3642
  timeout: int | None,
3637
3643
  ) -> None:
@@ -3640,6 +3646,7 @@ def _agent_search_impl(
3640
3646
  try:
3641
3647
  results = semantic_search_agents(
3642
3648
  q,
3649
+ organization_project_environment_uid=organization_project_environment_uid,
3643
3650
  limit=limit,
3644
3651
  timeout=timeout,
3645
3652
  )
@@ -4766,6 +4773,11 @@ def _print_data_node_storage_search_section(
4766
4773
 
4767
4774
  @agent.command("list")
4768
4775
  def agent_list_cmd(
4776
+ organization_project_environment_uid: uuid.UUID = typer.Option(
4777
+ ...,
4778
+ "--environment-uid",
4779
+ help="Organization Environment UID that scopes Agent discovery.",
4780
+ ),
4769
4781
  filter_entries: list[str] | None = typer.Option(None, "--filter", help=LIST_FILTER_OPTION_HELP),
4770
4782
  show_filters: bool = typer.Option(
4771
4783
  False, "--show-filters", help="Show the filters supported by this list command and exit."
@@ -4776,6 +4788,7 @@ def agent_list_cmd(
4776
4788
  List agents visible to the authenticated user.
4777
4789
  """
4778
4790
  _agent_list_impl(
4791
+ organization_project_environment_uid=str(organization_project_environment_uid),
4779
4792
  timeout=timeout,
4780
4793
  filter_entries=filter_entries,
4781
4794
  show_filters=show_filters,
@@ -4801,6 +4814,11 @@ def agent_detail_cmd(
4801
4814
  @agent.command("search")
4802
4815
  def agent_search_cmd(
4803
4816
  q: str = typer.Argument(..., help="Natural-language query to match against agents."),
4817
+ organization_project_environment_uid: uuid.UUID = typer.Option(
4818
+ ...,
4819
+ "--environment-uid",
4820
+ help="Organization Environment UID that scopes Agent discovery.",
4821
+ ),
4804
4822
  limit: int = typer.Option(
4805
4823
  20, "--limit", min=1, max=100, help="Maximum number of ranked agent matches to return."
4806
4824
  ),
@@ -4820,6 +4838,7 @@ def agent_search_cmd(
4820
4838
  """
4821
4839
  _agent_search_impl(
4822
4840
  q=q,
4841
+ organization_project_environment_uid=str(organization_project_environment_uid),
4823
4842
  limit=limit,
4824
4843
  timeout=timeout,
4825
4844
  )
@@ -56,6 +56,22 @@ class AgentSemanticSearchResult(BasePydanticModel):
56
56
  "",
57
57
  description="Short description returned by semantic search for the matched agent.",
58
58
  )
59
+ project_branch_uid: str = Field(
60
+ ...,
61
+ description="Public UID of the ProjectBranch that owns the matched Project Coding Agent.",
62
+ )
63
+ repository_branch: str = Field(
64
+ ...,
65
+ description="Repository branch of the matched Project Coding Agent.",
66
+ )
67
+ organization_project_environment_uid: str = Field(
68
+ ...,
69
+ description="Public UID of the Organization Environment that scoped the search result.",
70
+ )
71
+ organization_project_environment_name: str = Field(
72
+ ...,
73
+ description="Name of the Organization Environment that scoped the search result.",
74
+ )
59
75
  semantic_score: float = Field(
60
76
  ...,
61
77
  description="Vector similarity component of the semantic-search ranking.",
@@ -243,6 +259,15 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
243
259
  "agent_type": "str",
244
260
  "search": "str",
245
261
  }
262
+ READ_QUERY_PARAMS: ClassVar[dict[str, str]] = {
263
+ "organization_project_environment_uid": "uid",
264
+ }
265
+ READ_QUERY_PARAM_DESCRIPTIONS: ClassVar[dict[str, str]] = {
266
+ "organization_project_environment_uid": (
267
+ "Required Organization Environment boundary for Agent discovery. "
268
+ "This scopes reads and does not assign an environment to an Agent."
269
+ ),
270
+ }
246
271
 
247
272
  uid: str | None = Field(None, description="Public UID of the agent resource.")
248
273
  name: str = Field(
@@ -307,12 +332,34 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
307
332
  "ProjectBranch-scoped."
308
333
  ),
309
334
  )
335
+ repository_branch: str | None = Field(
336
+ ...,
337
+ description=(
338
+ "Read-only repository branch projected from the canonical ProjectBranch, "
339
+ "or null when the Agent is not ProjectBranch-scoped."
340
+ ),
341
+ )
342
+ organization_project_environment_uid: str | None = Field(
343
+ ...,
344
+ description=(
345
+ "Read-only public UID of the Organization Environment derived from the "
346
+ "canonical ProjectBranch, or null when the Agent is not environment-scoped."
347
+ ),
348
+ )
349
+ organization_project_environment_name: str | None = Field(
350
+ ...,
351
+ description=(
352
+ "Read-only name of the Organization Environment derived from the canonical "
353
+ "ProjectBranch, or null when the Agent is not environment-scoped."
354
+ ),
355
+ )
310
356
 
311
357
  @classmethod
312
358
  def semantic_search(
313
359
  cls,
314
360
  q: str,
315
361
  *,
362
+ organization_project_environment_uid: str,
316
363
  limit: int = 20,
317
364
  timeout=None,
318
365
  ) -> list[AgentSemanticSearchResult]:
@@ -321,7 +368,7 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
321
368
  POST <object_url>/semantic-search/
322
369
 
323
370
  Server behavior:
324
- - results stay scoped to the caller organization
371
+ - results stay scoped to the requested Organization Environment
325
372
  - returns ranked lightweight agent search rows, not full Agent records
326
373
  """
327
374
  q = (q or "").strip()
@@ -333,6 +380,10 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
333
380
  raise ValueError("limit must be between 1 and 100")
334
381
 
335
382
  body: dict[str, Any] = {
383
+ "organization_project_environment_uid": cls._coerce_filter_uid(
384
+ organization_project_environment_uid,
385
+ field_name="organization_project_environment_uid",
386
+ ),
336
387
  "q": q,
337
388
  "limit": limit,
338
389
  }
@@ -734,6 +734,26 @@ class JobRun(BaseObjectOrm, BasePydanticModel):
734
734
  description="Read-only helper field containing the associated job name.",
735
735
  examples=["daily-training-job"],
736
736
  )
737
+ project_uid: str | None = Field(
738
+ ...,
739
+ description="Read-only public UID of the associated project, or null for a run outside project scope.",
740
+ examples=["1d0530c0-65d1-4db0-856b-dc29d8260a09"],
741
+ )
742
+ project_name: str | None = Field(
743
+ ...,
744
+ description="Read-only name of the associated project, or null for a run outside project scope.",
745
+ examples=["market-data-service"],
746
+ )
747
+ project_branch_uid: str | None = Field(
748
+ ...,
749
+ description="Read-only public UID of the associated project branch, or null for an unscoped run.",
750
+ examples=["5a28020a-0f1b-47ee-aab8-334286234bea"],
751
+ )
752
+ project_branch_name: str | None = Field(
753
+ ...,
754
+ description="Read-only repository branch name associated with the run, or null for an unscoped run.",
755
+ examples=["main"],
756
+ )
737
757
 
738
758
  execution_start: datetime.datetime | None = Field(
739
759
  default=None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 6.0.32
3
+ Version: 6.0.34
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.32"
7
+ version = "6.0.34"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -508,6 +508,7 @@ def test_list_organization_teams_uses_client_model(cli_mod, monkeypatch):
508
508
  def test_list_agents_uses_client_model(cli_mod, monkeypatch):
509
509
  api_mod = importlib.import_module("mainsequence.cli.api")
510
510
  captured = {}
511
+ environment_uid = "22222222-2222-4222-8222-222222222222"
511
512
 
512
513
  class FakeAgent:
513
514
  def __init__(self, uid, name):
@@ -532,12 +533,19 @@ def test_list_agents_uses_client_model(cli_mod, monkeypatch):
532
533
 
533
534
  monkeypatch.setattr(api_mod, "_run_sdk_model_operation", _run_sdk_model_operation)
534
535
 
535
- out = api_mod.list_agents(timeout=9, filters={"agent_type": "custom"})
536
+ out = api_mod.list_agents(
537
+ organization_project_environment_uid=environment_uid,
538
+ timeout=9,
539
+ filters={"agent_type": "custom"},
540
+ )
536
541
  assert captured == {
537
542
  "module_name": "mainsequence.client.agent_runtime_models",
538
543
  "class_name": "Agent",
539
544
  "timeout": 9,
540
- "filters": {"agent_type": "custom"},
545
+ "filters": {
546
+ "agent_type": "custom",
547
+ "organization_project_environment_uid": environment_uid,
548
+ },
541
549
  }
542
550
  assert out == [
543
551
  {
@@ -590,6 +598,7 @@ def test_get_project_repository_uses_public_client_model(cli_mod, monkeypatch):
590
598
  def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
591
599
  api_mod = importlib.import_module("mainsequence.cli.api")
592
600
  captured = {}
601
+ environment_uid = "22222222-2222-4222-8222-222222222222"
593
602
 
594
603
  class FakeSearchResult:
595
604
  def __init__(self):
@@ -616,8 +625,18 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
616
625
 
617
626
  class _ClientAgent:
618
627
  @classmethod
619
- def semantic_search(cls, q, *, limit=20, timeout=None):
628
+ def semantic_search(
629
+ cls,
630
+ q,
631
+ *,
632
+ organization_project_environment_uid,
633
+ limit=20,
634
+ timeout=None,
635
+ ):
620
636
  captured["q"] = q
637
+ captured["organization_project_environment_uid"] = (
638
+ organization_project_environment_uid
639
+ )
621
640
  captured["limit"] = limit
622
641
  captured["timeout"] = timeout
623
642
  return [FakeSearchResult()]
@@ -628,6 +647,7 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
628
647
 
629
648
  out = api_mod.semantic_search_agents(
630
649
  "data research",
650
+ organization_project_environment_uid=environment_uid,
631
651
  limit=10,
632
652
  timeout=17,
633
653
  )
@@ -635,6 +655,7 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
635
655
  "module_name": "mainsequence.client.agent_runtime_models",
636
656
  "class_name": "Agent",
637
657
  "q": "data research",
658
+ "organization_project_environment_uid": environment_uid,
638
659
  "limit": 10,
639
660
  "timeout": 17,
640
661
  }
@@ -5633,6 +5654,9 @@ def test_list_project_job_runs_uses_client_model(cli_mod, monkeypatch):
5633
5654
 
5634
5655
  def test_get_project_job_run_logs_uses_client_model(cli_mod, monkeypatch):
5635
5656
  api_mod = importlib.import_module("mainsequence.cli.api")
5657
+ real_job_run = importlib.import_module(
5658
+ "mainsequence.client.models_helpers"
5659
+ ).JobRun
5636
5660
  captured = {}
5637
5661
 
5638
5662
  monkeypatch.setattr(
@@ -5658,22 +5682,38 @@ def test_get_project_job_run_logs_uses_client_model(cli_mod, monkeypatch):
5658
5682
  class FakeBaseObjectOrm:
5659
5683
  ROOT_URL = "https://old.test/api/v1"
5660
5684
 
5661
- class FakeJobRun:
5662
- ROOT_URL = "https://old.test/api/v1/job-runs"
5685
+ class CanonicalJobRun(real_job_run):
5663
5686
 
5664
5687
  @classmethod
5665
5688
  def get(cls, pk, timeout=None):
5666
5689
  captured["job_run_uid_arg"] = pk
5667
- return types.SimpleNamespace(
5668
- get_logs=lambda timeout=None: {
5669
- "job_run_uid": pk,
5690
+ return cls.model_validate(
5691
+ {
5692
+ "uid": pk,
5693
+ "name": "daily-run-1",
5694
+ "unique_identifier": "jobrun_abc123",
5695
+ "job_uid": "7d0ab07c-d1c0-4b7f-9c69-3c1a41c0a4da",
5696
+ "job_name": "daily-prices",
5697
+ "project_uid": "1d0530c0-65d1-4db0-856b-dc29d8260a09",
5698
+ "project_name": "market-data-service",
5699
+ "project_branch_uid": "5a28020a-0f1b-47ee-aab8-334286234bea",
5700
+ "project_branch_name": "main",
5670
5701
  "status": "RUNNING",
5671
- "rows": ["first line"],
5702
+ "runtime_image_uid": "6cfdb152-923e-45b9-a150-c4541c68b0d1",
5703
+ "runtime_image_digest": "sha256:" + "b" * 64,
5672
5704
  }
5673
5705
  )
5674
5706
 
5707
+ def get_logs(self, *, timeout=None):
5708
+ captured["get_logs_timeout"] = timeout
5709
+ return {
5710
+ "job_run_uid": self.uid,
5711
+ "status": self.status,
5712
+ "rows": ["first line"],
5713
+ }
5714
+
5675
5715
  fake_base.BaseObjectOrm = FakeBaseObjectOrm
5676
- fake_helpers.JobRun = FakeJobRun
5716
+ fake_helpers.JobRun = CanonicalJobRun
5677
5717
  fake_client_pkg.utils = fake_utils
5678
5718
 
5679
5719
  monkeypatch.setitem(sys.modules, "mainsequence.client", fake_client_pkg)
@@ -5683,6 +5723,7 @@ def test_get_project_job_run_logs_uses_client_model(cli_mod, monkeypatch):
5683
5723
 
5684
5724
  out = api_mod.get_project_job_run_logs("4c1d77c8-8a42-42b8-a9c1-06be9a336e5d")
5685
5725
  assert captured["job_run_uid_arg"] == "4c1d77c8-8a42-42b8-a9c1-06be9a336e5d"
5726
+ assert captured["get_logs_timeout"] is None
5686
5727
  assert captured["jwt"] == ("acc", "ref")
5687
5728
  assert out == {
5688
5729
  "job_run_uid": "4c1d77c8-8a42-42b8-a9c1-06be9a336e5d",
@@ -6249,11 +6290,12 @@ def test_project_project_resource_delete_fastapi_requires_confirmation(
6249
6290
 
6250
6291
 
6251
6292
  def test_agent_list(cli_mod, runner, monkeypatch):
6293
+ environment_uid = "22222222-2222-4222-8222-222222222222"
6252
6294
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6253
6295
  monkeypatch.setattr(
6254
6296
  cli_mod,
6255
6297
  "list_agents",
6256
- lambda timeout=None, filters=None: [
6298
+ lambda organization_project_environment_uid, timeout=None, filters=None: [
6257
6299
  {
6258
6300
  "uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
6259
6301
  "name": "Research Copilot",
@@ -6267,7 +6309,10 @@ def test_agent_list(cli_mod, runner, monkeypatch):
6267
6309
  ],
6268
6310
  )
6269
6311
 
6270
- result = runner.invoke(cli_mod.app, ["agent", "list"])
6312
+ result = runner.invoke(
6313
+ cli_mod.app,
6314
+ ["agent", "list", "--environment-uid", environment_uid],
6315
+ )
6271
6316
  assert result.exit_code == 0
6272
6317
  assert "Agents" in result.output
6273
6318
  assert "UID" in result.output
@@ -6278,11 +6323,12 @@ def test_agent_list(cli_mod, runner, monkeypatch):
6278
6323
 
6279
6324
 
6280
6325
  def test_agent_list_json(cli_mod, runner, monkeypatch):
6326
+ environment_uid = "22222222-2222-4222-8222-222222222222"
6281
6327
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6282
6328
  monkeypatch.setattr(
6283
6329
  cli_mod,
6284
6330
  "list_agents",
6285
- lambda timeout=None, filters=None: [
6331
+ lambda organization_project_environment_uid, timeout=None, filters=None: [
6286
6332
  {
6287
6333
  "uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
6288
6334
  "name": "Research Copilot",
@@ -6296,7 +6342,10 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
6296
6342
  ],
6297
6343
  )
6298
6344
 
6299
- result = runner.invoke(cli_mod.app, ["agent", "list", "--json"])
6345
+ result = runner.invoke(
6346
+ cli_mod.app,
6347
+ ["agent", "list", "--environment-uid", environment_uid, "--json"],
6348
+ )
6300
6349
  assert result.exit_code == 0
6301
6350
  payload = json.loads(result.output)
6302
6351
  assert payload[0]["uid"] == "e0e75693-4110-464c-93e0-82c7fd9c9a23"
@@ -6305,12 +6354,14 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
6305
6354
 
6306
6355
  def test_agent_search(cli_mod, runner, monkeypatch):
6307
6356
  captured = {}
6357
+ environment_uid = "22222222-2222-4222-8222-222222222222"
6308
6358
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6309
6359
 
6310
- def _search(q, *, limit=20, timeout=None):
6360
+ def _search(q, *, organization_project_environment_uid, limit=20, timeout=None):
6311
6361
  captured.update(
6312
6362
  {
6313
6363
  "q": q,
6364
+ "organization_project_environment_uid": organization_project_environment_uid,
6314
6365
  "limit": limit,
6315
6366
  "timeout": timeout,
6316
6367
  }
@@ -6334,6 +6385,8 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6334
6385
  "agent",
6335
6386
  "search",
6336
6387
  "data research",
6388
+ "--environment-uid",
6389
+ environment_uid,
6337
6390
  "--limit",
6338
6391
  "10",
6339
6392
  "--timeout",
@@ -6343,6 +6396,7 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6343
6396
  assert result.exit_code == 0
6344
6397
  assert captured == {
6345
6398
  "q": "data research",
6399
+ "organization_project_environment_uid": environment_uid,
6346
6400
  "limit": 10,
6347
6401
  "timeout": 17,
6348
6402
  }
@@ -6356,6 +6410,7 @@ def test_agent_search(cli_mod, runner, monkeypatch):
6356
6410
 
6357
6411
 
6358
6412
  def test_agent_search_json(cli_mod, runner, monkeypatch):
6413
+ environment_uid = "22222222-2222-4222-8222-222222222222"
6359
6414
  monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
6360
6415
  monkeypatch.setattr(
6361
6416
  cli_mod,
@@ -6372,7 +6427,17 @@ def test_agent_search_json(cli_mod, runner, monkeypatch):
6372
6427
  ],
6373
6428
  )
6374
6429
 
6375
- result = runner.invoke(cli_mod.app, ["agent", "search", "data research", "--json"])
6430
+ result = runner.invoke(
6431
+ cli_mod.app,
6432
+ [
6433
+ "agent",
6434
+ "search",
6435
+ "data research",
6436
+ "--environment-uid",
6437
+ environment_uid,
6438
+ "--json",
6439
+ ],
6440
+ )
6376
6441
  assert result.exit_code == 0
6377
6442
  payload = json.loads(result.output)
6378
6443
  assert payload[0]["uid"] == "e0e75693-4110-464c-93e0-82c7fd9c9a23"