mainsequence 3.19.2__tar.gz → 3.19.3__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-3.19.2 → mainsequence-3.19.3}/PKG-INFO +2 -2
- {mainsequence-3.19.2 → mainsequence-3.19.3}/README.md +1 -1
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +350 -36
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/api.py +13 -7
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/cli.py +55 -49
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/models_tdag.py +50 -18
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/PKG-INFO +2 -2
- {mainsequence-3.19.2 → mainsequence-3.19.3}/pyproject.toml +1 -1
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_cli.py +71 -10
- {mainsequence-3.19.2 → mainsequence-3.19.3}/LICENSE +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/data_publishing/simple_tables/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/maintenance/local_journal/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/markets_platform/assets_and_translation/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/markets_platform/instruments_and_pricing/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/markets_platform/virtualfundbuilder/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/__main__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/bootstrap.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/config.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/cli/ui.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/base.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/client.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/data_sources_interfaces/timescale.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/models_simple_tables.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/models_user.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/models_vam.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/client/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/compute_validation.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/config.toml +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/favicon.png +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/image_1_base64.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/image_2_base64.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/image_3_base64.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/image_4_base64.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/image_5_base64.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/assets/logo.png +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/components/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/components/asset_select.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/components/date_settings.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/components/logged_user.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/core/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/core/theme.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/instruments/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/instruments/streamlit_form_factory.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/pages/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/dashboards/streamlit/scaffold.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/defaults.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/data_interface/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/data_interface/data_interface.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/base_instrument.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/bond.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/callability.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/interest_rate_swap.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/json_codec.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/position.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/instruments/ql_fields.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/interest_rates/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/interest_rates/etl/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/interest_rates/etl/curve_codec.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/interest_rates/etl/nodes.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/interest_rates/etl/registry.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/pricing_models/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/pricing_models/bond_pricer.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/pricing_models/indices.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/pricing_models/indices_builders.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/pricing_models/swap_pricer.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/settings.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/instruments/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/logconf.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/__main__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/base_persist_managers.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/config.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/configuration_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/build_operations.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/data_nodes.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/filters.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/namespacing.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/persist_managers.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/run_operations.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/data_nodes/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/filters.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/future_registry.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/pydantic_metadata.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/filters.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/persist_managers.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/schema.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/simple_tables/table_nodes.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/tdag/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/external_weights.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/intraday_trend.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/market_cap.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/mock_signal.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/data_nodes/portfolio_replicator.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/prices/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/prices/data_nodes.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/prices/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/rebalance_strategies/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/contrib/rebalance_strategies/rebalance_strategies.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/enums.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/portfolio_nodes.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/resource_factory/__init__.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/resource_factory/rebalance_factory.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/resource_factory/signal_factory.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence/virtualfundbuilder/utils.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/SOURCES.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/setup.cfg +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_auth_precedence.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_client.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_command_center_models.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_dependency_extras.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_filter_normalization.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_instruments.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_logconf.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_logged_user_components.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_run_configuration.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_simple_tables_configuration_hashing.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_simple_tables_persistence.py +0 -0
- {mainsequence-3.19.2 → mainsequence-3.19.3}/tests/test_workspace_snapshot.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mainsequence
|
|
3
|
-
Version: 3.19.
|
|
3
|
+
Version: 3.19.3
|
|
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
|
|
@@ -89,7 +89,7 @@ Requires-Dist: playwright; extra == "workspace-snapshots"
|
|
|
89
89
|
Dynamic: license-file
|
|
90
90
|
|
|
91
91
|
<p align="center">
|
|
92
|
-
<img src="https://main-sequence.
|
|
92
|
+
<img src="https://www.main-sequence.io/images/logos/MS_logo_long_black.png" alt="Main Sequence Logo" width="500"/>
|
|
93
93
|
</p>
|
|
94
94
|
|
|
95
95
|
# Main Sequence Python SDK
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://main-sequence.
|
|
2
|
+
<img src="https://www.main-sequence.io/images/logos/MS_logo_long_black.png" alt="Main Sequence Logo" width="500"/>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# Main Sequence Python SDK
|
|
@@ -104,6 +104,92 @@ Think in terms of these objects:
|
|
|
104
104
|
- saved widget or saved group:
|
|
105
105
|
import-layer snapshot/template, not a live linked widget instance inside the workspace
|
|
106
106
|
|
|
107
|
+
## Workspace JSON Model
|
|
108
|
+
|
|
109
|
+
Workspace JSON is the durable workspace definition. It is not a raw frontend state dump and it is
|
|
110
|
+
not a loaded runtime snapshot.
|
|
111
|
+
|
|
112
|
+
Portable export artifacts may use a wrapper:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"schema": "mainsequence.workspace",
|
|
117
|
+
"version": 1,
|
|
118
|
+
"exportedAt": "2026-05-07T00:00:00.000Z",
|
|
119
|
+
"workspace": {
|
|
120
|
+
"id": "workspace-example",
|
|
121
|
+
"title": "Example Workspace",
|
|
122
|
+
"description": "User-scoped workspace managed in Command Center.",
|
|
123
|
+
"type": "workspace",
|
|
124
|
+
"labels": [],
|
|
125
|
+
"category": "Custom",
|
|
126
|
+
"source": "user",
|
|
127
|
+
"layoutKind": "custom",
|
|
128
|
+
"grid": { "columns": 48, "rowHeight": 15, "gap": 8 },
|
|
129
|
+
"controls": {
|
|
130
|
+
"enabled": true,
|
|
131
|
+
"timeRange": {
|
|
132
|
+
"enabled": true,
|
|
133
|
+
"defaultRange": "24h",
|
|
134
|
+
"options": ["15m", "1h", "6h", "24h", "7d", "30d", "90d"]
|
|
135
|
+
},
|
|
136
|
+
"refresh": {
|
|
137
|
+
"enabled": true,
|
|
138
|
+
"defaultIntervalMs": 300000,
|
|
139
|
+
"intervals": [null, 30000, 60000, 300000, 600000, 3600000]
|
|
140
|
+
},
|
|
141
|
+
"actions": { "enabled": true, "share": false, "view": true }
|
|
142
|
+
},
|
|
143
|
+
"widgets": []
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Use the wrapper for portable artifacts. For direct workspace update commands, pass the writable
|
|
149
|
+
workspace payload shape expected by that command, not an arbitrary wrapper, unless the command
|
|
150
|
+
explicitly documents wrapper support.
|
|
151
|
+
|
|
152
|
+
Durable workspace JSON owns:
|
|
153
|
+
|
|
154
|
+
- workspace metadata, labels, category, source, layout kind, grid, and shared controls
|
|
155
|
+
- mounted widget instances and ordering
|
|
156
|
+
- widget `props`, `layout`, `position`, `bindings`, `managedBy`, `presentation`, and `row.children`
|
|
157
|
+
- connection/query configuration on source widgets when the source widget contract requires it
|
|
158
|
+
|
|
159
|
+
Durable workspace JSON does not own:
|
|
160
|
+
|
|
161
|
+
- current user-selected control values when the platform separates user state
|
|
162
|
+
- runtime/view state when the platform separates user state
|
|
163
|
+
- credentials, provider URLs, native socket details, or backend route fragments
|
|
164
|
+
- compiled or public runtime metadata generated by the platform
|
|
165
|
+
|
|
166
|
+
## Widget Instance Shape
|
|
167
|
+
|
|
168
|
+
Each mounted widget instance should resolve to this shape:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"id": "unique-instance-id",
|
|
173
|
+
"widgetId": "registered-widget-type-id",
|
|
174
|
+
"title": "Optional title",
|
|
175
|
+
"props": {},
|
|
176
|
+
"bindings": {},
|
|
177
|
+
"layout": { "cols": 12, "rows": 8 },
|
|
178
|
+
"position": { "x": 0, "y": 0 }
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Important fields:
|
|
183
|
+
|
|
184
|
+
- `id`: unique mounted instance id inside the workspace
|
|
185
|
+
- `widgetId`: registered widget type id, not a saved-widget id and not a mounted instance id
|
|
186
|
+
- `props`: durable widget configuration
|
|
187
|
+
- `runtimeState`: optional current runtime/view state, not durable source configuration
|
|
188
|
+
- `bindings`: target-owned graph edges from this widget's input ports to upstream output ports
|
|
189
|
+
- `managedBy`: marks hidden managed source widgets
|
|
190
|
+
- `presentation`: placement, rail visibility, chrome, and exposed field behavior
|
|
191
|
+
- `row.children`: nested widgets inside a row/container widget
|
|
192
|
+
|
|
107
193
|
## Inputs This Skill Needs
|
|
108
194
|
|
|
109
195
|
Before writing or mutating a workspace, collect or infer:
|
|
@@ -286,27 +372,133 @@ If the payload shape is not defined by those sources and cannot be verified, sto
|
|
|
286
372
|
|
|
287
373
|
### 3.1 Resolve connection-backed data before mounting consumers
|
|
288
374
|
|
|
289
|
-
|
|
375
|
+
Connections are backend-owned data resources. Workspace consumers should not store connection
|
|
376
|
+
details directly unless their registered widget contract explicitly supports embedded managed source
|
|
377
|
+
props.
|
|
290
378
|
|
|
291
|
-
|
|
292
|
-
2. verify the selected connection instance exists and is usable
|
|
293
|
-
3. verify the connection type and `queryModelId`
|
|
294
|
-
4. verify the typed query payload
|
|
295
|
-
5. verify the published output contract
|
|
296
|
-
6. add a Tabular Transform widget if analytical reshaping is required
|
|
297
|
-
7. bind consumers to the source or transform `dataset` output
|
|
379
|
+
Prefer explicit source widgets:
|
|
298
380
|
|
|
299
|
-
|
|
300
|
-
connection
|
|
381
|
+
- `connection-query` for request/response datasets
|
|
382
|
+
- `connection-stream-query` for streaming or incremental paths
|
|
383
|
+
- `tabular-transform` when analytical reshaping is needed before presentation
|
|
301
384
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
through an Adapter from API connection first, then use an explicit transform when analytical
|
|
305
|
-
reshaping is still required.
|
|
385
|
+
One source widget can feed several consumers. Reuse one source when the same query drives several
|
|
386
|
+
tables, charts, statistics, curves, or agent contexts.
|
|
306
387
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
388
|
+
Before mounting table, chart, statistic, curve, or similar data consumers:
|
|
389
|
+
|
|
390
|
+
1. identify the source widget
|
|
391
|
+
2. verify the selected connection instance exists and is usable
|
|
392
|
+
3. verify `connectionRef.id` is real and backend-owned
|
|
393
|
+
4. verify `connectionRef.typeId` matches the connection type
|
|
394
|
+
5. verify `queryModelId` matches `query.kind`
|
|
395
|
+
6. verify the typed query payload matches the selected connection type and query model
|
|
396
|
+
7. verify the published output contract
|
|
397
|
+
8. add a Tabular Transform widget if analytical reshaping is required
|
|
398
|
+
9. bind consumers to the source or transform output through target-owned `bindings`
|
|
399
|
+
|
|
400
|
+
Do not store credentials, provider URLs, native route fragments, backend route fragments, provider
|
|
401
|
+
ids, or mutable connection display labels as authoritative widget props.
|
|
402
|
+
|
|
403
|
+
Request/response source props:
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
{
|
|
407
|
+
"connectionRef": { "id": 123, "typeId": "mainsequence.simple-table" },
|
|
408
|
+
"queryModelId": "simple-table-sql",
|
|
409
|
+
"query": {
|
|
410
|
+
"kind": "simple-table-sql",
|
|
411
|
+
"sql": "select * from {{simple_table}} limit 500"
|
|
412
|
+
},
|
|
413
|
+
"timeRangeMode": "dashboard",
|
|
414
|
+
"variables": {},
|
|
415
|
+
"maxRows": 500
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Incremental request/response props:
|
|
420
|
+
|
|
421
|
+
```json
|
|
422
|
+
{
|
|
423
|
+
"incrementalRefreshMode": "incremental",
|
|
424
|
+
"incrementalTimeField": "timestamp",
|
|
425
|
+
"incrementalMergeKeyFields": ["symbol", "timestamp"],
|
|
426
|
+
"incrementalOverlapMs": 60000,
|
|
427
|
+
"incrementalRetentionMs": 86400000,
|
|
428
|
+
"incrementalDedupePolicy": "latest"
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
Stream source props:
|
|
433
|
+
|
|
434
|
+
```json
|
|
435
|
+
{
|
|
436
|
+
"connectionRef": { "id": 123, "typeId": "binance.market-data" },
|
|
437
|
+
"queryModelId": "ticker-stream",
|
|
438
|
+
"query": {
|
|
439
|
+
"kind": "ticker-stream",
|
|
440
|
+
"symbols": ["BTCUSDT", "ETHUSDT"]
|
|
441
|
+
},
|
|
442
|
+
"timeRangeMode": "none",
|
|
443
|
+
"mergeKeyFields": ["symbol"],
|
|
444
|
+
"retentionMaxRows": 1000
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Connection source rules:
|
|
449
|
+
|
|
450
|
+
- use stream widgets only when the query model advertises stream support
|
|
451
|
+
- configure retention and merge keys explicitly when the consumer expects bounded live state
|
|
452
|
+
- incremental refresh requires a time-range-aware query model and stable time and identity columns
|
|
453
|
+
- `incrementalTimeField` must exist in the returned frame
|
|
454
|
+
- `incrementalMergeKeyFields` must identify stable rows
|
|
455
|
+
- generic tabular consumers must receive `core.tabular_frame@v1`
|
|
456
|
+
- if the upstream connection returns raw arrays, paginated JSON, nested provider payloads, or other
|
|
457
|
+
ad hoc records, normalize through an Adapter from API connection first, then use an explicit
|
|
458
|
+
transform when analytical reshaping is still required
|
|
459
|
+
- when a project API or AppComponent legitimately returns a full canonical frame, ground the
|
|
460
|
+
contract against `mainsequence.client.command_center.data_models.TabularFrameResponse`
|
|
461
|
+
- source-specific runtime details belong in `source.context`, not top-level widget payload fields
|
|
462
|
+
|
|
463
|
+
### 3.2 Historical and incremental lanes
|
|
464
|
+
|
|
465
|
+
Modern tabular consumers use explicit role inputs:
|
|
466
|
+
|
|
467
|
+
- `seedData`: retained baseline or historical dataset
|
|
468
|
+
- `liveUpdates`: incremental publication lane
|
|
469
|
+
|
|
470
|
+
Source outputs:
|
|
471
|
+
|
|
472
|
+
- `connection-query.dataset`: retained `core.tabular_frame@v1` frame for historical consumers
|
|
473
|
+
- `connection-query.updates`: incremental output when incremental refresh is active
|
|
474
|
+
- `connection-stream-query.dataset`: retained compatibility frame
|
|
475
|
+
- `connection-stream-query.updates`: seed/update publication stream
|
|
476
|
+
|
|
477
|
+
Canonical binding shape:
|
|
478
|
+
|
|
479
|
+
```json
|
|
480
|
+
"bindings": {
|
|
481
|
+
"seedData": {
|
|
482
|
+
"sourceWidgetId": "historical-source",
|
|
483
|
+
"sourceOutputId": "dataset"
|
|
484
|
+
},
|
|
485
|
+
"liveUpdates": {
|
|
486
|
+
"sourceWidgetId": "stream-source",
|
|
487
|
+
"sourceOutputId": "updates"
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Rules:
|
|
493
|
+
|
|
494
|
+
- historical/request-response data uses `dataset -> seedData`
|
|
495
|
+
- live or incremental data uses `updates -> liveUpdates`
|
|
496
|
+
- `sourceData` is legacy or compatibility input; use it only when the widget contract requires it
|
|
497
|
+
- do not send stream `dataset` to `liveUpdates`
|
|
498
|
+
- do not send request/response `dataset` to `liveUpdates`
|
|
499
|
+
- generic tabular consumers must receive `core.tabular_frame@v1`
|
|
500
|
+
- raw arrays, paginated JSON, or nested provider payloads must be normalized before reaching generic
|
|
501
|
+
consumers
|
|
310
502
|
|
|
311
503
|
### 4. Shared workspace state and current-user state are different
|
|
312
504
|
|
|
@@ -389,26 +581,51 @@ Prefer:
|
|
|
389
581
|
Bindings are canonical instance-level graph edges. They live on the target widget instance in
|
|
390
582
|
`bindings`, not in `props`, and not in widget-type metadata.
|
|
391
583
|
|
|
392
|
-
One binding is always
|
|
584
|
+
One binding is always:
|
|
393
585
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
586
|
+
```text
|
|
587
|
+
source widget output port -> target widget input port
|
|
588
|
+
```
|
|
397
589
|
|
|
398
590
|
Persisted shape:
|
|
399
591
|
|
|
400
592
|
- `bindings[inputId] = WidgetPortBinding`
|
|
401
593
|
- `bindings[inputId] = WidgetPortBinding[]` when the target input declares `cardinality: "many"`
|
|
402
594
|
|
|
403
|
-
|
|
595
|
+
Minimal `WidgetPortBinding`:
|
|
404
596
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
-
|
|
597
|
+
```json
|
|
598
|
+
{
|
|
599
|
+
"sourceWidgetId": "prices-source",
|
|
600
|
+
"sourceOutputId": "dataset"
|
|
601
|
+
}
|
|
602
|
+
```
|
|
408
603
|
|
|
409
|
-
|
|
604
|
+
Binding with transform steps:
|
|
605
|
+
|
|
606
|
+
```json
|
|
607
|
+
{
|
|
608
|
+
"sourceWidgetId": "source-widget",
|
|
609
|
+
"sourceOutputId": "agent-context",
|
|
610
|
+
"transformSteps": [
|
|
611
|
+
{ "id": "extract-path", "path": ["summary"], "contractId": "core.value.string@v1" }
|
|
612
|
+
]
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
Treat ordered `transformSteps` as canonical. Legacy `transformId`, `transformPath`, and
|
|
410
617
|
`transformContractId` may still appear only as backward-compatible mirrors for older persisted
|
|
411
|
-
workspaces.
|
|
618
|
+
workspaces. Do not author those legacy fields in new workspace JSON.
|
|
619
|
+
|
|
620
|
+
Supported lightweight transform steps:
|
|
621
|
+
|
|
622
|
+
- `select-array-item`
|
|
623
|
+
- `extract-path`
|
|
624
|
+
|
|
625
|
+
Binding transforms are only for selecting one array item or extracting a nested field before
|
|
626
|
+
compatibility is evaluated. Do not use binding transforms for analytical reshaping. Use a
|
|
627
|
+
`tabular-transform` widget for projection, aggregate, pivot, unpivot, filtering, joining, or other
|
|
628
|
+
visible data operations.
|
|
412
629
|
|
|
413
630
|
Do not describe bindings loosely as “widget A uses widget B”. In this platform, bindings are always
|
|
414
631
|
port-to-port:
|
|
@@ -424,17 +641,16 @@ Resolve bindings from the target widget outward:
|
|
|
424
641
|
2. For each target input, record:
|
|
425
642
|
- `inputId`
|
|
426
643
|
- accepted contracts
|
|
644
|
+
- `acceptedOutputIds`
|
|
427
645
|
- `required`
|
|
428
646
|
- `cardinality`
|
|
429
647
|
- `effects`
|
|
430
648
|
3. Choose a source widget instance that actually publishes the required output id.
|
|
431
|
-
4.
|
|
649
|
+
4. Validate the source output id against `acceptedOutputIds` when the target input declares it.
|
|
650
|
+
5. If the source output is structured JSON or an array, resolve binding transforms before contract
|
|
432
651
|
validation.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
- `extract-path`
|
|
436
|
-
5. Validate the transformed contract against the target input `accepts`.
|
|
437
|
-
6. Treat the binding as usable only when the resolved status is `valid`.
|
|
652
|
+
6. Validate the transformed contract against the target input `accepts`.
|
|
653
|
+
7. Treat the binding as usable only when the resolved status is `valid`.
|
|
438
654
|
|
|
439
655
|
A binding can exist in workspace JSON and still be unusable at runtime. The runtime may resolve a
|
|
440
656
|
binding as:
|
|
@@ -461,6 +677,10 @@ Runtime and persistence rules:
|
|
|
461
677
|
- binding changes clear that target widget's `runtimeState`
|
|
462
678
|
- the widget settings `Bindings` tab and the workspace graph editor edit the same canonical binding model
|
|
463
679
|
- for `cardinality: "many"` inputs, preserve order and store an array of bindings for that input id
|
|
680
|
+
- for `cardinality: "one"` inputs, store a single binding object, not an array
|
|
681
|
+
- do not bind a widget to itself
|
|
682
|
+
- graph/editor interactions may be dragged in either visual direction, but persisted JSON is always
|
|
683
|
+
normalized back to target-owned bindings
|
|
464
684
|
|
|
465
685
|
Dynamic-IO rule:
|
|
466
686
|
|
|
@@ -471,6 +691,10 @@ Dynamic-IO rule:
|
|
|
471
691
|
Concrete examples:
|
|
472
692
|
|
|
473
693
|
- a Connection Query widget publishes `dataset`; a Tabular Transform widget can consume and republish `dataset`
|
|
694
|
+
- modern tabular consumers use explicit role inputs:
|
|
695
|
+
- historical/request-response data binds `dataset -> seedData`
|
|
696
|
+
- live or incremental data binds `updates -> liveUpdates`
|
|
697
|
+
- legacy `sourceData` should appear only when the widget contract still requires it
|
|
474
698
|
- `main-sequence-ai-agent-terminal` accepts one input with `cardinality: "many"`, so several
|
|
475
699
|
upstream widget contexts can feed one terminal
|
|
476
700
|
- widgets that implement `buildAgentSnapshot(...)` may also publish a synthetic `agent-context`
|
|
@@ -483,16 +707,85 @@ Review rule:
|
|
|
483
707
|
- target input id
|
|
484
708
|
- source widget instance id
|
|
485
709
|
- source output id
|
|
710
|
+
- accepted output id constraint, if any
|
|
486
711
|
- transform steps, if any
|
|
487
712
|
- final resolved contract
|
|
488
713
|
- final resolved status
|
|
489
714
|
|
|
715
|
+
## Managed Connection Sources
|
|
716
|
+
|
|
717
|
+
Some consumers support embedded connection authoring. Treat this as UI convenience, not a shortcut
|
|
718
|
+
around the source-widget model.
|
|
719
|
+
|
|
720
|
+
The persisted model still has:
|
|
721
|
+
|
|
722
|
+
- a visible owner widget, for example `graph`
|
|
723
|
+
- a hidden source widget, either `connection-query` or `connection-stream-query`
|
|
724
|
+
- `managedBy: { "ownerInstanceId": "<owner-id>", "role": "embedded-connection-source" }` on the hidden source widget
|
|
725
|
+
- a normal binding from the owner input to the hidden source output
|
|
726
|
+
|
|
727
|
+
Owner widget:
|
|
728
|
+
|
|
729
|
+
```json
|
|
730
|
+
{
|
|
731
|
+
"id": "graph-1",
|
|
732
|
+
"widgetId": "graph",
|
|
733
|
+
"props": {
|
|
734
|
+
"graphSourceMode": "connection",
|
|
735
|
+
"embeddedConnectionQuery": {
|
|
736
|
+
"connectionRef": { "id": 123, "typeId": "mainsequence.simple-table" },
|
|
737
|
+
"queryModelId": "simple-table-sql",
|
|
738
|
+
"query": { "kind": "simple-table-sql", "sql": "select * from {{simple_table}}" }
|
|
739
|
+
}
|
|
740
|
+
},
|
|
741
|
+
"bindings": {
|
|
742
|
+
"seedData": {
|
|
743
|
+
"sourceWidgetId": "graph-1-source",
|
|
744
|
+
"sourceOutputId": "dataset"
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Hidden source widget:
|
|
751
|
+
|
|
752
|
+
```json
|
|
753
|
+
{
|
|
754
|
+
"id": "graph-1-source",
|
|
755
|
+
"widgetId": "connection-query",
|
|
756
|
+
"title": "Graph Source",
|
|
757
|
+
"props": {
|
|
758
|
+
"connectionRef": { "id": 123, "typeId": "mainsequence.simple-table" },
|
|
759
|
+
"queryModelId": "simple-table-sql",
|
|
760
|
+
"query": { "kind": "simple-table-sql", "sql": "select * from {{simple_table}}" }
|
|
761
|
+
},
|
|
762
|
+
"managedBy": {
|
|
763
|
+
"ownerInstanceId": "graph-1",
|
|
764
|
+
"role": "embedded-connection-source"
|
|
765
|
+
},
|
|
766
|
+
"presentation": {
|
|
767
|
+
"placementMode": "sidebar",
|
|
768
|
+
"railVisibility": "hidden"
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
Managed stream sources bind hidden source `updates` to owner `liveUpdates`.
|
|
774
|
+
|
|
775
|
+
Rules:
|
|
776
|
+
|
|
777
|
+
- keep owner props, hidden source props, `managedBy`, and bindings aligned
|
|
778
|
+
- do not leave orphan hidden source widgets
|
|
779
|
+
- do not point `managedBy.ownerInstanceId` at a missing owner
|
|
780
|
+
- prefer explicit visible source widgets when they make the workspace easier to inspect or reuse
|
|
781
|
+
|
|
490
782
|
|
|
491
783
|
## Review Rules
|
|
492
784
|
|
|
493
785
|
When reviewing a workspace task, look for:
|
|
494
786
|
|
|
495
787
|
- guessed widget payloads
|
|
788
|
+
- guessed input ids or output ids
|
|
496
789
|
- widget work that skipped CLI registry verification
|
|
497
790
|
- widget work that skipped SDK client model review when one exists
|
|
498
791
|
- unknown or unverified `widgetId` values
|
|
@@ -500,12 +793,21 @@ When reviewing a workspace task, look for:
|
|
|
500
793
|
- workspace mutation attempted without first exporting the current workspace JSON
|
|
501
794
|
- widget payloads changed without saving versioned JSON drafts under `workspaces/widgets/`
|
|
502
795
|
- workspace-wide rewrites for one-widget changes
|
|
503
|
-
-
|
|
796
|
+
- current-user runtime state mixed into durable workspace JSON accidentally
|
|
504
797
|
- runtime ownership violations such as consumer widgets inventing canonical fetch paths
|
|
505
798
|
- unresolved external resource ids
|
|
506
|
-
- connection-backed consumers missing a source or transform
|
|
799
|
+
- connection-backed consumers missing a source widget or required transform widget
|
|
507
800
|
- generic tabular consumers bound to raw JSON instead of `core.tabular_frame@v1`
|
|
508
801
|
- full canonical tabular payloads that drift from `TabularFrameResponse`
|
|
802
|
+
- bindings authored in `props` instead of `widget.bindings`
|
|
803
|
+
- bindings placed on the source widget instead of the target widget
|
|
804
|
+
- bindings that ignore `acceptedOutputIds`
|
|
805
|
+
- `dataset -> liveUpdates`
|
|
806
|
+
- stream `dataset` used for live data instead of stream `updates`
|
|
807
|
+
- stream or incremental outputs wired to the wrong role input
|
|
808
|
+
- binding transforms used for analytical reshaping instead of a transform widget
|
|
809
|
+
- hidden managed source widgets missing their owner widget
|
|
810
|
+
- stale `managedBy.ownerInstanceId` values
|
|
509
811
|
- widget trees using structures not supported by the Main Sequence repository source models
|
|
510
812
|
|
|
511
813
|
## Validation Checklist
|
|
@@ -523,13 +825,25 @@ Do not claim success until you have checked:
|
|
|
523
825
|
- versioned workspace/widget JSON files were preserved pending user acceptance
|
|
524
826
|
- widget detail was reviewed for `widgetVersion`, configuration, runtime, IO, capabilities, agent hints, and examples
|
|
525
827
|
- the relevant SDK client model was reviewed when one exists
|
|
526
|
-
-
|
|
828
|
+
- every source widget has a valid connection ref, query model id, typed query payload, and output contract
|
|
829
|
+
- every `query.kind` matches `queryModelId`
|
|
527
830
|
- generic tabular consumers receive `core.tabular_frame@v1`
|
|
831
|
+
- every binding references an existing source widget and output id
|
|
832
|
+
- every binding targets an existing input id
|
|
833
|
+
- every binding matches the target input contract
|
|
834
|
+
- every binding respects `acceptedOutputIds` when declared
|
|
835
|
+
- `cardinality: "many"` bindings preserve order as arrays
|
|
836
|
+
- `cardinality: "one"` bindings are single binding objects
|
|
837
|
+
- historical/request-response data uses `dataset -> seedData` when the widget exposes role inputs
|
|
838
|
+
- live or incremental data uses `updates -> liveUpdates` when the widget exposes role inputs
|
|
528
839
|
- full canonical tabular frames match `TabularFrameResponse`
|
|
529
840
|
- widget ids and widget instance ids are correct
|
|
530
841
|
- any mounted widget that depends on a project API points to a FastAPI project resource that already exists
|
|
531
842
|
- any mounted widget that depends on a project API points to a FastAPI `ResourceRelease` that already exists
|
|
532
843
|
- local payload shape was reconciled against the verified widget id, widget-detail contract, and SDK model
|
|
844
|
+
- managed sources have valid `managedBy.ownerInstanceId` values
|
|
845
|
+
- owner widgets and hidden managed source widgets agree on connection/query props
|
|
846
|
+
- no credentials, native URLs, or backend route fragments are embedded in workspace JSON
|
|
533
847
|
- the chosen mutation mode is correct:
|
|
534
848
|
- full workspace update
|
|
535
849
|
- widget-scoped mutation
|
|
@@ -591,27 +591,33 @@ def get_projects() -> list[dict]:
|
|
|
591
591
|
return data.get("results") or []
|
|
592
592
|
|
|
593
593
|
|
|
594
|
-
def
|
|
594
|
+
def search_projects(
|
|
595
|
+
q: str,
|
|
595
596
|
*,
|
|
597
|
+
limit: int = 20,
|
|
596
598
|
timeout: int | None = None,
|
|
597
|
-
) -> list[str]:
|
|
599
|
+
) -> list[dict[str, Any]]:
|
|
598
600
|
"""
|
|
599
|
-
|
|
601
|
+
Search projects visible to the authenticated user via SDK client model.
|
|
600
602
|
|
|
601
603
|
Single source of truth:
|
|
602
|
-
- delegates payload parsing to `Project.
|
|
604
|
+
- delegates payload parsing to `Project.quick_search()`
|
|
603
605
|
"""
|
|
604
606
|
try:
|
|
605
607
|
payload = _run_sdk_model_operation(
|
|
606
608
|
module_name="mainsequence.client.models_tdag",
|
|
607
609
|
class_name="Project",
|
|
608
|
-
operation=lambda ClientProject: ClientProject.
|
|
610
|
+
operation=lambda ClientProject: ClientProject.quick_search(
|
|
611
|
+
q=q,
|
|
612
|
+
limit=limit,
|
|
613
|
+
timeout=timeout,
|
|
614
|
+
),
|
|
609
615
|
)
|
|
610
|
-
return [
|
|
616
|
+
return [_sdk_object_to_dict(item) for item in list(payload or [])]
|
|
611
617
|
except Exception as e:
|
|
612
618
|
if isinstance(e, (ApiError, NotLoggedIn)):
|
|
613
619
|
raise
|
|
614
|
-
raise ApiError(f"
|
|
620
|
+
raise ApiError(f"Project search failed: {e}") from e
|
|
615
621
|
|
|
616
622
|
|
|
617
623
|
def validate_project_name(
|
|
@@ -137,7 +137,6 @@ from .api import (
|
|
|
137
137
|
list_github_organizations,
|
|
138
138
|
list_market_asset_translation_tables,
|
|
139
139
|
list_market_portfolios,
|
|
140
|
-
list_org_project_names,
|
|
141
140
|
list_organization_teams,
|
|
142
141
|
list_project_base_images,
|
|
143
142
|
list_project_images,
|
|
@@ -188,6 +187,7 @@ from .api import (
|
|
|
188
187
|
run_project_job,
|
|
189
188
|
safe_slug,
|
|
190
189
|
schedule_batch_project_jobs,
|
|
190
|
+
search_projects,
|
|
191
191
|
semantic_search_agents,
|
|
192
192
|
start_agent_new_session,
|
|
193
193
|
sync_project_after_commit,
|
|
@@ -2570,54 +2570,6 @@ def user_show():
|
|
|
2570
2570
|
)
|
|
2571
2571
|
|
|
2572
2572
|
|
|
2573
|
-
@organization.command("project-names")
|
|
2574
|
-
def organization_project_names_cmd(
|
|
2575
|
-
timeout: int | None = typer.Option(None, "--timeout", help="Request timeout in seconds"),
|
|
2576
|
-
):
|
|
2577
|
-
"""
|
|
2578
|
-
List project names visible to the authenticated user's organization.
|
|
2579
|
-
|
|
2580
|
-
Uses SDK client `Project.get_org_project_names()` as the single source of truth.
|
|
2581
|
-
|
|
2582
|
-
Examples
|
|
2583
|
-
--------
|
|
2584
|
-
```bash
|
|
2585
|
-
mainsequence organization project-names
|
|
2586
|
-
mainsequence organization project-names --timeout 60
|
|
2587
|
-
```
|
|
2588
|
-
"""
|
|
2589
|
-
_require_login()
|
|
2590
|
-
|
|
2591
|
-
try:
|
|
2592
|
-
project_names = list_org_project_names(timeout=timeout)
|
|
2593
|
-
except ApiError as e:
|
|
2594
|
-
error(f"Organization project names fetch failed: {e}")
|
|
2595
|
-
raise typer.Exit(1) from e
|
|
2596
|
-
|
|
2597
|
-
if _emit_json(project_names):
|
|
2598
|
-
return
|
|
2599
|
-
|
|
2600
|
-
if project_names:
|
|
2601
|
-
print_table(
|
|
2602
|
-
"Organization Project Names",
|
|
2603
|
-
["Project Name"],
|
|
2604
|
-
[[project_name] for project_name in project_names],
|
|
2605
|
-
)
|
|
2606
|
-
else:
|
|
2607
|
-
info("No organization-visible project names.")
|
|
2608
|
-
info(f"Total organization-visible project names: {len(project_names)}")
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
@organization.command("project_names", hidden=True)
|
|
2612
|
-
def organization_project_names_alias_cmd(
|
|
2613
|
-
timeout: int | None = typer.Option(None, "--timeout", help="Request timeout in seconds"),
|
|
2614
|
-
):
|
|
2615
|
-
"""
|
|
2616
|
-
Backward-compatible alias for `mainsequence organization project-names`.
|
|
2617
|
-
"""
|
|
2618
|
-
organization_project_names_cmd(timeout=timeout)
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
2573
|
@organization.command("github-organizations")
|
|
2622
2574
|
def organization_github_organizations_cmd():
|
|
2623
2575
|
"""
|
|
@@ -7945,6 +7897,60 @@ def project_validate_name_cmd(
|
|
|
7945
7897
|
raise typer.Exit(1)
|
|
7946
7898
|
|
|
7947
7899
|
|
|
7900
|
+
@project.command("search")
|
|
7901
|
+
def project_search_cmd(
|
|
7902
|
+
q: str = typer.Argument(..., help="Project search query. Minimum 3 characters."),
|
|
7903
|
+
limit: int = typer.Option(20, "--limit", min=1, max=100, help="Maximum number of matches to return."),
|
|
7904
|
+
timeout: int | None = typer.Option(None, "--timeout", help="Request timeout in seconds"),
|
|
7905
|
+
):
|
|
7906
|
+
"""
|
|
7907
|
+
Search projects visible to the authenticated user.
|
|
7908
|
+
|
|
7909
|
+
Uses SDK client `Project.quick_search()` as the single source of truth.
|
|
7910
|
+
|
|
7911
|
+
Examples
|
|
7912
|
+
--------
|
|
7913
|
+
```bash
|
|
7914
|
+
mainsequence project search "tutorial"
|
|
7915
|
+
mainsequence project search "rates" --limit 10
|
|
7916
|
+
mainsequence project search "161"
|
|
7917
|
+
```
|
|
7918
|
+
"""
|
|
7919
|
+
_require_login()
|
|
7920
|
+
|
|
7921
|
+
normalized_query = (q or "").strip()
|
|
7922
|
+
if len(normalized_query) < 3:
|
|
7923
|
+
error("Project search failed: Query must contain at least 3 characters.")
|
|
7924
|
+
raise typer.Exit(1)
|
|
7925
|
+
|
|
7926
|
+
try:
|
|
7927
|
+
projects = search_projects(normalized_query, limit=limit, timeout=timeout)
|
|
7928
|
+
except ApiError as e:
|
|
7929
|
+
error(f"Project search failed: {e}")
|
|
7930
|
+
raise typer.Exit(1) from e
|
|
7931
|
+
|
|
7932
|
+
if _emit_json(projects):
|
|
7933
|
+
return
|
|
7934
|
+
|
|
7935
|
+
if projects:
|
|
7936
|
+
print_table(
|
|
7937
|
+
"Project Search Results",
|
|
7938
|
+
["ID", "Project Name", "Repository Branch", "Cluster ID"],
|
|
7939
|
+
[
|
|
7940
|
+
[
|
|
7941
|
+
str(project.get("id") or "-"),
|
|
7942
|
+
str(project.get("project_name") or "-"),
|
|
7943
|
+
str(project.get("repository_branch") or "-"),
|
|
7944
|
+
str(project.get("cluster_id") or "-"),
|
|
7945
|
+
]
|
|
7946
|
+
for project in projects
|
|
7947
|
+
],
|
|
7948
|
+
)
|
|
7949
|
+
else:
|
|
7950
|
+
info("No projects matched the search.")
|
|
7951
|
+
info(f'Project search matches for "{normalized_query}": {len(projects)}')
|
|
7952
|
+
|
|
7953
|
+
|
|
7948
7954
|
@project.command("validate_name", hidden=True)
|
|
7949
7955
|
def project_validate_name_alias_cmd(
|
|
7950
7956
|
project_name: str = typer.Argument(..., help="Project name to validate."),
|