mainsequence 4.4.22__tar.gz → 4.4.23__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 (161) hide show
  1. {mainsequence-4.4.22/mainsequence.egg-info → mainsequence-4.4.23}/PKG-INFO +1 -1
  2. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/a2a_communication/SKILL.md +103 -0
  3. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/cli.py +97 -5
  4. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/config.py +73 -0
  5. {mainsequence-4.4.22 → mainsequence-4.4.23/mainsequence.egg-info}/PKG-INFO +1 -1
  6. {mainsequence-4.4.22 → mainsequence-4.4.23}/pyproject.toml +1 -1
  7. {mainsequence-4.4.22 → mainsequence-4.4.23}/LICENSE +0 -0
  8. {mainsequence-4.4.22 → mainsequence-4.4.23}/README.md +0 -0
  9. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/AGENTS.md +0 -0
  10. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  11. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
  12. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  13. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  14. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/widgets/app_components/SKILL.md +0 -0
  15. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/widgets/tables/SKILL.md +0 -0
  16. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/widgets/tabular_transform/SKILL.md +0 -0
  17. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  18. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  19. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  20. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  21. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  22. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  23. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  24. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  25. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  26. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  27. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  28. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  29. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  30. {mainsequence-4.4.22 → mainsequence-4.4.23}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  31. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/__init__.py +0 -0
  32. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/__main__.py +0 -0
  33. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/bootstrap.py +0 -0
  34. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/__init__.py +0 -0
  35. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/api.py +0 -0
  36. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/browser_auth.py +0 -0
  37. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/docker_utils.py +0 -0
  38. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/doctor.py +0 -0
  39. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/local_ops.py +0 -0
  40. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/migrations.py +0 -0
  41. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/model_filters.py +0 -0
  42. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/project_status.py +0 -0
  43. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/pydantic_cli.py +0 -0
  44. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/sdk_utils.py +0 -0
  45. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/ssh_utils.py +0 -0
  46. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/cli/ui.py +0 -0
  47. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/__init__.py +0 -0
  48. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/agent_runtime_models.py +0 -0
  49. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/base.py +0 -0
  50. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/client.py +0 -0
  51. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/__init__.py +0 -0
  52. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/app_component.py +0 -0
  53. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/connections.py +0 -0
  54. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/__init__.py +0 -0
  55. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/adapter_from_api.py +0 -0
  56. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/response_mapping.py +0 -0
  57. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/table_visuals.py +0 -0
  58. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/tabular.py +0 -0
  59. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/contracts/ui.py +0 -0
  60. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/data_models.py +0 -0
  61. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/providers/__init__.py +0 -0
  62. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/providers/adapter_from_api.py +0 -0
  63. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/__init__.py +0 -0
  64. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/bindings.py +0 -0
  65. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/connection_query.py +0 -0
  66. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/registry.py +0 -0
  67. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/table.py +0 -0
  68. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/widgets/tabular_transform.py +0 -0
  69. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/workspace.py +0 -0
  70. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  71. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/workspaces/__init__.py +0 -0
  72. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/workspaces/documents.py +0 -0
  73. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/command_center/workspaces/mounted_widgets.py +0 -0
  74. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/compute_validation.py +0 -0
  75. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  76. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  77. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  78. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  79. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/dtype_codec.py +0 -0
  80. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/exceptions.py +0 -0
  81. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/fastapi/__init__.py +0 -0
  82. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/fastapi/auth.py +0 -0
  83. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/metatables/__init__.py +0 -0
  84. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/metatables/core.py +0 -0
  85. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/models_foundry.py +0 -0
  86. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/models_helpers.py +0 -0
  87. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/models_user.py +0 -0
  88. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/client/utils.py +0 -0
  89. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/defaults.py +0 -0
  90. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/instrumentation/__init__.py +0 -0
  91. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/instrumentation/utils.py +0 -0
  92. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/logconf.py +0 -0
  93. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/__init__.py +0 -0
  94. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/__main__.py +0 -0
  95. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  96. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  97. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  98. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  99. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
  100. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  101. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  102. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
  103. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  104. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  105. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/future_registry.py +0 -0
  106. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/hashing.py +0 -0
  107. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  108. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  109. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/env.py +0 -0
  110. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/provider.py +0 -0
  111. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/registry.py +0 -0
  112. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  113. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  114. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  115. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  116. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  117. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/schema_names.py +0 -0
  118. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  119. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/runtime_flags.py +0 -0
  120. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence/scaffold_skills.py +0 -0
  121. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence.egg-info/SOURCES.txt +0 -0
  122. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence.egg-info/dependency_links.txt +0 -0
  123. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence.egg-info/entry_points.txt +0 -0
  124. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence.egg-info/requires.txt +0 -0
  125. {mainsequence-4.4.22 → mainsequence-4.4.23}/mainsequence.egg-info/top_level.txt +0 -0
  126. {mainsequence-4.4.22 → mainsequence-4.4.23}/setup.cfg +0 -0
  127. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_auth_precedence.py +0 -0
  128. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_build_operations_hashing.py +0 -0
  129. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_cli.py +0 -0
  130. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_cli_browser_auth.py +0 -0
  131. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_cli_migrations.py +0 -0
  132. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_client.py +0 -0
  133. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_command_center_app_component_models.py +0 -0
  134. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_command_center_data_models.py +0 -0
  135. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_command_center_models.py +0 -0
  136. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_command_center_table_contracts.py +0 -0
  137. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_command_center_tabular_transform.py +0 -0
  138. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  139. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_data_node_storage_dimension_queries.py +0 -0
  140. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_data_node_update_flow.py +0 -0
  141. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_dependency_extras.py +0 -0
  142. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_duckdb_interface_dimensions.py +0 -0
  143. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_filter_normalization.py +0 -0
  144. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_instrumentation.py +0 -0
  145. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_logconf.py +0 -0
  146. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_meta_table_migrations.py +0 -0
  147. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_meta_tables_client_models.py +0 -0
  148. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  149. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_models_user_request_bound_auth.py +0 -0
  150. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_pod_project_resolution.py +0 -0
  151. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_project_batch_jobs_from_file.py +0 -0
  152. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_run_configuration.py +0 -0
  153. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_scaffold_skills.py +0 -0
  154. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_schema_names.py +0 -0
  155. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_secret_client_model.py +0 -0
  156. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_source_table_configuration.py +0 -0
  157. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_sqlite_interface_dimensions.py +0 -0
  158. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_update_runner_uid_runtime.py +0 -0
  159. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_update_statistics.py +0 -0
  160. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_update_uid_guards.py +0 -0
  161. {mainsequence-4.4.22 → mainsequence-4.4.23}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.4.22
