mainsequence 4.4.22__tar.gz → 4.4.24__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.
- {mainsequence-4.4.22/mainsequence.egg-info → mainsequence-4.4.24}/PKG-INFO +1 -1
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/a2a_communication/SKILL.md +149 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/api.py +4 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/cli.py +126 -5
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/config.py +73 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/agent_runtime_models.py +51 -1
- {mainsequence-4.4.22 → mainsequence-4.4.24/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-4.4.22 → mainsequence-4.4.24}/pyproject.toml +1 -1
- {mainsequence-4.4.22 → mainsequence-4.4.24}/LICENSE +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/README.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/widgets/app_components/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/widgets/tables/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/widgets/tabular_transform/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/__main__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/base.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/client.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/adapter_from_api.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/response_mapping.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/table_visuals.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/tabular.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/ui.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/providers/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/providers/adapter_from_api.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/bindings.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/connection_query.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/registry.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/table.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/tabular_transform.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspaces/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspaces/documents.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspaces/mounted_widgets.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/metatables/core.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/defaults.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/logconf.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/setup.cfg +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_auth_precedence.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_cli.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_cli_migrations.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_client.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_table_contracts.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_tabular_transform.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_data_access_mixin_dimension_audit.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_data_node_storage_dimension_queries.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_data_node_update_flow.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_dependency_extras.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_filter_normalization.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_instrumentation.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_logconf.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_meta_tables_client_models.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_run_configuration.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_schema_names.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_secret_client_model.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_update_statistics.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_update_uid_guards.py +0 -0
- {mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_workspace_snapshot.py +0 -0
{mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/a2a_communication/SKILL.md
RENAMED
|
@@ -105,6 +105,155 @@ 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
|
+
## Send Files
|
|
143
|
+
|
|
144
|
+
A2A can send inline files as raw parts. For PDFs, use `--file`; the CLI reads
|
|
145
|
+
the file bytes, enforces the 15 MiB inline limit, base64 encodes the bytes, and
|
|
146
|
+
sends the part with `filename` and `mediaType`.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
mainsequence agent session a2a send \
|
|
150
|
+
<target_agent_session_uid> \
|
|
151
|
+
--message "Please summarize this PDF." \
|
|
152
|
+
--file report.pdf \
|
|
153
|
+
--media-type application/pdf
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The same handle shortcut works with files:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
mainsequence agent session a2a send \
|
|
160
|
+
portfolios \
|
|
161
|
+
--message "Please summarize this PDF." \
|
|
162
|
+
--file report.pdf \
|
|
163
|
+
--media-type application/pdf
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
For retries of the exact same message and file attachment, reuse the same
|
|
167
|
+
`--message-id`.
|
|
168
|
+
|
|
169
|
+
## Python Usage
|
|
170
|
+
|
|
171
|
+
In Python, use the backend handle to get or create the target session, then
|
|
172
|
+
reuse the returned session UID for every message in the same conversation. The
|
|
173
|
+
binding is:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
handle_unique_id -> AgentSession.uid -> A2A message.contextId
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Direct SDK flow:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from mainsequence.client.agent_runtime_models import Agent, AgentSession
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
agent = Agent.get_by_uid(target_agent_uid)
|
|
186
|
+
session = agent.get_or_create_session(
|
|
187
|
+
handle_unique_id="portfolios",
|
|
188
|
+
name="Portfolio analysis",
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
response = AgentSession.send_a2a_message(
|
|
192
|
+
session.uid,
|
|
193
|
+
message="Return a JSON object with keys: summary, risk_level, next_action.",
|
|
194
|
+
strict_dictionary=True,
|
|
195
|
+
)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
For another message in the same conversation, reuse the same `session.uid`:
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
response = AgentSession.send_a2a_message(
|
|
202
|
+
session.uid,
|
|
203
|
+
message="Now identify the highest priority follow-up.",
|
|
204
|
+
strict_dictionary=True,
|
|
205
|
+
)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
To send a PDF, pass a file attachment. The SDK reads the raw bytes, enforces the
|
|
209
|
+
15 MiB inline limit, base64 encodes them, and sends `filename` plus `mediaType`:
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
response = AgentSession.send_a2a_message(
|
|
213
|
+
session.uid,
|
|
214
|
+
message="Please summarize this PDF.",
|
|
215
|
+
files=[
|
|
216
|
+
{
|
|
217
|
+
"path": "report.pdf",
|
|
218
|
+
"media_type": "application/pdf",
|
|
219
|
+
"filename": "report.pdf",
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Reusable helper:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from mainsequence.client.agent_runtime_models import Agent, AgentSession
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def send_to_agent_handle(
|
|
232
|
+
target_agent_uid: str,
|
|
233
|
+
handle_unique_id: str,
|
|
234
|
+
message: str,
|
|
235
|
+
*,
|
|
236
|
+
name: str | None = None,
|
|
237
|
+
files: list[dict[str, str]] | None = None,
|
|
238
|
+
strict_dictionary: bool = False,
|
|
239
|
+
):
|
|
240
|
+
agent = Agent.get_by_uid(target_agent_uid)
|
|
241
|
+
session = agent.get_or_create_session(
|
|
242
|
+
handle_unique_id=handle_unique_id,
|
|
243
|
+
name=name,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
return AgentSession.send_a2a_message(
|
|
247
|
+
session.uid, # The SDK sends this as A2A message.contextId.
|
|
248
|
+
message=message,
|
|
249
|
+
files=files,
|
|
250
|
+
strict_dictionary=strict_dictionary,
|
|
251
|
+
)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Use the same `handle_unique_id` for the same target conversation. Use a new
|
|
255
|
+
handle for a different task or conversation.
|
|
256
|
+
|
|
108
257
|
## Response Handling
|
|
109
258
|
|
|
110
259
|
- Parse the CLI output as the standard A2A JSON response.
|
|
@@ -1244,6 +1244,7 @@ def send_agent_session_a2a_message(
|
|
|
1244
1244
|
agent_session_uid: str,
|
|
1245
1245
|
*,
|
|
1246
1246
|
message: str,
|
|
1247
|
+
files: list[dict[str, Any]] | None = None,
|
|
1247
1248
|
message_id: str | None = None,
|
|
1248
1249
|
strict_dictionary: bool = False,
|
|
1249
1250
|
json_repair_attempts: int = 3,
|
|
@@ -1262,6 +1263,7 @@ def send_agent_session_a2a_message(
|
|
|
1262
1263
|
ClientAgentSession,
|
|
1263
1264
|
agent_session_uid=str(agent_session_uid),
|
|
1264
1265
|
message=message,
|
|
1266
|
+
files=files,
|
|
1265
1267
|
message_id=message_id,
|
|
1266
1268
|
cached_runtime_access=cached_runtime_access,
|
|
1267
1269
|
strict_dictionary=strict_dictionary,
|
|
@@ -1287,6 +1289,7 @@ def _send_agent_session_a2a_message_with_cache(
|
|
|
1287
1289
|
*,
|
|
1288
1290
|
agent_session_uid: str,
|
|
1289
1291
|
message: str,
|
|
1292
|
+
files: list[dict[str, Any]] | None,
|
|
1290
1293
|
message_id: str | None,
|
|
1291
1294
|
cached_runtime_access: dict[str, Any] | None,
|
|
1292
1295
|
strict_dictionary: bool,
|
|
@@ -1300,6 +1303,7 @@ def _send_agent_session_a2a_message_with_cache(
|
|
|
1300
1303
|
payload = ClientAgentSession.send_a2a_message(
|
|
1301
1304
|
agent_session_uid,
|
|
1302
1305
|
message=message,
|
|
1306
|
+
files=files,
|
|
1303
1307
|
message_id=message_id,
|
|
1304
1308
|
strict_dictionary=strict_dictionary,
|
|
1305
1309
|
json_repair_attempts=json_repair_attempts,
|
|
@@ -3829,11 +3829,77 @@ 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
|
-
|
|
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,
|
|
3901
|
+
files: list[pathlib.Path] | None,
|
|
3902
|
+
media_types: list[str] | None,
|
|
3837
3903
|
strict_dictionary: bool,
|
|
3838
3904
|
json_repair_attempts: int,
|
|
3839
3905
|
message_id: str | None,
|
|
@@ -3855,16 +3921,38 @@ def _agent_session_a2a_send_impl(
|
|
|
3855
3921
|
if json_repair_attempts < 1:
|
|
3856
3922
|
error("--json-repair-attempts must be greater than 0.")
|
|
3857
3923
|
raise typer.Exit(1)
|
|
3924
|
+
attachment_paths = list(files or [])
|
|
3925
|
+
attachment_media_types = list(media_types or [])
|
|
3926
|
+
if attachment_media_types and len(attachment_media_types) != len(attachment_paths):
|
|
3927
|
+
error("--media-type must be provided once per --file when used.")
|
|
3928
|
+
raise typer.Exit(1)
|
|
3929
|
+
attachments = [
|
|
3930
|
+
{
|
|
3931
|
+
"path": str(path),
|
|
3932
|
+
"media_type": attachment_media_types[index]
|
|
3933
|
+
if attachment_media_types
|
|
3934
|
+
else "application/pdf",
|
|
3935
|
+
}
|
|
3936
|
+
for index, path in enumerate(attachment_paths)
|
|
3937
|
+
]
|
|
3858
3938
|
effective_message_id = str(message_id).strip() if message_id is not None else ""
|
|
3859
3939
|
if not effective_message_id:
|
|
3860
3940
|
effective_message_id = f"msg-{uuid.uuid4()}"
|
|
3861
3941
|
|
|
3862
3942
|
_require_login()
|
|
3943
|
+
agent_session_uid = _resolve_agent_session_uid_or_handle(
|
|
3944
|
+
agent_session_uid_or_handle,
|
|
3945
|
+
target_agent_uid=target_agent_uid,
|
|
3946
|
+
name=name,
|
|
3947
|
+
parent_session_uid=parent_session_uid,
|
|
3948
|
+
timeout=timeout,
|
|
3949
|
+
)
|
|
3863
3950
|
|
|
3864
3951
|
try:
|
|
3865
3952
|
response_payload = send_agent_session_a2a_message(
|
|
3866
3953
|
agent_session_uid,
|
|
3867
3954
|
message=resolved_message,
|
|
3955
|
+
files=attachments,
|
|
3868
3956
|
message_id=effective_message_id,
|
|
3869
3957
|
strict_dictionary=strict_dictionary,
|
|
3870
3958
|
json_repair_attempts=json_repair_attempts,
|
|
@@ -6677,8 +6765,26 @@ def agent_session_get_or_create_cmd(
|
|
|
6677
6765
|
|
|
6678
6766
|
@agent_session_a2a_group.command("send")
|
|
6679
6767
|
def agent_session_a2a_send_cmd(
|
|
6680
|
-
|
|
6681
|
-
AGENT_SESSION_MODEL_REF,
|
|
6768
|
+
agent_session_uid_or_handle: str = pydantic_argument(
|
|
6769
|
+
AGENT_SESSION_MODEL_REF,
|
|
6770
|
+
"uid",
|
|
6771
|
+
...,
|
|
6772
|
+
help="Agent session UID, or cached A2A handle.",
|
|
6773
|
+
),
|
|
6774
|
+
target_agent_uid: str | None = typer.Option(
|
|
6775
|
+
None,
|
|
6776
|
+
"--target-agent-uid",
|
|
6777
|
+
help="Target agent UID used to create or resolve a handle on first use.",
|
|
6778
|
+
),
|
|
6779
|
+
name: str | None = typer.Option(
|
|
6780
|
+
None,
|
|
6781
|
+
"--name",
|
|
6782
|
+
help="Optional session name used only when resolving a handle with --target-agent-uid.",
|
|
6783
|
+
),
|
|
6784
|
+
parent_session_uid: str | None = typer.Option(
|
|
6785
|
+
None,
|
|
6786
|
+
"--parent-session-uid",
|
|
6787
|
+
help="Optional parent session UID used only when resolving a handle with --target-agent-uid.",
|
|
6682
6788
|
),
|
|
6683
6789
|
message: str | None = typer.Option(
|
|
6684
6790
|
None,
|
|
@@ -6690,6 +6796,16 @@ def agent_session_a2a_send_cmd(
|
|
|
6690
6796
|
"--message-file",
|
|
6691
6797
|
help="Path to a UTF-8 text file containing the A2A message.",
|
|
6692
6798
|
),
|
|
6799
|
+
files: list[pathlib.Path] | None = typer.Option(
|
|
6800
|
+
None,
|
|
6801
|
+
"--file",
|
|
6802
|
+
help="Inline file attachment to send as an A2A raw part.",
|
|
6803
|
+
),
|
|
6804
|
+
media_types: list[str] | None = typer.Option(
|
|
6805
|
+
None,
|
|
6806
|
+
"--media-type",
|
|
6807
|
+
help="Media type for each --file. Defaults to application/pdf.",
|
|
6808
|
+
),
|
|
6693
6809
|
strict_dictionary: bool = typer.Option(
|
|
6694
6810
|
False,
|
|
6695
6811
|
"--strict-dictionary",
|
|
@@ -6713,12 +6829,17 @@ def agent_session_a2a_send_cmd(
|
|
|
6713
6829
|
timeout: int | None = typer.Option(None, "--timeout", help="Request timeout in seconds"),
|
|
6714
6830
|
):
|
|
6715
6831
|
"""
|
|
6716
|
-
Send one standard A2A message to an existing
|
|
6832
|
+
Send one standard A2A message to an existing session UID or cached handle.
|
|
6717
6833
|
"""
|
|
6718
6834
|
_agent_session_a2a_send_impl(
|
|
6719
|
-
|
|
6835
|
+
agent_session_uid_or_handle=agent_session_uid_or_handle,
|
|
6836
|
+
target_agent_uid=target_agent_uid,
|
|
6837
|
+
name=name,
|
|
6838
|
+
parent_session_uid=parent_session_uid,
|
|
6720
6839
|
message=message,
|
|
6721
6840
|
message_file=message_file,
|
|
6841
|
+
files=files,
|
|
6842
|
+
media_types=media_types,
|
|
6722
6843
|
strict_dictionary=strict_dictionary,
|
|
6723
6844
|
json_repair_attempts=json_repair_attempts,
|
|
6724
6845
|
message_id=message_id,
|
|
@@ -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,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import base64
|
|
3
4
|
import datetime
|
|
4
5
|
import json
|
|
6
|
+
import pathlib
|
|
5
7
|
import time
|
|
6
8
|
import uuid
|
|
7
9
|
from enum import Enum
|
|
@@ -22,6 +24,7 @@ STANDARD_A2A_CONTENT_TYPE = "application/a2a+json"
|
|
|
22
24
|
STANDARD_A2A_OUTPUT_CONTRACT_METADATA_KEY = (
|
|
23
25
|
"https://mainsequence.ai/a2a/extensions/output-contract/v1"
|
|
24
26
|
)
|
|
27
|
+
MAX_INLINE_A2A_FILE_BYTES = 15 * 1024 * 1024
|
|
25
28
|
|
|
26
29
|
|
|
27
30
|
class AgentSessionStatus(str, Enum):
|
|
@@ -712,6 +715,7 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
|
|
|
712
715
|
*,
|
|
713
716
|
agent_session_uid: str,
|
|
714
717
|
message: str,
|
|
718
|
+
files: list[Any] | None = None,
|
|
715
719
|
message_id: str | None = None,
|
|
716
720
|
strict_dictionary: bool = False,
|
|
717
721
|
json_repair_attempts: int = 3,
|
|
@@ -727,12 +731,16 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
|
|
|
727
731
|
normalized_message_id = f"msg-{uuid.uuid4()}"
|
|
728
732
|
|
|
729
733
|
accepted_output_modes = ["application/json"] if strict_dictionary else ["text/plain"]
|
|
734
|
+
parts: list[dict[str, Any]] = [{"text": normalized_message}]
|
|
735
|
+
for file_spec in files or []:
|
|
736
|
+
parts.append(AgentSession._build_standard_a2a_raw_file_part(file_spec))
|
|
737
|
+
|
|
730
738
|
body: dict[str, Any] = {
|
|
731
739
|
"message": {
|
|
732
740
|
"messageId": normalized_message_id,
|
|
733
741
|
"role": "ROLE_USER",
|
|
734
742
|
"contextId": agent_session_uid,
|
|
735
|
-
"parts":
|
|
743
|
+
"parts": parts,
|
|
736
744
|
},
|
|
737
745
|
"configuration": {
|
|
738
746
|
"acceptedOutputModes": accepted_output_modes,
|
|
@@ -751,6 +759,46 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
|
|
|
751
759
|
}
|
|
752
760
|
return body
|
|
753
761
|
|
|
762
|
+
@staticmethod
|
|
763
|
+
def _build_standard_a2a_raw_file_part(file_spec: Any) -> dict[str, Any]:
|
|
764
|
+
if isinstance(file_spec, (str, pathlib.Path)):
|
|
765
|
+
path = pathlib.Path(file_spec).expanduser()
|
|
766
|
+
media_type = "application/pdf" if path.suffix.lower() == ".pdf" else ""
|
|
767
|
+
filename = path.name
|
|
768
|
+
elif isinstance(file_spec, dict):
|
|
769
|
+
raw_path = file_spec.get("path")
|
|
770
|
+
if raw_path is None:
|
|
771
|
+
raise ValueError("A2A file attachment requires a path")
|
|
772
|
+
path = pathlib.Path(str(raw_path)).expanduser()
|
|
773
|
+
media_type = str(
|
|
774
|
+
file_spec.get("media_type") or file_spec.get("mediaType") or ""
|
|
775
|
+
).strip()
|
|
776
|
+
if not media_type and path.suffix.lower() == ".pdf":
|
|
777
|
+
media_type = "application/pdf"
|
|
778
|
+
filename = str(file_spec.get("filename") or path.name).strip()
|
|
779
|
+
else:
|
|
780
|
+
raise TypeError("A2A file attachment must be a path or dict")
|
|
781
|
+
|
|
782
|
+
if not media_type:
|
|
783
|
+
raise ValueError(f"A2A file attachment '{path}' requires media_type")
|
|
784
|
+
if not filename:
|
|
785
|
+
raise ValueError(f"A2A file attachment '{path}' requires filename")
|
|
786
|
+
|
|
787
|
+
file_bytes = path.read_bytes()
|
|
788
|
+
if len(file_bytes) > MAX_INLINE_A2A_FILE_BYTES:
|
|
789
|
+
size_mib = len(file_bytes) / (1024 * 1024)
|
|
790
|
+
limit_mib = MAX_INLINE_A2A_FILE_BYTES / (1024 * 1024)
|
|
791
|
+
raise ValueError(
|
|
792
|
+
f"A2A attachment '{filename}' is {size_mib:.1f} MiB; "
|
|
793
|
+
f"inline attachments are limited to {limit_mib:.0f} MiB."
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
return {
|
|
797
|
+
"raw": base64.b64encode(file_bytes).decode("ascii"),
|
|
798
|
+
"filename": filename,
|
|
799
|
+
"mediaType": media_type,
|
|
800
|
+
}
|
|
801
|
+
|
|
754
802
|
@classmethod
|
|
755
803
|
def _post_standard_a2a_message(
|
|
756
804
|
cls,
|
|
@@ -793,6 +841,7 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
|
|
|
793
841
|
agent_session: str | AgentSession,
|
|
794
842
|
*,
|
|
795
843
|
message: str,
|
|
844
|
+
files: list[Any] | None = None,
|
|
796
845
|
message_id: str | None = None,
|
|
797
846
|
strict_dictionary: bool = False,
|
|
798
847
|
json_repair_attempts: int = 3,
|
|
@@ -806,6 +855,7 @@ class AgentSession(BaseObjectOrm, BasePydanticModel):
|
|
|
806
855
|
body = cls._build_standard_a2a_message_send_body(
|
|
807
856
|
agent_session_uid=session_uid,
|
|
808
857
|
message=message,
|
|
858
|
+
files=files,
|
|
809
859
|
message_id=message_id,
|
|
810
860
|
strict_dictionary=strict_dictionary,
|
|
811
861
|
json_repair_attempts=json_repair_attempts,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/dashboards/streamlit/SKILL.md
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/data_access/exploration/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/app_component.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/connections.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/tabular.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/contracts/ui.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/data_models.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/providers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/__init__.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/bindings.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/registry.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/widgets/table.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/command_center/workspace_snapshot.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/__init__.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/duckdb.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/client/data_sources_interfaces/sqlite.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/compiled_sql/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/build_operations.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/data_nodes.py
RENAMED
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/namespacing.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/persist_managers.py
RENAMED
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/data_nodes/run_operations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/mainsequence/meta_tables/sqlalchemy_contracts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_command_center_app_component_models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-4.4.22 → mainsequence-4.4.24}/tests/test_data_node_storage_dimension_queries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|