3
+ Version: 4.4.23
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -105,6 +105,109 @@ mainsequence agent session a2a send \
105
105
  --message "Now identify the highest priority follow-up."
106
106
  ```
107
107
 
108
+ ## Handle Shortcut Helper
109
+
110
+ For repeated communication with the same target agent, use a stable handle. On
111
+ first use, include the target agent UID so the CLI can create or resolve the
112
+ target session and cache the returned session UID:
113
+
114
+ ```bash
115
+ mainsequence agent session a2a send \
116
+ <stable_handle_unique_id> \
117
+ --target-agent-uid <target_agent_uid> \
118
+ --message "Return a JSON object with keys: summary, risk_level, next_action." \
119
+ --strict-dictionary
120
+ ```
121
+
122
+ `--name` is optional and only affects the session if the backend creates it:
123
+
124
+ ```bash
125
+ mainsequence agent session a2a send \
126
+ portfolios \
127
+ --target-agent-uid <target_agent_uid> \
128
+ --name "Portfolio analysis" \
129
+ --message "Return a JSON object with keys: summary, risk_level, next_action." \
130
+ --strict-dictionary
131
+ ```
132
+
133
+ After the handle is cached, reuse it without the target agent UID:
134
+
135
+ ```bash
136
+ mainsequence agent session a2a send \
137
+ portfolios \
138
+ --message "Now identify the highest priority follow-up." \
139
+ --strict-dictionary
140
+ ```
141
+
142
+ ## Python Usage
143
+
144
+ In Python, use the backend handle to get or create the target session, then
145
+ reuse the returned session UID for every message in the same conversation. The
146
+ binding is:
147
+
148
+ ```text
149
+ handle_unique_id -> AgentSession.uid -> A2A message.contextId
150
+ ```
151
+
152
+ Direct SDK flow:
153
+
154
+ ```python
155
+ from mainsequence.client.agent_runtime_models import Agent, AgentSession
156
+
157
+
158
+ agent = Agent.get_by_uid(target_agent_uid)
159
+ session = agent.get_or_create_session(
160
+ handle_unique_id="portfolios",
161
+ name="Portfolio analysis",
162
+ )
163
+
164
+ response = AgentSession.send_a2a_message(
165
+ session.uid,
166
+ message="Return a JSON object with keys: summary, risk_level, next_action.",
167
+ strict_dictionary=True,
168
+ )
169
+ ```
170
+
171
+ For another message in the same conversation, reuse the same `session.uid`:
172
+
173
+ ```python
174
+ response = AgentSession.send_a2a_message(
175
+ session.uid,
176
+ message="Now identify the highest priority follow-up.",
177
+ strict_dictionary=True,
178
+ )
179
+ ```
180
+
181
+ Reusable helper:
182
+
183
+ ```python
184
+ from mainsequence.client.agent_runtime_models import Agent, AgentSession
185
+
186
+
187
+ def send_to_agent_handle(
188
+ target_agent_uid: str,
189
+ handle_unique_id: str,
190
+ message: str,
191
+ *,
192
+ name: str | None = None,
193
+ strict_dictionary: bool = False,
194
+ ):
195
+ agent = Agent.get_by_uid(target_agent_uid)
196
+ session = agent.get_or_create_session(
197
+ handle_unique_id=handle_unique_id,
198
+ name=name,
199
+ )
200
+
201
+ return AgentSession.send_a2a_message(
202
+ session.uid, # The SDK sends this as A2A message.contextId.
203
+ message=message,
204
+ strict_dictionary=strict_dictionary,
205
+ )
206
+ ```
207
+
208
+ Use the same `handle_unique_id` for the same target conversation. Use a new
209
+ handle for a different task or conversation.
210
+
108
211
  ## Response Handling
109
212
 
110
213
  - Parse the CLI output as the standard A2A JSON response.
@@ -3829,9 +3829,73 @@ def _extract_standard_a2a_message_text(payload: dict[str, object]) -> str:
3829
3829
  return "".join(chunks)
3830
3830
 
3831
3831
 
3832
+ def _looks_like_uuid(value: str) -> bool:
3833
+ try:
3834
+ uuid.UUID(str(value))
3835
+ return True
3836
+ except (TypeError, ValueError):
3837
+ return False
3838
+
3839
+
3840
+ def _resolve_agent_session_uid_or_handle(
3841
+ target: str,
3842
+ *,
3843
+ target_agent_uid: str | None,
3844
+ name: str | None,
3845
+ parent_session_uid: str | None,
3846
+ timeout: int | None,
3847
+ ) -> str:
3848
+ resolved_target = str(target or "").strip()
3849
+ if not resolved_target:
3850
+ error("agent session UID or handle is required.")
3851
+ raise typer.Exit(1)
3852
+ if _looks_like_uuid(resolved_target):
3853
+ return resolved_target
3854
+
3855
+ resolved_agent_uid = str(target_agent_uid or "").strip()
3856
+ if not resolved_agent_uid:
3857
+ cached = cfg.get_a2a_handle_cache(resolved_target)
3858
+ cached_session_uid = str((cached or {}).get("agent_session_uid") or "").strip()
3859
+ if cached_session_uid:
3860
+ return cached_session_uid
3861
+ error(
3862
+ f"No cached A2A session for handle '{resolved_target}'. "
3863
+ "Pass --target-agent-uid once to create or resolve it."
3864
+ )
3865
+ raise typer.Exit(1)
3866
+
3867
+ try:
3868
+ agent_session_payload = get_or_create_agent_session(
3869
+ resolved_agent_uid,
3870
+ handle_unique_id=resolved_target,
3871
+ name=name,
3872
+ parent_session_uid=parent_session_uid,
3873
+ timeout=timeout,
3874
+ )
3875
+ except ApiError as e:
3876
+ error(f"Agent session handle resolution failed: {e}")
3877
+ raise typer.Exit(1) from e
3878
+
3879
+ agent_session_uid = str(agent_session_payload.get("uid") or "").strip()
3880
+ if not agent_session_uid:
3881
+ error("Agent session handle resolution did not return a session UID.")
3882
+ raise typer.Exit(1)
3883
+
3884
+ cfg.save_a2a_handle_cache(
3885
+ resolved_target,
3886
+ agent_uid=resolved_agent_uid,
3887
+ agent_session_uid=agent_session_uid,
3888
+ name=name,
3889
+ )
3890
+ return agent_session_uid
3891
+
3892
+
3832
3893
  def _agent_session_a2a_send_impl(
3833
3894
  *,
3834
- agent_session_uid: str,
3895
+ agent_session_uid_or_handle: str,
3896
+ target_agent_uid: str | None,
3897
+ name: str | None,
3898
+ parent_session_uid: str | None,
3835
3899
  message: str | None,
3836
3900
  message_file: pathlib.Path | None,
3837
3901
  strict_dictionary: bool,
@@ -3860,6 +3924,13 @@ def _agent_session_a2a_send_impl(
3860
3924
  effective_message_id = f"msg-{uuid.uuid4()}"
3861
3925
 
3862
3926
  _require_login()
3927
+ agent_session_uid = _resolve_agent_session_uid_or_handle(
3928
+ agent_session_uid_or_handle,
3929
+ target_agent_uid=target_agent_uid,
3930
+ name=name,
3931
+ parent_session_uid=parent_session_uid,
3932
+ timeout=timeout,
3933
+ )
3863
3934
 
3864
3935
  try:
3865
3936
  response_payload = send_agent_session_a2a_message(
@@ -6677,8 +6748,26 @@ def agent_session_get_or_create_cmd(
6677
6748
 
6678
6749
  @agent_session_a2a_group.command("send")
6679
6750
  def agent_session_a2a_send_cmd(
6680
- agent_session_uid: str = pydantic_argument(
6681
- AGENT_SESSION_MODEL_REF, "uid", ..., help="Agent session UID."
6751
+ agent_session_uid_or_handle: str = pydantic_argument(
6752
+ AGENT_SESSION_MODEL_REF,
6753
+ "uid",
6754
+ ...,
6755
+ help="Agent session UID, or cached A2A handle.",
6756
+ ),
6757
+ target_agent_uid: str | None = typer.Option(
6758
+ None,
6759
+ "--target-agent-uid",
6760
+ help="Target agent UID used to create or resolve a handle on first use.",
6761
+ ),
6762
+ name: str | None = typer.Option(
6763
+ None,
6764
+ "--name",
6765
+ help="Optional session name used only when resolving a handle with --target-agent-uid.",
6766
+ ),
6767
+ parent_session_uid: str | None = typer.Option(
6768
+ None,
6769
+ "--parent-session-uid",
6770
+ help="Optional parent session UID used only when resolving a handle with --target-agent-uid.",
6682
6771
  ),
6683
6772
  message: str | None = typer.Option(
6684
6773
  None,
@@ -6713,10 +6802,13 @@ def agent_session_a2a_send_cmd(
6713
6802
  timeout: int | None = typer.Option(None, "--timeout", help="Request timeout in seconds"),
6714
6803
  ):
6715
6804
  """
6716
- Send one standard A2A message to an existing agent session.
6805
+ Send one standard A2A message to an existing session UID or cached handle.
6717
6806
  """
6718
6807
  _agent_session_a2a_send_impl(
6719
- agent_session_uid=agent_session_uid,
6808
+ agent_session_uid_or_handle=agent_session_uid_or_handle,
6809
+ target_agent_uid=target_agent_uid,
6810
+ name=name,
6811
+ parent_session_uid=parent_session_uid,
6720
6812
  message=message,
6721
6813
  message_file=message_file,
6722
6814
  strict_dictionary=strict_dictionary,
@@ -55,6 +55,7 @@ SESSION_OVERRIDES_DIR = CFG_DIR / "session_overrides"
55
55
  TOKENS_JSON = CFG_DIR / "token.json"
56
56
  AUTH_JSON = CFG_DIR / "auth.json"
57
57
  RUNTIME_ACCESS_CACHE_JSON = CFG_DIR / "runtime_access_cache.json"
58
+ A2A_HANDLE_CACHE_JSON = CFG_DIR / "a2a_handle_cache.json"
58
59
 
59
60
  # Session-scoped auth environment variables (no token file persistence).
60
61
  ENV_USERNAME = "MAINSEQUENCE_USERNAME"
@@ -469,6 +470,78 @@ def clear_runtime_access_cache(
469
470
  return False
470
471
 
471
472
 
473
+ def _a2a_handle_cache_key(handle_unique_id: str, backend: str | None = None) -> str:
474
+ backend_key = _auth_backend_key(backend)
475
+ raw = f"{backend_key}|{_runtime_access_user_key()}|{str(handle_unique_id).strip()}"
476
+ return hashlib.sha256(raw.encode("utf-8")).hexdigest()
477
+
478
+
479
+ def _read_a2a_handle_cache() -> dict:
480
+ data = read_json(A2A_HANDLE_CACHE_JSON, {})
481
+ if not isinstance(data, dict):
482
+ return {"version": 1, "entries": {}}
483
+ entries = data.get("entries")
484
+ if not isinstance(entries, dict):
485
+ entries = {}
486
+ return {"version": 1, "entries": entries}
487
+
488
+
489
+ def _write_a2a_handle_cache(data: dict) -> None:
490
+ write_json(A2A_HANDLE_CACHE_JSON, data)
491
+ if os.name == "posix":
492
+ try:
493
+ os.chmod(A2A_HANDLE_CACHE_JSON, 0o600)
494
+ except Exception:
495
+ pass
496
+
497
+
498
+ def get_a2a_handle_cache(
499
+ handle_unique_id: str,
500
+ *,
501
+ backend: str | None = None,
502
+ ) -> dict | None:
503
+ """
504
+ Return a cached A2A handle mapping scoped by backend and current user.
505
+ """
506
+ handle = str(handle_unique_id or "").strip()
507
+ if not handle:
508
+ return None
509
+ cache = _read_a2a_handle_cache()
510
+ entry = cache["entries"].get(_a2a_handle_cache_key(handle, backend))
511
+ return dict(entry) if isinstance(entry, dict) else None
512
+
513
+
514
+ def save_a2a_handle_cache(
515
+ handle_unique_id: str,
516
+ *,
517
+ agent_uid: str,
518
+ agent_session_uid: str,
519
+ name: str | None = None,
520
+ backend: str | None = None,
521
+ ) -> dict:
522
+ """
523
+ Cache an A2A handle to the backend AgentSession UID it resolves to.
524
+ """
525
+ handle = str(handle_unique_id or "").strip()
526
+ if not handle:
527
+ raise ValueError("handle_unique_id is required")
528
+
529
+ now = time.time()
530
+ entry = {
531
+ "backend_url": _auth_backend_key(backend),
532
+ "handle_unique_id": handle,
533
+ "agent_uid": str(agent_uid),
534
+ "agent_session_uid": str(agent_session_uid),
535
+ "name": str(name) if name is not None else None,
536
+ "cached_at_epoch": now,
537
+ "cached_at": _iso_utc_from_epoch(now),
538
+ }
539
+ cache = _read_a2a_handle_cache()
540
+ cache["entries"][_a2a_handle_cache_key(handle, backend)] = entry
541
+ _write_a2a_handle_cache(cache)
542
+ return dict(entry)
543
+
544
+
472
545
  def _keychain_account_for_backend(backend: str | None = None) -> str:
473
546
  """
474
547
  Return the backend-scoped keychain account name.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.4.22
3
+ Version: 4.4.23
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "4.4.22"
7
+ version = "4.4.23"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
File without changes
File without changes
File without changes